ECC/tests/hooks
Michael 600072ebd8
fix(hooks): resolve MCP health-check spawn ENOENT on Windows (#1456)
* fix(hooks): resolve MCP health-check spawn ENOENT on Windows

On Windows, commands like 'npx' are batch files (npx.cmd) that require
shell expansion to resolve via PATH. Without shell: true, Node.js
spawn() fails with ENOENT.

However, absolute paths (e.g. C:\Program Files\nodejs\node.exe) must
NOT use shell mode because cmd.exe misparses paths containing spaces.

Fix: enable shell mode only for non-absolute commands on Windows, using
path.isAbsolute() to distinguish. This matches how attemptReconnect()
already handles the shell option.

Fixes #1455

* fix(hooks): harden Windows shell spawn — validate command for metacharacters

Addresses bot review feedback on PR #1456:

- Add UNSAFE_SHELL_CHARS regex to guard against shell injection when
  needsShell=true: cmd.exe operators (&, |, <, >, ^, %, !, (), ;,
  whitespace) are rejected before shell mode is enabled
- Add typeof command === 'string' check so path.isAbsolute() cannot
  throw on malformed non-string command values
- Rename test to 'via PATH resolution' (not Windows-only; runs all platforms)
- Fix misleading test comment: 'node' resolves via PATH like npx.cmd but
  does not itself use .cmd; comment now accurately reflects the intent

* fix(hooks): kill full process tree on Windows when shell mode is used

When needsShell=true, the spawned child is cmd.exe. Calling child.kill()
only terminates the shell, leaving the real server process orphaned.

Use taskkill /PID <pid> /T /F on Windows+shell to kill the entire
process tree rooted at cmd.exe. Fall back to SIGTERM+SIGKILL on all
other platforms or when shell mode is not active.

* fix(hooks): fall back to child.kill() when taskkill fails

Windows taskkill can fail if it's not on PATH, the process already
exited, or permissions are denied. Previously the failure was silently
ignored and no kill signal reached the child.

Now: capture the spawnSync result and fall back to child.kill('SIGKILL')
on any taskkill error or non-zero status. This still may leak a
detached server process but at least guarantees the cmd.exe shell is
signaled.
2026-05-11 01:13:37 -04:00
..
auto-tmux-dev.test.js feat: add C++ language support and hook tests (#539) 2026-03-16 14:31:49 -07:00
bash-hook-dispatcher.test.js fix: consolidate bash hooks without fork storms 2026-04-14 21:23:57 -07:00
block-no-verify.test.js fix: parse block-no-verify flags by shell words 2026-04-29 21:59:12 -04:00
check-hook-enabled.test.js feat: add C++ language support and hook tests (#539) 2026-03-16 14:31:49 -07:00
config-protection.test.js fix: finish blocker lane hook and install regressions 2026-03-25 04:00:50 -04:00
continuous-learning-observe-runner.test.js fix: route continuous learning observe hooks through node 2026-04-29 21:28:59 -04:00
cost-tracker.test.js feat: sync ecc2 cost tracker metrics 2026-04-09 06:22:20 -07:00
design-quality-check.test.js feat: add web frontend rules and design quality hook 2026-04-02 17:33:17 -07:00
detect-project-worktree.test.js fix(tests): resolve Windows CI test failures (#701) 2026-03-20 03:37:21 -07:00
doc-file-warning.test.js refactor: address reviewer feedback 2026-03-29 10:09:02 +08:00
evaluate-session.test.js fix: remove unused execFileSync import (no-unused-vars ESLint) 2026-02-18 07:15:53 +05:30
gateguard-fact-force.test.js fix: show correct gateguard hook recovery id 2026-04-30 11:26:15 -04:00
governance-capture.test.js fix: resolve blocker PR validation regressions 2026-03-25 01:34:29 -04:00
hook-flags.test.js feat: add C++ language support and hook tests (#539) 2026-03-16 14:31:49 -07:00
hooks.test.js fix: cap session-start context injection 2026-04-30 08:41:52 -04:00
insaits-security-monitor.test.js test: extend insaits monitor subprocess timeout 2026-04-29 19:25:18 -04:00
insaits-security-wrapper.test.js fix: fail open on insaits monitor errors 2026-04-29 18:03:33 -04:00
mcp-health-check.test.js fix(hooks): resolve MCP health-check spawn ENOENT on Windows (#1456) 2026-05-11 01:13:37 -04:00
observe-subdirectory-detection.test.js fix(clv2): resolve cwd to git root before project detection 2026-03-30 04:46:31 -04:00
observer-memory.test.js fix: retry observer wait after signal 2026-04-28 22:11:47 -04:00
plugin-hook-bootstrap.test.js test: cover hook bootstrap and InsAIts monitor 2026-04-29 17:45:22 -04:00
post-bash-hooks.test.js feat: add C++ language support and hook tests (#539) 2026-03-16 14:31:49 -07:00
pre-bash-commit-quality.test.js fix: run pre-bash linters through windows wrappers 2026-04-29 18:59:10 -04:00
pre-bash-dev-server-block.test.js feat: add C++ language support and hook tests (#539) 2026-03-16 14:31:49 -07:00
pre-bash-reminders.test.js feat: add C++ language support and hook tests (#539) 2026-03-16 14:31:49 -07:00
quality-gate.test.js feat: add C++ language support and hook tests (#539) 2026-03-16 14:31:49 -07:00
session-activity-tracker.test.js test: cover session activity tracker edge paths 2026-04-29 18:15:51 -04:00
stop-format-typecheck.test.js perf(hooks): batch format+typecheck at Stop instead of per Edit (#746) 2026-03-31 14:12:12 -07:00
suggest-compact.test.js test: isolate suggest-compact counter fixtures 2026-03-25 03:51:15 -04:00
test_insaits_security_monitor.py test: cover hook bootstrap and InsAIts monitor 2026-04-29 17:45:22 -04:00