Summary
shell-quote's quote() function did not validate object-token inputs against the operator model used by parse(). The .op field was backslash-escaped character by character using /(.)/g, which in JavaScript does not match line terminators (\n, \r, U+2028, U+2029). A line terminator in .op therefore passed through unescaped into the output; POSIX shells treat a literal \n as a command separator, so any content after it would execute as a second command.
The vulnerable code path is reachable in two ways. Neither requires the parser to misbehave, parse() only emits ops from a fixed control set, but both are documented API surface:
- Direct construction. A caller builds
{ op: '...\n...' }from external input (e.g. a deserialized argument array) and passes it toquote(). envFnreturn.parse(cmd, envFn)is documented to splice the return value ofenvFninto the result array when it is an object. An attacker-influenced data source consulted byenvFncan introduce an object token whose.opreachesquote().
PoC
const { parse, quote } = require('shell-quote');
// Direct construction
quote([{ op: ';\nid' }]);
// → "\;\n\\i\\d" ← literal newline; second line executes as a command
// Via parse() with an envFn returning attacker-shaped objects
const tokens = parse('echo $X', () => ({ op: ';\nid' }));
require('child_process').execSync(quote(tokens), { shell: true });
// Executes `id` after `echo \;`.
Confirmed under sh, bash, dash, and zsh.
Workarounds
Prior to upgrading, callers that build object tokens from untrusted input should validate .op against the parser's operator set themselves, and never construct { op } from attacker-controlled strings.
Credits
Reported by Akshat Sinha
Impact
Shell command injection in callers that pass object tokens with attacker-influenced .op values to quote() and then hand the result to a shell. The preconditions are narrower than ordinary string injection, they require the caller to feed object tokens into quote(), but object tokens are a public, documented part of the API surface, and quote() is intended to be a shell-safety boundary.
Untrusted input is inserted into a command that is later executed by the application, allowing the attacker to alter the intent of that command. Typical impact: arbitrary command execution in the application's environment.
CVE-2026-9277 has a CVSS score of 8.1 (Critical). The vector is network-reachable, no privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (1.8.4); upgrading removes the vulnerable code path.
Affected versions
Security releases
Kodem intelligence
Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.
Remediation advice
Fixed by replacing the per-character escape with strict shape validation in quote(). The object-token branch now:
{ op },.opmust be a string from the same allowlist the parser emits (||,&&,;;,|&,<(,<<<,>>,>&,<&,&,;,(,),|,<,>). Anything else throwsTypeError. This is the direct fix for the reported issue and removes the entire class of.opinjection.{ op: 'glob', pattern },.patternmust be a string with no line terminators. Glob metacharacters (*,?,[,],{,},,) pass through; all other shell-special characters are backslash-escaped. (Previously the pattern field was discarded entirely and the literal string\g\l\o\bwas emitted, a latent bug, not security-relevant.){ comment },.commentmust be a string with no line terminators (line terminators would end the shell comment and resume command parsing, same injection shape).- Any other object shape,
TypeError.
The fix is allowlist-based rather than a targeted regex tweak, so it closes the reported vector and forecloses adjacent ones (U+2028 / U+2029 line separators in .op, line terminators in comments, unknown-shape objects coerced through .replace).
Frequently Asked Questions
- What is CVE-2026-9277? CVE-2026-9277 is a critical-severity command injection vulnerability in shell-quote (npm), affecting versions >= 1.1.0, <= 1.8.3. It is fixed in 1.8.4. Untrusted input is inserted into a command that is later executed by the application, allowing the attacker to alter the intent of that command.
- How severe is CVE-2026-9277? CVE-2026-9277 has a CVSS score of 8.1 (Critical). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
- Which versions of shell-quote are affected by CVE-2026-9277? shell-quote (npm) versions >= 1.1.0, <= 1.8.3 is affected.
- Is there a fix for CVE-2026-9277? Yes. CVE-2026-9277 is fixed in 1.8.4. Upgrade to this version or later.
- Is CVE-2026-9277 exploitable, and should I be worried? Whether CVE-2026-9277 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
- What actually determines whether CVE-2026-9277 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
- How do I fix CVE-2026-9277? Upgrade
shell-quoteto 1.8.4 or later.