CVE-2026-9277: Shell quote Shell-quote Quote() Does Not Escape Vulnerability
CRITICALCVE-2026-9277 is a CRITICAL (CVSS 8.1) shell-quote quote() does not escape vulnerability (CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')) affecting Shell quote libraries in the npm ecosystem. The issue involves shell-quote quote() does not escape newlines in object .op values. Remediation is available by upgrading affected packages to version 1.8.4.
CVE-2026-9277 at a Glance
Security Impact
CVSS: 8.1
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H).
How to Fix CVE-2026-9277
To remediate this vulnerability, upgrade all affected Shell quote dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
npm install shell-quote@1.8.4
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
npm ls shell-quote
How to Check if You Are Affected
To determine whether your Node.js application is affected by CVE-2026-9277, inspect your project dependencies using npm:
npm ls shell-quote
Analyze the terminal output to locate any version of Shell quote in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.8.4), your application is affected.
Note: The npm ls shell-quote command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection'), where the product constructs all or part of an os command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended os command when it is sent to a downstream component. In Shell quote, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-9277 Affected Shell quote Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
shell-quote
|
npm |
≥ 1.1.0
< 1.8.4
|
1.8.4
|
References
Frequently Asked Questions
What is CVE-2026-9277?
Which Shell quote versions are affected?
What version fixes CVE-2026-9277?
Is shell-quote affected?
What is the CVSS score of CVE-2026-9277?
What CWE is associated with CVE-2026-9277?
How can I check npm dependencies for CVE-2026-9277?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-w7jw-789q-3m8p",
"modified" : "2026-06-09T14:27:15Z",
"published" : "2026-06-09T14:27:15Z",
"aliases" : [ "CVE-2026-9277" ],
"summary" : "shell-quote quote() does not escape newlines in object .op values",
"details" : "### Summary\n\n`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.\n\nThe 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:\n\n1. **Direct construction.** A caller builds `{ op: '...\\n...' }` from external input (e.g. a deserialized argument array) and passes it to `quote()`.\n2. **`envFn` return.** `parse(cmd, envFn)` is documented to splice the return value of `envFn` into the result array when it is an object. An attacker-influenced data source consulted by `envFn` can introduce an object token whose `.op` reaches `quote()`.\n\n### Impact\n\nShell 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.\n\n### PoC\n\n```js\nconst { parse, quote } = require('shell-quote');\n\n// Direct construction\nquote([{ op: ';\\nid' }]);\n// → \"\\;\\n\\\\i\\\\d\" ← literal newline; second line executes as a command\n\n// Via parse() with an envFn returning attacker-shaped objects\nconst tokens = parse('echo $X', () => ({ op: ';\\nid' }));\nrequire('child_process').execSync(quote(tokens), { shell: true });\n// Executes `id` after `echo \\;`.\n```\n\nConfirmed under `sh`, `bash`, `dash`, and `zsh`.\n\n### Patch\n\nFixed by replacing the per-character escape with strict shape validation in `quote()`. The object-token branch now:\n\n- **`{ op }`** — `.op` must be a string from the same allowlist the parser emits (`||`, `&&`, `;;`, `|&`, `<(`, `<<<`, `>>`, `>&`, `<&`, `&`, `;`, `(`, `)`, `|`, `<`, `>`). Anything else throws `TypeError`. This is the direct fix for the reported issue and removes the entire class of `.op` injection.\n- **`{ op: 'glob', pattern }`** — `.pattern` must 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\\b` was emitted — a latent bug, not security-relevant.)\n- **`{ comment }`** — `.comment` must be a string with no line terminators (line terminators would end the shell comment and resume command parsing — same injection shape).\n- **Any other object shape** — `TypeError`.\n\nThe 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`).\n\n### Workarounds\n\nPrior 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.\n\n### Credits\n\nReported by Akshat Sinha",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H"
}, {
"type" : "CVSS_V4",
"score" : "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "npm",
"name" : "shell-quote"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "1.1.0"
}, {
"fixed" : "1.8.4"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 1.8.3"
}
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/ljharb/shell-quote/security/advisories/GHSA-w7jw-789q-3m8p"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-9277"
}, {
"type" : "WEB",
"url" : "https://github.com/ljharb/shell-quote/commit/1518179"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/ljharb/shell-quote"
}, {
"type" : "WEB",
"url" : "https://www.npmjs.com/package/shell-quote"
}, {
"type" : "WEB",
"url" : "http://www.openwall.com/lists/oss-security/2026/05/23/2"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-77", "CWE-78" ],
"severity" : "CRITICAL",
"github_reviewed" : true,
"github_reviewed_at" : "2026-06-09T14:27:15Z",
"nvd_published_at" : "2026-05-22T14:16:30Z"
}
}