@paretools/shared 0.3.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  # @paretools/shared
2
2
 
3
- Shared utilities for Pare MCP servers.
3
+ [![npm](https://img.shields.io/npm/v/@paretools/shared.svg)](https://www.npmjs.com/package/@paretools/shared)
4
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/Dave-London/Pare/blob/main/LICENSE)
5
+
6
+ Shared utilities for [Pare](https://github.com/Dave-London/Pare) MCP servers.
4
7
 
5
8
  ## Exports
6
9
 
@@ -18,8 +21,8 @@ import { run, dualOutput, stripAnsi } from "@paretools/shared";
18
21
 
19
22
  ## Links
20
23
 
21
- - [Pare monorepo](https://github.com/Dave-London/pare)
24
+ - [Pare monorepo](https://github.com/Dave-London/Pare)
22
25
 
23
26
  ## License
24
27
 
25
- [MIT](https://github.com/Dave-London/pare/blob/main/LICENSE)
28
+ [MIT](https://github.com/Dave-London/Pare/blob/main/LICENSE)
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
- export { dualOutput } from "./output.js";
2
- export { run, type RunResult, type RunOptions } from "./runner.js";
1
+ export { dualOutput, estimateTokens, compactDualOutput } from "./output.js";
2
+ export { run, escapeCmdArg, type RunResult, type RunOptions } from "./runner.js";
3
3
  export { stripAnsi } from "./ansi.js";
4
4
  export { assertNoFlagInjection, assertAllowedCommand } from "./validation.js";
5
+ export { INPUT_LIMITS } from "./limits.js";
6
+ export { sanitizeErrorOutput } from "./sanitize.js";
5
7
  export type { ToolOutput } from "./types.js";
6
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
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"}
1
+ {"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"}
package/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
- export { dualOutput } from "./output.js";
2
- export { run } from "./runner.js";
1
+ export { dualOutput, estimateTokens, compactDualOutput } from "./output.js";
2
+ export { run, escapeCmdArg } from "./runner.js";
3
3
  export { stripAnsi } from "./ansi.js";
4
4
  export { assertNoFlagInjection, assertAllowedCommand } from "./validation.js";
5
+ export { INPUT_LIMITS } from "./limits.js";
6
+ export { sanitizeErrorOutput } from "./sanitize.js";
5
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
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"}
1
+ {"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Shared input-validation limits for all Pare MCP servers.
3
+ *
4
+ * These provide defense-in-depth against DoS via extremely long inputs.
5
+ * Applied to Zod input schemas with `.max()` — output schemas are NOT
6
+ * constrained because their size is determined by tool output, not user input.
7
+ */
8
+ export declare const INPUT_LIMITS: {
9
+ /** Maximum length for any general string parameter (64 KB). */
10
+ readonly STRING_MAX: 65536;
11
+ /** Maximum items in any array parameter. */
12
+ readonly ARRAY_MAX: 1000;
13
+ /** Maximum length for file system paths. */
14
+ readonly PATH_MAX: 4096;
15
+ /** Maximum length for commit messages (generous to allow long messages). */
16
+ readonly MESSAGE_MAX: 72000;
17
+ /** Maximum length for short identifiers (branch names, package names, etc.). */
18
+ readonly SHORT_STRING_MAX: 255;
19
+ };
20
+ //# sourceMappingURL=limits.d.ts.map
@@ -0,0 +1 @@
1
+ {"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"}
package/dist/limits.js ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Shared input-validation limits for all Pare MCP servers.
3
+ *
4
+ * These provide defense-in-depth against DoS via extremely long inputs.
5
+ * Applied to Zod input schemas with `.max()` — output schemas are NOT
6
+ * constrained because their size is determined by tool output, not user input.
7
+ */
8
+ export const INPUT_LIMITS = {
9
+ /** Maximum length for any general string parameter (64 KB). */
10
+ STRING_MAX: 65_536,
11
+ /** Maximum items in any array parameter. */
12
+ ARRAY_MAX: 1_000,
13
+ /** Maximum length for file system paths. */
14
+ PATH_MAX: 4_096,
15
+ /** Maximum length for commit messages (generous to allow long messages). */
16
+ MESSAGE_MAX: 72_000,
17
+ /** Maximum length for short identifiers (branch names, package names, etc.). */
18
+ SHORT_STRING_MAX: 255,
19
+ };
20
+ //# sourceMappingURL=limits.js.map
@@ -0,0 +1 @@
1
+ {"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"}
package/dist/output.d.ts CHANGED
@@ -9,4 +9,24 @@ import type { ToolOutput } from "./types.js";
9
9
  * @param humanFormat - A function that formats `data` as human-readable text.
10
10
  */
11
11
  export declare function dualOutput<T>(data: T, humanFormat: (d: T) => string): ToolOutput<T>;
12
+ /**
13
+ * Estimates the token count of a string using the ~4 chars/token heuristic.
14
+ */
15
+ export declare function estimateTokens(text: string): number;
16
+ /**
17
+ * Creates a dual-output response with automatic compact mode.
18
+ *
19
+ * Compares the token cost of the full structured JSON against the raw CLI stdout.
20
+ * When the structured output would use more tokens than raw, applies a compact
21
+ * projection to reduce the schema. Setting `forceFullSchema` to true always
22
+ * returns the full (non-compact) data.
23
+ *
24
+ * @param data - The full structured data parsed from CLI output.
25
+ * @param rawStdout - The ANSI-stripped stdout from the CLI command.
26
+ * @param humanFormat - Formatter for full data (used when not compacting).
27
+ * @param compactMap - Projects full data into a compact shape.
28
+ * @param compactFormat - Formatter for compact data.
29
+ * @param forceFullSchema - When true, skip auto-detection and return full data.
30
+ */
31
+ 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>;
12
32
  //# sourceMappingURL=output.d.ts.map
@@ -1 +1 @@
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"}
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;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"}
package/dist/output.js CHANGED
@@ -13,4 +13,37 @@ export function dualOutput(data, humanFormat) {
13
13
  structuredContent: data,
14
14
  };
15
15
  }
16
+ /**
17
+ * Estimates the token count of a string using the ~4 chars/token heuristic.
18
+ */
19
+ export function estimateTokens(text) {
20
+ return Math.ceil(text.length / 4);
21
+ }
22
+ /**
23
+ * Creates a dual-output response with automatic compact mode.
24
+ *
25
+ * Compares the token cost of the full structured JSON against the raw CLI stdout.
26
+ * When the structured output would use more tokens than raw, applies a compact
27
+ * projection to reduce the schema. Setting `forceFullSchema` to true always
28
+ * returns the full (non-compact) data.
29
+ *
30
+ * @param data - The full structured data parsed from CLI output.
31
+ * @param rawStdout - The ANSI-stripped stdout from the CLI command.
32
+ * @param humanFormat - Formatter for full data (used when not compacting).
33
+ * @param compactMap - Projects full data into a compact shape.
34
+ * @param compactFormat - Formatter for compact data.
35
+ * @param forceFullSchema - When true, skip auto-detection and return full data.
36
+ */
37
+ export function compactDualOutput(data, rawStdout, humanFormat, compactMap, compactFormat, forceFullSchema) {
38
+ if (forceFullSchema) {
39
+ return dualOutput(data, humanFormat);
40
+ }
41
+ const structuredTokens = estimateTokens(JSON.stringify(data));
42
+ const rawTokens = estimateTokens(rawStdout);
43
+ if (structuredTokens >= rawTokens) {
44
+ const compact = compactMap(data);
45
+ return dualOutput(compact, compactFormat);
46
+ }
47
+ return dualOutput(data, humanFormat);
48
+ }
16
49
  //# sourceMappingURL=output.js.map
@@ -1 +1 @@
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"}
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;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"}
package/dist/runner.d.ts CHANGED
@@ -1,13 +1,33 @@
1
+ /** Options for the command runner, including working directory, timeout, and environment overrides. */
1
2
  export interface RunOptions {
2
3
  cwd?: string;
3
4
  timeout?: number;
4
5
  env?: Record<string, string>;
5
6
  }
7
+ /** Result of a command execution, containing the exit code and ANSI-stripped stdout/stderr. */
6
8
  export interface RunResult {
7
9
  exitCode: number;
8
10
  stdout: string;
9
11
  stderr: string;
10
12
  }
13
+ /**
14
+ * Escapes a single argument for safe use with cmd.exe on Windows.
15
+ *
16
+ * When `shell: true` is used with `execFile` on Windows, Node.js wraps each
17
+ * argument in double quotes. Inside double quotes cmd.exe still interprets:
18
+ * - `%VAR%` for environment variable expansion
19
+ * - `^` as the escape character itself
20
+ * - `&`, `|`, `<`, `>` as pipeline / redirection operators
21
+ *
22
+ * We neutralise these by:
23
+ * 1. Replacing `%` with `%%` (disables env-var expansion inside quotes).
24
+ * 2. Prefixing `^`, `&`, `|`, `<`, `>`, `!` with the cmd.exe escape char `^`.
25
+ * (`!` must be escaped to prevent delayed expansion of `!VAR!`.)
26
+ *
27
+ * Parentheses `(` `)` are NOT escaped here because inside double-quoted
28
+ * strings they are literal characters and do not affect grouping.
29
+ */
30
+ export declare function escapeCmdArg(arg: string): string;
11
31
  /**
12
32
  * Executes a command and returns cleaned output with ANSI codes stripped.
13
33
  * Uses execFile (not exec) to avoid shell injection. On Windows, shell is
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAGA,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,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"}
1
+ {"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"}
package/dist/runner.js CHANGED
@@ -1,5 +1,38 @@
1
1
  import { execFile } from "node:child_process";
2
2
  import { stripAnsi } from "./ansi.js";
3
+ import { sanitizeErrorOutput } from "./sanitize.js";
4
+ /**
5
+ * Escapes a single argument for safe use with cmd.exe on Windows.
6
+ *
7
+ * When `shell: true` is used with `execFile` on Windows, Node.js wraps each
8
+ * argument in double quotes. Inside double quotes cmd.exe still interprets:
9
+ * - `%VAR%` for environment variable expansion
10
+ * - `^` as the escape character itself
11
+ * - `&`, `|`, `<`, `>` as pipeline / redirection operators
12
+ *
13
+ * We neutralise these by:
14
+ * 1. Replacing `%` with `%%` (disables env-var expansion inside quotes).
15
+ * 2. Prefixing `^`, `&`, `|`, `<`, `>`, `!` with the cmd.exe escape char `^`.
16
+ * (`!` must be escaped to prevent delayed expansion of `!VAR!`.)
17
+ *
18
+ * Parentheses `(` `)` are NOT escaped here because inside double-quoted
19
+ * strings they are literal characters and do not affect grouping.
20
+ */
21
+ export function escapeCmdArg(arg) {
22
+ // Step 1: Escape % → %% to prevent %VAR% expansion
23
+ let escaped = arg.replace(/%/g, "%%");
24
+ // Step 2: Caret-escape cmd.exe metacharacters that are dangerous
25
+ // even inside double quotes. The caret itself must be escaped first
26
+ // so that carets we insert are not themselves re-escaped.
27
+ escaped = escaped.replace(/\^/g, "^^");
28
+ escaped = escaped.replace(/&/g, "^&");
29
+ escaped = escaped.replace(/\|/g, "^|");
30
+ escaped = escaped.replace(/</g, "^<");
31
+ escaped = escaped.replace(/>/g, "^>");
32
+ // Step 3: Escape ! to prevent delayed expansion (!VAR!)
33
+ escaped = escaped.replace(/!/g, "^!");
34
+ return escaped;
35
+ }
3
36
  /**
4
37
  * Executes a command and returns cleaned output with ANSI codes stripped.
5
38
  * Uses execFile (not exec) to avoid shell injection. On Windows, shell is
@@ -11,9 +44,13 @@ import { stripAnsi } from "./ansi.js";
11
44
  */
12
45
  export function run(cmd, args, opts) {
13
46
  return new Promise((resolve, reject) => {
14
- execFile(cmd, args, {
47
+ // On Windows with shell mode, escape cmd.exe metacharacters to prevent
48
+ // environment variable expansion and command injection via special chars.
49
+ // See escapeCmdArg() for details on what is escaped and why.
50
+ const safeArgs = process.platform === "win32" ? args.map(escapeCmdArg) : args;
51
+ execFile(cmd, safeArgs, {
15
52
  cwd: opts?.cwd,
16
- timeout: opts?.timeout ?? 30_000,
53
+ timeout: opts?.timeout ?? 60_000,
17
54
  env: opts?.env ? { ...process.env, ...opts.env } : undefined,
18
55
  maxBuffer: 10 * 1024 * 1024, // 10 MB
19
56
  shell: process.platform === "win32",
@@ -29,6 +66,12 @@ export function run(cmd, args, opts) {
29
66
  reject(new Error(`Permission denied executing "${cmd}": ${errno.message}`));
30
67
  return;
31
68
  }
69
+ // Timeout: execFile killed the child after the configured timeout.
70
+ // Surface this clearly instead of silently returning exitCode 1.
71
+ if (error.killed && error.signal) {
72
+ reject(new Error(`Command "${cmd}" timed out after ${opts?.timeout ?? 60_000}ms and was killed (${error.signal}).`));
73
+ return;
74
+ }
32
75
  // Windows: cmd.exe masks ENOENT — detect via stderr message
33
76
  const cleanStderr = stripAnsi(stderr);
34
77
  if (cleanStderr.includes("is not recognized")) {
@@ -39,7 +82,7 @@ export function run(cmd, args, opts) {
39
82
  resolve({
40
83
  exitCode: error ? (typeof error.code === "number" ? error.code : 1) : 0,
41
84
  stdout: stripAnsi(stdout),
42
- stderr: stripAnsi(stderr),
85
+ stderr: sanitizeErrorOutput(stripAnsi(stderr)),
43
86
  });
44
87
  });
45
88
  });
@@ -1 +1 @@
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;AActC;;;;;;;;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"}
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Sanitizes error output by replacing sensitive filesystem paths with
3
+ * home-relative equivalents. This prevents leaking usernames and absolute
4
+ * home directory paths in error messages returned to MCP clients.
5
+ *
6
+ * Replacements:
7
+ * /home/<user>/... → ~/...
8
+ * /Users/<user>/... → ~/...
9
+ * /root/... → ~/...
10
+ * C:\Users\<user>\... → ~\...
11
+ */
12
+ export declare function sanitizeErrorOutput(text: string): string;
13
+ //# sourceMappingURL=sanitize.d.ts.map
@@ -0,0 +1 @@
1
+ {"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Sanitizes error output by replacing sensitive filesystem paths with
3
+ * home-relative equivalents. This prevents leaking usernames and absolute
4
+ * home directory paths in error messages returned to MCP clients.
5
+ *
6
+ * Replacements:
7
+ * /home/<user>/... → ~/...
8
+ * /Users/<user>/... → ~/...
9
+ * /root/... → ~/...
10
+ * C:\Users\<user>\... → ~\...
11
+ */
12
+ export function sanitizeErrorOutput(text) {
13
+ // Unix: /home/<username>/rest → ~/rest
14
+ let result = text.replace(/\/home\/[^/\s]+\//g, "~/");
15
+ // macOS: /Users/<username>/rest → ~/rest
16
+ result = result.replace(/\/Users\/[^/\s]+\//g, "~/");
17
+ // Unix: /root/rest → ~/rest
18
+ result = result.replace(/\/root\//g, "~/");
19
+ // Windows: C:\Users\<username>\rest → ~\rest (with escaped or literal backslashes)
20
+ result = result.replace(/[A-Z]:\\Users\\[^\\:\s]+\\/gi, "~\\");
21
+ return result;
22
+ }
23
+ //# sourceMappingURL=sanitize.js.map
@@ -0,0 +1 @@
1
+ {"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,5 +4,18 @@
4
4
  * See: CVE-2025-68144, CVE-2025-68145
5
5
  */
6
6
  export declare function assertNoFlagInjection(value: string, paramName: string): void;
7
+ /**
8
+ * Validates that a command is in the allowlist of safe build tools to prevent arbitrary command execution.
9
+ *
10
+ * Known limitation: only the basename is checked, so a path like `/tmp/evil/npm` would pass.
11
+ * Rejecting paths entirely would break legitimate use cases (NixOS store paths, `C:\Program Files\...`,
12
+ * non-PATH installs). Exploiting this requires placing a malicious binary on disk, which already
13
+ * implies the system is compromised.
14
+ *
15
+ * Security note: When a full path is provided (containing `/` or `\`), a warning is logged because
16
+ * basename-only validation cannot guarantee the binary at that path is the genuine tool. An attacker
17
+ * with write access to the filesystem could place a malicious binary at a path like `/tmp/evil/npm`.
18
+ * The warning serves as an audit trail for security-conscious deployments.
19
+ */
7
20
  export declare function assertAllowedCommand(command: string): void;
8
21
  //# sourceMappingURL=validation.d.ts.map
@@ -1 +1 @@
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,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAe1D"}
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;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAwB1D"}
@@ -4,7 +4,7 @@
4
4
  * See: CVE-2025-68144, CVE-2025-68145
5
5
  */
6
6
  export function assertNoFlagInjection(value, paramName) {
7
- if (value.startsWith("-")) {
7
+ if (value.trimStart().startsWith("-")) {
8
8
  throw new Error(`Invalid ${paramName}: "${value}". Values must not start with "-" to prevent argument injection.`);
9
9
  }
10
10
  }
@@ -38,6 +38,19 @@ const ALLOWED_BUILD_COMMANDS = new Set([
38
38
  "nx",
39
39
  "bazel",
40
40
  ]);
41
+ /**
42
+ * Validates that a command is in the allowlist of safe build tools to prevent arbitrary command execution.
43
+ *
44
+ * Known limitation: only the basename is checked, so a path like `/tmp/evil/npm` would pass.
45
+ * Rejecting paths entirely would break legitimate use cases (NixOS store paths, `C:\Program Files\...`,
46
+ * non-PATH installs). Exploiting this requires placing a malicious binary on disk, which already
47
+ * implies the system is compromised.
48
+ *
49
+ * Security note: When a full path is provided (containing `/` or `\`), a warning is logged because
50
+ * basename-only validation cannot guarantee the binary at that path is the genuine tool. An attacker
51
+ * with write access to the filesystem could place a malicious binary at a path like `/tmp/evil/npm`.
52
+ * The warning serves as an audit trail for security-conscious deployments.
53
+ */
41
54
  export function assertAllowedCommand(command) {
42
55
  // Extract the base command name (handle paths like /usr/bin/npm or C:\npm.cmd)
43
56
  const base = command
@@ -49,5 +62,11 @@ export function assertAllowedCommand(command) {
49
62
  throw new Error(`Command "${command}" is not in the allowed build commands list. ` +
50
63
  `Allowed: ${[...ALLOWED_BUILD_COMMANDS].sort().join(", ")}`);
51
64
  }
65
+ // Warn when a full path is used — basename-only validation cannot verify the actual binary
66
+ if (command.includes("/") || command.includes("\\")) {
67
+ console.warn(`[pare:security] Command uses a full path: "${command}". ` +
68
+ `Only the basename "${base}" was validated against the allowlist. ` +
69
+ `Ensure this path points to a trusted binary.`);
70
+ }
52
71
  }
53
72
  //# sourceMappingURL=validation.js.map
@@ -1 +1 @@
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,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"}
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,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"}
package/package.json CHANGED
@@ -1,17 +1,22 @@
1
1
  {
2
2
  "name": "@paretools/shared",
3
- "version": "0.3.0",
3
+ "version": "0.6.0",
4
4
  "description": "Shared utilities for Pare MCP servers",
5
5
  "license": "MIT",
6
6
  "keywords": [
7
7
  "mcp",
8
8
  "mcp-server",
9
9
  "model-context-protocol",
10
- "structured-output"
10
+ "structured-output",
11
+ "ai",
12
+ "ai-agent",
13
+ "token-efficient",
14
+ "devtools",
15
+ "cli"
11
16
  ],
12
- "homepage": "https://github.com/Dave-London/pare/tree/main/packages/shared",
17
+ "homepage": "https://github.com/Dave-London/Pare/tree/main/packages/shared",
13
18
  "engines": {
14
- "node": ">=18"
19
+ "node": ">=20"
15
20
  },
16
21
  "type": "module",
17
22
  "exports": {
@@ -25,7 +30,7 @@
25
30
  },
26
31
  "repository": {
27
32
  "type": "git",
28
- "url": "https://github.com/Dave-London/pare.git",
33
+ "url": "https://github.com/Dave-London/Pare.git",
29
34
  "directory": "packages/shared"
30
35
  },
31
36
  "files": [
@@ -33,12 +38,12 @@
33
38
  ],
34
39
  "dependencies": {
35
40
  "@modelcontextprotocol/sdk": "^1.26.0",
36
- "zod": "^3.25.0"
41
+ "zod": "^4.3.6"
37
42
  },
38
43
  "devDependencies": {
39
- "@types/node": "^22.0.0",
44
+ "@types/node": "^25.2.3",
40
45
  "typescript": "^5.7.0",
41
- "vitest": "^3.0.0",
46
+ "vitest": "^4.0.18",
42
47
  "@paretools/tsconfig": "0.0.0"
43
48
  },
44
49
  "scripts": {