Sign In

@paretools/shared

Package Overview
Dependencies
Maintainers
1
Versions
35
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@paretools/shared - npm Package Compare versions

Comparing version
0.5.0
to
0.6.0
+20
dist/limits.d.ts
/**
* Shared input-validation limits for all Pare MCP servers.
*
* These provide defense-in-depth against DoS via extremely long inputs.
* Applied to Zod input schemas with `.max()` — output schemas are NOT
* constrained because their size is determined by tool output, not user input.
*/
export declare const INPUT_LIMITS: {
/** Maximum length for any general string parameter (64 KB). */
readonly STRING_MAX: 65536;
/** Maximum items in any array parameter. */
readonly ARRAY_MAX: 1000;
/** Maximum length for file system paths. */
readonly PATH_MAX: 4096;
/** Maximum length for commit messages (generous to allow long messages). */
readonly MESSAGE_MAX: 72000;
/** Maximum length for short identifiers (branch names, package names, etc.). */
readonly SHORT_STRING_MAX: 255;
};
//# sourceMappingURL=limits.d.ts.map
{"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../src/limits.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,YAAY;IACvB,+DAA+D;;IAG/D,4CAA4C;;IAG5C,4CAA4C;;IAG5C,4EAA4E;;IAG5E,gFAAgF;;CAExE,CAAC"}
/**
* Shared input-validation limits for all Pare MCP servers.
*
* These provide defense-in-depth against DoS via extremely long inputs.
* Applied to Zod input schemas with `.max()` — output schemas are NOT
* constrained because their size is determined by tool output, not user input.
*/
export const INPUT_LIMITS = {
/** Maximum length for any general string parameter (64 KB). */
STRING_MAX: 65_536,
/** Maximum items in any array parameter. */
ARRAY_MAX: 1_000,
/** Maximum length for file system paths. */
PATH_MAX: 4_096,
/** Maximum length for commit messages (generous to allow long messages). */
MESSAGE_MAX: 72_000,
/** Maximum length for short identifiers (branch names, package names, etc.). */
SHORT_STRING_MAX: 255,
};
//# sourceMappingURL=limits.js.map
{"version":3,"file":"limits.js","sourceRoot":"","sources":["../src/limits.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,+DAA+D;IAC/D,UAAU,EAAE,MAAM;IAElB,4CAA4C;IAC5C,SAAS,EAAE,KAAK;IAEhB,4CAA4C;IAC5C,QAAQ,EAAE,KAAK;IAEf,4EAA4E;IAC5E,WAAW,EAAE,MAAM;IAEnB,gFAAgF;IAChF,gBAAgB,EAAE,GAAG;CACb,CAAC"}
/**
* Sanitizes error output by replacing sensitive filesystem paths with
* home-relative equivalents. This prevents leaking usernames and absolute
* home directory paths in error messages returned to MCP clients.
*
* Replacements:
* /home/<user>/... → ~/...
* /Users/<user>/... → ~/...
* /root/... → ~/...
* C:\Users\<user>\... → ~\...
*/
export declare function sanitizeErrorOutput(text: string): string;
//# sourceMappingURL=sanitize.d.ts.map
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAcxD"}
/**
* Sanitizes error output by replacing sensitive filesystem paths with
* home-relative equivalents. This prevents leaking usernames and absolute
* home directory paths in error messages returned to MCP clients.
*
* Replacements:
* /home/<user>/... → ~/...
* /Users/<user>/... → ~/...
* /root/... → ~/...
* C:\Users\<user>\... → ~\...
*/
export function sanitizeErrorOutput(text) {
// Unix: /home/<username>/rest → ~/rest
let result = text.replace(/\/home\/[^/\s]+\//g, "~/");
// macOS: /Users/<username>/rest → ~/rest
result = result.replace(/\/Users\/[^/\s]+\//g, "~/");
// Unix: /root/rest → ~/rest
result = result.replace(/\/root\//g, "~/");
// Windows: C:\Users\<username>\rest → ~\rest (with escaped or literal backslashes)
result = result.replace(/[A-Z]:\\Users\\[^\\:\s]+\\/gi, "~\\");
return result;
}
//# sourceMappingURL=sanitize.js.map
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,uCAAuC;IACvC,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC;IAEtD,yCAAyC;IACzC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAC;IAErD,4BAA4B;IAC5B,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAE3C,mFAAmF;IACnF,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;IAE/D,OAAO,MAAM,CAAC;AAChB,CAAC"}
+4
-2

@@ -1,6 +0,8 @@

export { dualOutput } from "./output.js";
export { run, type RunResult, type RunOptions } from "./runner.js";
export { dualOutput, estimateTokens, compactDualOutput } from "./output.js";
export { run, escapeCmdArg, type RunResult, type RunOptions } from "./runner.js";
export { stripAnsi } from "./ansi.js";
export { assertNoFlagInjection, assertAllowedCommand } from "./validation.js";
export { INPUT_LIMITS } from "./limits.js";
export { sanitizeErrorOutput } from "./sanitize.js";
export type { ToolOutput } from "./types.js";
//# sourceMappingURL=index.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,GAAG,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC9E,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}

@@ -1,5 +0,7 @@

export { dualOutput } from "./output.js";
export { run } from "./runner.js";
export { dualOutput, estimateTokens, compactDualOutput } from "./output.js";
export { run, escapeCmdArg } from "./runner.js";
export { stripAnsi } from "./ansi.js";
export { assertNoFlagInjection, assertAllowedCommand } from "./validation.js";
export { INPUT_LIMITS } from "./limits.js";
export { sanitizeErrorOutput } from "./sanitize.js";
//# sourceMappingURL=index.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,GAAG,EAAmC,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,GAAG,EAAE,YAAY,EAAmC,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC"}

@@ -12,2 +12,22 @@ import type { ToolOutput } from "./types.js";

export declare function dualOutput<T>(data: T, humanFormat: (d: T) => string): ToolOutput<T>;
/**
* Estimates the token count of a string using the ~4 chars/token heuristic.
*/
export declare function estimateTokens(text: string): number;
/**
* Creates a dual-output response with automatic compact mode.
*
* Compares the token cost of the full structured JSON against the raw CLI stdout.
* When the structured output would use more tokens than raw, applies a compact
* projection to reduce the schema. Setting `forceFullSchema` to true always
* returns the full (non-compact) data.
*
* @param data - The full structured data parsed from CLI output.
* @param rawStdout - The ANSI-stripped stdout from the CLI command.
* @param humanFormat - Formatter for full data (used when not compacting).
* @param compactMap - Projects full data into a compact shape.
* @param compactFormat - Formatter for compact data.
* @param forceFullSchema - When true, skip auto-detection and return full data.
*/
export declare function compactDualOutput<T, C>(data: T, rawStdout: string, humanFormat: (d: T) => string, compactMap: (d: T) => C, compactFormat: (d: C) => string, forceFullSchema: boolean): ToolOutput<T | C>;
//# sourceMappingURL=output.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,CAKnF"}
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,CAKnF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,CAAC,EACpC,IAAI,EAAE,CAAC,EACP,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,EAC7B,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EACvB,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,EAC/B,eAAe,EAAE,OAAO,GACvB,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAcnB"}

@@ -16,2 +16,35 @@ /**

}
/**
* Estimates the token count of a string using the ~4 chars/token heuristic.
*/
export function estimateTokens(text) {
return Math.ceil(text.length / 4);
}
/**
* Creates a dual-output response with automatic compact mode.
*
* Compares the token cost of the full structured JSON against the raw CLI stdout.
* When the structured output would use more tokens than raw, applies a compact
* projection to reduce the schema. Setting `forceFullSchema` to true always
* returns the full (non-compact) data.
*
* @param data - The full structured data parsed from CLI output.
* @param rawStdout - The ANSI-stripped stdout from the CLI command.
* @param humanFormat - Formatter for full data (used when not compacting).
* @param compactMap - Projects full data into a compact shape.
* @param compactFormat - Formatter for compact data.
* @param forceFullSchema - When true, skip auto-detection and return full data.
*/
export function compactDualOutput(data, rawStdout, humanFormat, compactMap, compactFormat, forceFullSchema) {
if (forceFullSchema) {
return dualOutput(data, humanFormat);
}
const structuredTokens = estimateTokens(JSON.stringify(data));
const rawTokens = estimateTokens(rawStdout);
if (structuredTokens >= rawTokens) {
const compact = compactMap(data);
return dualOutput(compact, compactFormat);
}
return dualOutput(data, humanFormat);
}
//# sourceMappingURL=output.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAI,IAAO,EAAE,WAA6B;IAClE,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACpD,iBAAiB,EAAE,IAAI;KACxB,CAAC;AACJ,CAAC"}
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAI,IAAO,EAAE,WAA6B;IAClE,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACpD,iBAAiB,EAAE,IAAI;KACxB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAO,EACP,SAAiB,EACjB,WAA6B,EAC7B,UAAuB,EACvB,aAA+B,EAC/B,eAAwB;IAExB,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,UAAU,CAAC,IAAI,EAAE,WAAW,CAAsB,CAAC;IAC5D,CAAC;IAED,MAAM,gBAAgB,GAAG,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IAE5C,IAAI,gBAAgB,IAAI,SAAS,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QACjC,OAAO,UAAU,CAAC,OAAO,EAAE,aAAa,CAAsB,CAAC;IACjE,CAAC;IAED,OAAO,UAAU,CAAC,IAAI,EAAE,WAAW,CAAsB,CAAC;AAC5D,CAAC"}

@@ -14,2 +14,20 @@ /** Options for the command runner, including working directory, timeout, and environment overrides. */

/**
* Escapes a single argument for safe use with cmd.exe on Windows.
*
* When `shell: true` is used with `execFile` on Windows, Node.js wraps each
* argument in double quotes. Inside double quotes cmd.exe still interprets:
* - `%VAR%` for environment variable expansion
* - `^` as the escape character itself
* - `&`, `|`, `<`, `>` as pipeline / redirection operators
*
* We neutralise these by:
* 1. Replacing `%` with `%%` (disables env-var expansion inside quotes).
* 2. Prefixing `^`, `&`, `|`, `<`, `>`, `!` with the cmd.exe escape char `^`.
* (`!` must be escaped to prevent delayed expansion of `!VAR!`.)
*
* Parentheses `(` `)` are NOT escaped here because inside double-quoted
* strings they are literal characters and do not affect grouping.
*/
export declare function escapeCmdArg(arg: string): string;
/**
* Executes a command and returns cleaned output with ANSI codes stripped.

@@ -16,0 +34,0 @@ * Uses execFile (not exec) to avoid shell injection. On Windows, shell is

@@ -1,1 +0,1 @@

{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAGA,uGAAuG;AACvG,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,+FAA+F;AAC/F,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAkDtF"}
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAIA,uGAAuG;AACvG,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,+FAA+F;AAC/F,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiBhD;AAED;;;;;;;;GAQG;AACH,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAkEtF"}
import { execFile } from "node:child_process";
import { stripAnsi } from "./ansi.js";
import { sanitizeErrorOutput } from "./sanitize.js";
/**
* Escapes a single argument for safe use with cmd.exe on Windows.
*
* When `shell: true` is used with `execFile` on Windows, Node.js wraps each
* argument in double quotes. Inside double quotes cmd.exe still interprets:
* - `%VAR%` for environment variable expansion
* - `^` as the escape character itself
* - `&`, `|`, `<`, `>` as pipeline / redirection operators
*
* We neutralise these by:
* 1. Replacing `%` with `%%` (disables env-var expansion inside quotes).
* 2. Prefixing `^`, `&`, `|`, `<`, `>`, `!` with the cmd.exe escape char `^`.
* (`!` must be escaped to prevent delayed expansion of `!VAR!`.)
*
* Parentheses `(` `)` are NOT escaped here because inside double-quoted
* strings they are literal characters and do not affect grouping.
*/
export function escapeCmdArg(arg) {
// Step 1: Escape % → %% to prevent %VAR% expansion
let escaped = arg.replace(/%/g, "%%");
// Step 2: Caret-escape cmd.exe metacharacters that are dangerous
// even inside double quotes. The caret itself must be escaped first
// so that carets we insert are not themselves re-escaped.
escaped = escaped.replace(/\^/g, "^^");
escaped = escaped.replace(/&/g, "^&");
escaped = escaped.replace(/\|/g, "^|");
escaped = escaped.replace(/</g, "^<");
escaped = escaped.replace(/>/g, "^>");
// Step 3: Escape ! to prevent delayed expansion (!VAR!)
escaped = escaped.replace(/!/g, "^!");
return escaped;
}
/**
* Executes a command and returns cleaned output with ANSI codes stripped.

@@ -14,5 +47,9 @@ * Uses execFile (not exec) to avoid shell injection. On Windows, shell is

return new Promise((resolve, reject) => {
execFile(cmd, args, {
// On Windows with shell mode, escape cmd.exe metacharacters to prevent
// environment variable expansion and command injection via special chars.
// See escapeCmdArg() for details on what is escaped and why.
const safeArgs = process.platform === "win32" ? args.map(escapeCmdArg) : args;
execFile(cmd, safeArgs, {
cwd: opts?.cwd,
timeout: opts?.timeout ?? 30_000,
timeout: opts?.timeout ?? 60_000,
env: opts?.env ? { ...process.env, ...opts.env } : undefined,

@@ -33,2 +70,8 @@ maxBuffer: 10 * 1024 * 1024, // 10 MB

}
// Timeout: execFile killed the child after the configured timeout.
// Surface this clearly instead of silently returning exitCode 1.
if (error.killed && error.signal) {
reject(new Error(`Command "${cmd}" timed out after ${opts?.timeout ?? 60_000}ms and was killed (${error.signal}).`));
return;
}
// Windows: cmd.exe masks ENOENT — detect via stderr message

@@ -44,3 +87,3 @@ const cleanStderr = stripAnsi(stderr);

stdout: stripAnsi(stdout),
stderr: stripAnsi(stderr),
stderr: sanitizeErrorOutput(stripAnsi(stderr)),
});

@@ -47,0 +90,0 @@ });

@@ -1,1 +0,1 @@

{"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAgBtC;;;;;;;;GAQG;AACH,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,IAAc,EAAE,IAAiB;IAChE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,QAAQ,CACN,GAAG,EACH,IAAI,EACJ;YACE,GAAG,EAAE,IAAI,EAAE,GAAG;YACd,OAAO,EAAE,IAAI,EAAE,OAAO,IAAI,MAAM;YAChC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS;YAC5D,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,QAAQ;YACrC,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;SACpC,EACD,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACxB,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,KAAK,GAAG,KAA8B,CAAC;gBAE7C,wDAAwD;gBACxD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC5B,MAAM,CACJ,IAAI,KAAK,CACP,uBAAuB,GAAG,uDAAuD,CAClF,CACF,CAAC;oBACF,OAAO;gBACT,CAAC;gBACD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;oBACtD,MAAM,CAAC,IAAI,KAAK,CAAC,gCAAgC,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;oBAC5E,OAAO;gBACT,CAAC;gBAED,4DAA4D;gBAC5D,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;gBACtC,IAAI,WAAW,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;oBAC9C,MAAM,CACJ,IAAI,KAAK,CACP,uBAAuB,GAAG,uDAAuD,CAClF,CACF,CAAC;oBACF,OAAO;gBACT,CAAC;YACH,CAAC;YAED,OAAO,CAAC;gBACN,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACvE,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC;gBACzB,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC;aAC1B,CAAC,CAAC;QACL,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}

@@ -7,4 +7,16 @@ /**

export declare function assertNoFlagInjection(value: string, paramName: string): void;
/** Validates that a command is in the allowlist of safe build tools to prevent arbitrary command execution. */
/**
* Validates that a command is in the allowlist of safe build tools to prevent arbitrary command execution.
*
* Known limitation: only the basename is checked, so a path like `/tmp/evil/npm` would pass.
* Rejecting paths entirely would break legitimate use cases (NixOS store paths, `C:\Program Files\...`,
* non-PATH installs). Exploiting this requires placing a malicious binary on disk, which already
* implies the system is compromised.
*
* Security note: When a full path is provided (containing `/` or `\`), a warning is logged because
* basename-only validation cannot guarantee the binary at that path is the genuine tool. An attacker
* with write access to the filesystem could place a malicious binary at a path like `/tmp/evil/npm`.
* The warning serves as an audit trail for security-conscious deployments.
*/
export declare function assertAllowedCommand(command: string): void;
//# sourceMappingURL=validation.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAM5E;AAiCD,+GAA+G;AAC/G,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAe1D"}
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAM5E;AAiCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAwB1D"}

@@ -7,3 +7,3 @@ /**

export function assertNoFlagInjection(value, paramName) {
if (value.startsWith("-")) {
if (value.trimStart().startsWith("-")) {
throw new Error(`Invalid ${paramName}: "${value}". Values must not start with "-" to prevent argument injection.`);

@@ -42,3 +42,15 @@ }

]);
/** Validates that a command is in the allowlist of safe build tools to prevent arbitrary command execution. */
/**
* Validates that a command is in the allowlist of safe build tools to prevent arbitrary command execution.
*
* Known limitation: only the basename is checked, so a path like `/tmp/evil/npm` would pass.
* Rejecting paths entirely would break legitimate use cases (NixOS store paths, `C:\Program Files\...`,
* non-PATH installs). Exploiting this requires placing a malicious binary on disk, which already
* implies the system is compromised.
*
* Security note: When a full path is provided (containing `/` or `\`), a warning is logged because
* basename-only validation cannot guarantee the binary at that path is the genuine tool. An attacker
* with write access to the filesystem could place a malicious binary at a path like `/tmp/evil/npm`.
* The warning serves as an audit trail for security-conscious deployments.
*/
export function assertAllowedCommand(command) {

@@ -55,3 +67,9 @@ // Extract the base command name (handle paths like /usr/bin/npm or C:\npm.cmd)

}
// Warn when a full path is used — basename-only validation cannot verify the actual binary
if (command.includes("/") || command.includes("\\")) {
console.warn(`[pare:security] Command uses a full path: "${command}". ` +
`Only the basename "${base}" was validated against the allowlist. ` +
`Ensure this path points to a trusted binary.`);
}
}
//# sourceMappingURL=validation.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa,EAAE,SAAiB;IACpE,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,WAAW,SAAS,MAAM,KAAK,kEAAkE,CAClG,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC;IACrC,KAAK;IACL,KAAK;IACL,MAAM;IACN,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,OAAO;IACP,QAAQ;IACR,SAAS;IACT,KAAK;IACL,KAAK;IACL,OAAO;IACP,IAAI;IACJ,QAAQ;IACR,SAAS;IACT,KAAK;IACL,SAAS;IACT,MAAM;IACN,SAAS;IACT,QAAQ;IACR,OAAO;IACP,IAAI;IACJ,OAAO;CACR,CAAC,CAAC;AAEH,+GAA+G;AAC/G,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,+EAA+E;IAC/E,MAAM,IAAI,GACR,OAAO;SACJ,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,EAAE;QACN,EAAE,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;IAEhD,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CACb,YAAY,OAAO,+CAA+C;YAChE,YAAY,CAAC,GAAG,sBAAsB,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC9D,CAAC;IACJ,CAAC;AACH,CAAC"}
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa,EAAE,SAAiB;IACpE,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CACb,WAAW,SAAS,MAAM,KAAK,kEAAkE,CAClG,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC;IACrC,KAAK;IACL,KAAK;IACL,MAAM;IACN,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,OAAO;IACP,QAAQ;IACR,SAAS;IACT,KAAK;IACL,KAAK;IACL,OAAO;IACP,IAAI;IACJ,QAAQ;IACR,SAAS;IACT,KAAK;IACL,SAAS;IACT,MAAM;IACN,SAAS;IACT,QAAQ;IACR,OAAO;IACP,IAAI;IACJ,OAAO;CACR,CAAC,CAAC;AAEH;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,+EAA+E;IAC/E,MAAM,IAAI,GACR,OAAO;SACJ,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,EAAE;QACN,EAAE,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;IAEhD,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CACb,YAAY,OAAO,+CAA+C;YAChE,YAAY,CAAC,GAAG,sBAAsB,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC9D,CAAC;IACJ,CAAC;IAED,2FAA2F;IAC3F,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACpD,OAAO,CAAC,IAAI,CACV,8CAA8C,OAAO,KAAK;YACxD,sBAAsB,IAAI,yCAAyC;YACnE,8CAA8C,CACjD,CAAC;IACJ,CAAC;AACH,CAAC"}
{
"name": "@paretools/shared",
"version": "0.5.0",
"version": "0.6.0",
"description": "Shared utilities for Pare MCP servers",

@@ -17,3 +17,3 @@ "license": "MIT",

],
"homepage": "https://github.com/Dave-London/pare/tree/main/packages/shared",
"homepage": "https://github.com/Dave-London/Pare/tree/main/packages/shared",
"engines": {

@@ -34,3 +34,3 @@ "node": ">=20"

"type": "git",
"url": "https://github.com/Dave-London/pare.git",
"url": "https://github.com/Dave-London/Pare.git",
"directory": "packages/shared"

@@ -37,0 +37,0 @@ },

# @paretools/shared
[![npm](https://img.shields.io/npm/v/@paretools/shared.svg)](https://www.npmjs.com/package/@paretools/shared)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/Dave-London/pare/blob/main/LICENSE)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/Dave-London/Pare/blob/main/LICENSE)
Shared utilities for [Pare](https://github.com/Dave-London/pare) MCP servers.
Shared utilities for [Pare](https://github.com/Dave-London/Pare) MCP servers.

@@ -24,6 +24,6 @@ ## Exports

- [Pare monorepo](https://github.com/Dave-London/pare)
- [Pare monorepo](https://github.com/Dave-London/Pare)
## License
[MIT](https://github.com/Dave-London/pare/blob/main/LICENSE)
[MIT](https://github.com/Dave-London/Pare/blob/main/LICENSE)