mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 06:06:37 +03:00
Fix: keep the node runtime probe clear of cmd.exe metacharacters (#458)
Volta's Windows shims exec through `cmd /C`, which re-parses the argument list, so the `>=` inside the probe's `node -e` payload was read as output redirection. The command died with "The filename, directory name, or volume label syntax is incorrect" before node started, the guard read that as a missing runtime, and the hook it exists to protect was disabled on every PostToolUse and Stop. A user on a supported Node 24 got a one-time notice telling them to install Node 22, then silence. Clamping with Math.min is the same floor test in the same ES5-only syntax, with no character cmd.exe can claim. Verified through the Volta shim on Node 24.16.0 and 22.18.0 (exit 0) and against a real Node 20.6.1 binary (exit 1), so the floor is unchanged. Adds a regression test asserting no `<`, `>`, or newline reaches any generated `node -e` payload. Upstream cause: volta-cli/volta#1791. Prepared with AI assistance (Claude Code).
This commit is contained in:
@@ -72,7 +72,13 @@ const NODE_MAJOR_FLOOR = 22;
|
||||
// renders only on DENY, so warning would block the edit -> probe only
|
||||
// Grok Build: PostToolUse/Stop stdout is ignored outright -> probe only
|
||||
// Copilot: output contract unconfirmed; do not guess a shape -> probe only
|
||||
const NODE_PROBE = `node -e "process.exit(parseInt(process.versions.node,10)>=${NODE_MAJOR_FLOOR}?0:1)" 2>/dev/null`;
|
||||
//
|
||||
// The clamp avoids `<` and `>` deliberately: Volta's Windows shims run through
|
||||
// `cmd /C`, which reads an angle bracket in the `-e` payload as redirection, so
|
||||
// `>=` failed before node ran at all and the guard reported a missing runtime on
|
||||
// a machine that had a supported one (volta-cli/volta#1791). Newlines break the
|
||||
// same way, so this payload also has to stay on one line.
|
||||
const NODE_PROBE = `node -e "process.exit(Math.min(parseInt(process.versions.node,10),${NODE_MAJOR_FLOOR})===${NODE_MAJOR_FLOOR}?0:1)" 2>/dev/null`;
|
||||
const guardedNode = (hookPath, notice = '') => {
|
||||
const probe = notice
|
||||
? `! { ${NODE_PROBE} || { ${notice}; exit 0; }; }`
|
||||
|
||||
Reference in New Issue
Block a user