mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-21 18:47:02 +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:
@@ -34,7 +34,7 @@ const ENGINES_NODE_MAJOR = parseInt(
|
||||
JSON.parse(fs.readFileSync(path.join(REPO_ROOT, 'package.json'), 'utf8')).engines.node.replace(/[^\d.]/g, ''),
|
||||
10,
|
||||
);
|
||||
const NODE_PROBE = `process.exit(parseInt(process.versions.node,10)>=${ENGINES_NODE_MAJOR}?0:1)`;
|
||||
const NODE_PROBE = `process.exit(Math.min(parseInt(process.versions.node,10),${ENGINES_NODE_MAJOR})===${ENGINES_NODE_MAJOR}?0:1)`;
|
||||
|
||||
function expectCommand(command, expectedPath) {
|
||||
assert.equal(typeof command, 'string');
|
||||
@@ -226,6 +226,14 @@ describe('hook manifest builders', () => {
|
||||
}
|
||||
});
|
||||
|
||||
// Volta's Windows shims exec through `cmd /C`, which claims `<`, `>`, and
|
||||
// newlines from the `node -e` payload, so the probe died before node ran and
|
||||
// the guard read that as a missing runtime (volta-cli/volta#1791). Every
|
||||
// command is asserted to carry NODE_PROBE above, so this covers them all.
|
||||
it('keeps the runtime probe free of characters cmd.exe re-parses', () => {
|
||||
assert.ok(!/[<>\n]/.test(NODE_PROBE), `cmd.exe-unsafe character in probe: ${NODE_PROBE}`);
|
||||
});
|
||||
|
||||
it('routes supported hook builders and leaves other providers alone', () => {
|
||||
assert.ok(hooksJsonFor('claude'));
|
||||
assert.ok(hooksJsonFor('codex'));
|
||||
|
||||
Reference in New Issue
Block a user