Repository navigation
test(dev): cover Windows npm invocation safety and supervisor cleanup - #266
Merged
dDevAhmed merged 1 commit intoOct 18, 2026
Conversation
SW-064 (DigiNodes#165): createNpmInvocation is the only place the CLI decides how to reach npm, and on Windows it goes through cmd.exe /d /s /c npm <args> - a wrapper around a command interpreter. Nothing tested it: critical-path.test.ts re-implements the same wrapper inline in its own helper rather than importing the function, so it asserts a copy of the behaviour and npm.ts itself had no direct coverage. Pins that the fixed /d /s /c prefix always leads, and that a hostile argument (value & calc.exe, $(whoami), backticks, quotes, newlines) arrives as exactly one inert argv element on both platforms. SW-065 (DigiNodes#166): the existing supervisor suite covers a one-child spawn failure and a two-child sibling exit, leaving two cleanup properties unverified. With three children, a mid-loop failure must terminate every already-started child - the two-child case cannot distinguish 'all children killed' from 'the next one killed'. And fail() wraps the original error as the cause so the reason is not lost, which nothing asserted. Covers no-orphans across three children, cause preservation, exit-code and signal in the failure message, handler teardown after failure, and the child 'error' event path.
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two security-sensitive gaps in areas the wave flagged but nothing tested.
SW-064 (#165) —
createNpmInvocationhad no direct coverageThis is the only place the CLI decides how to reach npm, and on Windows it does so
through
cmd.exe /d /s /c npm <args>— a wrapper around a command interpreter.The entire safety property is that the argument vector stays an argv: the moment a
caller-supplied string is joined into one command line, a value containing
&,|,;or backticks stops being data and becomes a command fragment.Nothing tested it.
critical-path.test.ts:39re-implements the same wrapper inlinein its own helper rather than importing the function, so it asserts a copy of the
behaviour, and
npm.tsitself had no direct coverage at all.The new cases run on both platforms (via the
Object.defineProperty(process, 'platform', …)pattern already used ingenerator-reserved-names.test.ts) and pin:/d /s /cprefix always leads, so nothing can be prepended to it;value & calc.exe,$(whoami), backticks, quotes,an embedded newline,
value && echo pwned— arrives as exactly one inert argvelement, byte-for-byte, on Windows and POSIX alike;
commandandargsremain separate, which is what lets the spawner passshell: false.SW-065 (#166) — two supervisor cleanup properties unverified
The existing suite covers a one-child spawn failure and a two-child sibling exit.
Two properties of cleanup therefore had no real test:
No child is orphaned. With three children, a mid-loop failure must terminate
every already-started child. The two-child case cannot distinguish "all children
killed" from "the next one killed" — both produce the same assertion. This suite
also confirms a spec that was never spawned has nothing to clean up, so the test
cannot pass by over-killing.
The failure cause survives.
fail()wraps the original error as thecauseofa
SubprocessCliErrorso the underlying reason is not lost. The existing caseasserts only the error type; nothing checked the cause was actually attached.
Plus: exit code and signal both reach the message, handlers are removed after a
failure, and the child
errorevent path still cleans up.Issue references
Closes #165
Closes #166
Closes #167
Closes #169
What this PR actually changes
Implemented in full — #165 (
npm-invocation-metacharacters.test.ts) and#166 (
dev-supervisor-cleanup.test.ts).Not implemented here:
test-command.test.tsasserts a zero exit resolves and a code-9 exit rejectswith
SubprocessCliError, andtest-orchestration-regression.test.tsalsoasserts the
with code 9message.test-orchestration-regression.test.tshas dedicated streaming cases for boththe Node and the Cargo workflow, and
test-command.test.ts:44asserts thesuccessful child's output.
Both were verified against the code rather than assumed, so no duplicate coverage
was added for them.
Split from another PR in this wave
The repeated-signal half of cleanup idempotency is covered by a separate
contributor's
dev-orchestrator-signal-idempotency.test.ts. This file stays onfailure paths so the two suites do not overlap.
Not run
node_moduleswas not installed and the suite was not executed, per yourconstraint. The platform-stub cases use the same
Object.defineProperty+ restorepattern as
generator-reserved-names.test.ts, so they should behave, but a localrun is worth doing before merge — particularly on Windows, where the
cmd.exebranch actually executes.