Skip to main content

shell-quote CVE-2026-102422

| EUVDEUVD-2026-88629 CRITICAL
OS Command Injection (CWE-78)
2026-09-29 harborist GHSA-pqg4-j6r4-53mv
9.2
CVSS 4.0 · Vendor: harborist
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Identify app using shell-quote with comment/parse pattern
  2. Delivery
    Craft input with line terminator + shell payload
  3. Exploit
    quote() emits comment that fails to neutralize later token
  4. Execution
    Terminator ends comment, payload becomes shell input
  5. Persist
    Shell executes arbitrary command
  6. Impact
    Full command execution in app context

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A05:2025 - Injection
ASVS 5.0
V1 - Encoding and Sanitization OS command sanitization, avoid shell exec
MITRE ATT&CK

2 techniques across 1 tactic: Execution

The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up.

Exploitation Conditions

Exploitation requires the downstream application (not shell-quote's defaults) to call quote() with a { comment } token followed by a string that includes attacker-controlled data, or to use the quote(parse(untrustedCommand).concat(untrustedArg)) idiom where parse() emits a mid-word '#' comment token (e.g. from a URL fragment). The attacker must inject a line terminator (\n, \r, U+2028, or U+2029) followed by shell syntax into that later string, and the resulting string must actually be executed by a POSIX-family shell (sh, bash, dash, ksh, zsh). Limiting factors: the flaw is not triggerable against a bare default install - it needs the specific vulnerable calling pattern, so real exposure depends on how each dependent project uses the library; upgrading to shell-quote 1.11.0 makes quote() throw a TypeError in these cases.

Impact

This is a genuine command-injection flaw (CWE-78) in shell-quote, a foundational Node.js utility, and the vendor CVSS 4.0 score of 9.2 (AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H) reflects the potential for full shell execution. However, the raw score overstates broad real-world risk because the vulnerability is a library defect that is only exploitable when the CALLING application uses a specific, non-default pattern: passing untrusted data through quote() with a { comment } token followed by an untrusted string, or the quote(parse(untrusted).concat(untrustedArg)) idiom. The AT:P (Attack Requirements: Present) metric captures exactly this - exploitation is conditional on how the downstream code is written, not on default library behavior. EPSS is not provided, the CVE is NOT in CISA KEV, and no public standalone exploit is identified (only regression tests ship with the fix), so there is no signal of active or widespread exploitation. Signals are internally consistent: high technical impact but a conditional, developer-dependent trigger. Treat as a real fix-forward priority for any project that constructs shell strings from user input via shell-quote, but not an emergency mass-exploitation event. Note also this is an INCOMPLETE-FIX follow-up to CVE-2026-9277, which only rejected line terminators inside the comment's own text.

Exploit ScenarioDerived

An application builds a shell command from user-controlled input using shell-quote's quote(), where a { comment } token is followed by an attacker-influenced string (or uses quote(parse(untrustedCommand).concat(untrustedArg))). The attacker supplies a value containing a line terminator followed by shell code (e.g. 'a\nid;#'); the terminator ends the injected '#' comment and the remainder is parsed and executed by sh/bash/dash/ksh/zsh. No standalone public exploit is identified, but the security advisory's regression tests demonstrate the technique concretely.

Act Now Prioritize within 24-48h. Why: CRITICAL severity + public POC available.
1 public PoC Patch available 0.4% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv2 – Sep 29, 2026

Command injection in the Node.js shell-quote library (formerly published as shell-quote on npm) allows an attacker who controls a string placed after a { comment } token to break out of the generated shell command and execute arbitrary shell input. The flaw affects the quote() function before version 1.11.0: a line terminator (\n, \r, U+2028 or U+2029) inside a later string terminates the '#' comment emitted for the comment token, causing the remainder of that string to be interpreted as shell syntax - for example quote(['echo','ok',{comment:'x'},'a\nid;#']) executes id under sh, bash, dash, ksh and zsh. It is also reachable through the quote(parse(untrustedCommand).concat(untrustedArg)) idiom, because parse() emits a mid-word comment token for inputs such as a URL fragment (http://example.com/#frag). This is a genuine command-injection flaw (CWE-78) in a foundational Node.js utility; the vendor CVSS 4.0 score of 9.2 reflects the potential for full shell execution, though our independent CVSS 3.1 assessment is AV:N/AC:H (the vulnerable calling pattern is a prerequisite and is not present in a bare default install). No public exploit was identified at time of analysis and the issue is not in CISA KEV; the upstream fix commit includes test cases that demonstrate the triggering payload shapes. Vendor-released patch: shell-quote 1.11.0.

Earlier versions of this analysis (1)
v1 Sep 29, 2026 - 04:20 CVSS 8.1

Command injection in the npm package shell-quote (ljharb) before 1.11.0 lets attacker-influenced text that follows a { comment } token escape the emitted shell comment and be executed by sh, bash, dash, ksh, or zsh. The quote() function renders a comment token as # plus its text, commenting out the rest of the shell line - including the opening quote of any later string token - so a line terminator (\n, \r, U+2028, U+2029) inside that later string terminates the comment and causes the remainder to be parsed as shell input; quote(['echo', 'ok', { comment: 'x' }, 'a\nid;#']) runs id. It is not exploitable against default library usage: a downstream application must call quote() with a comment token followed by an attacker-influenced string containing a line terminator, or concatenate untrusted data onto parse() output (which itself emits a comment token for a mid-word #, such as a URL fragment), and the resulting string must actually be executed by a POSIX-family shell - hence the assessed AV:N/AC:H/PR:N vector. No public exploit code identified at time of analysis; vendor patch is available in 1.11.0 (upstream commit 6002b2ed).

RemediationAI

Upgrade to shell-quote 1.11.0, the vendor-released fix, which makes quote() throw a TypeError when any string following a { comment } token contains a line terminator; the patch commit is https://github.com/ljharb/shell-quote/commit/6002b2ed90c6b83095eb272b6b0adaf3a172b0bc and the advisory is https://github.com/ljharb/shell-quote/security/advisories/GHSA-pqg4-j6r4-53mv. Because shell-quote is typically a transitive dependency, run an npm audit / dependency-tree review and force resolution (e.g. npm overrides or yarn resolutions) to 1.11.0 for every consumer; note that 1.11.0 intentionally introduces a new TypeError failure mode, so callers that legitimately embed newlines after a comment token must rework their tokenization rather than swallow the exception. If upgrading is not immediately possible, the actionable compensating controls are: stop passing user-controlled strings in positions after a { comment } token, and strip or reject \n, \r, U+2028 and U+2029 from any value that will follow a comment (trade-off: altering argument content may change program behavior for legitimate multi-line arguments); avoid the quote(parse(untrustedCommand).concat(untrustedArg)) idiom entirely, since parse() can emit a mid-word '#' comment token from harmless-looking input such as a URL fragment (trade-off: requires refactoring argument construction); sanitize or pre-encode untrusted values before concatenation so the mid-word '#' cannot appear; and run the Node process under a least-privilege user with restricted PATH so that a successful injection yields limited shell capability. Note that no vendor-released patch for pre-1.11.0 branches was identified - the fix is version 1.11.0 only - and there is no public exploit identified at time of analysis, so prioritization should be based on whether your dependency tree reaches 1.11.0 and whether your code uses the affected calling patterns.

Affected Packages

npm shell-quote fix: 1.11.0

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in npm

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

shell-quote is a widely depended-upon npm utility for parsing and quoting shell command strings in Node.js. Its quote() function serializes an array of tokens back into a shell-safe command line: strings are single-quoted with escaping, while { op: ... } objects emit operators and { comment: 'text' } objects emit '#' followed by the comment text, which in a POSIX shell comments out the remainder of the physical line. The root cause is CWE-78 (improper neutralization of special elements used in an OS command): quote() assumed the comment it emitted would consume the rest of the line and therefore did not consider that a line terminator in a *later* string token could re-open parsing. When quote() reaches a subsequent string containing \n, \r, U+2028 or U+2029, the comment ends at the terminator, the single-opening-quote for that string has already been swallowed by the comment, and the string's remaining characters are emitted unquoted and unescaped into the command - yielding arbitrary shell syntax. This is an incomplete fix: CVE-2026-9277 previously hardened the comment's own text against line terminators but did not extend the check to tokens appearing after the comment. The upstream commit 6002b2ed90c6b83095eb272b6b0adaf3a172b0bc addresses this by tracking a sawComment flag in quote.js and throwing a TypeError('a token after a comment must not contain line terminators') when any later string matches LINE_TERMINATORS, with corresponding documentation updates in README.md, quote.d.ts and regression tests in test/quote.js. The same commit's tests confirm that parse('curl http://x/#frag').concat('a\nid;#') reproduces the injection path, because parse() treats a '#' in the middle of a word as a comment token. Per CPE/ecosystem data the affected component is the npm package shell-quote (https://www.npmjs.com/package/shell-quote) at versions below 1.11.0.

Know when npm gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (harborist) PRIMARY 9.2 HIGH
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
vuln.today AI 8.1 HIGH

AC:H because exploitation depends on the app using the specific comment/parse() pattern (not default); PR:N/UI:N as untrusted input alone triggers it; C/I/A:H reflect arbitrary shell command execution.

3.1 AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
4.0 AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Red Hat 8.1 HIGH

Primary rating from Vendor (harborist).

CVSS VectorVendor: harborist

Attack Vector
Network
Attack Complexity
Low
Attack Requirements
Present
Privileges Required
None
User Interaction
None
Vulnerable system: Confidentiality
High
Vulnerable system: Integrity
High
Vulnerable system: Availability
High
Subsequent system: Confidentiality
None
Subsequent system: Integrity
None
Subsequent system: Availability
None

Lifecycle Timeline

3
Severity Changed
Sep 29, 2026 - 04:22 NVD
HIGH CRITICAL
CVSS changed
Sep 29, 2026 - 04:22 NVD
8.1 (HIGH) 9.2 (CRITICAL)
CVE Published
Sep 29, 2026 - 03:47 cve.org
HIGH 8.1

DescriptionCVE.org

shell-quote's quote() function emits a { comment } token as # followed by its text, which comments out the rest of the shell line, including the opening quote of any later string token. A line terminator (\n, \r, U+2028, U+2029) in that later string therefore ends the comment, and the rest of the string is parsed as shell input: quote(['echo', 'ok', { comment: 'x' }, 'a\nid;#']) runs id in sh, bash, dash, ksh and zsh. parse() emits a comment token for a # in the middle of a word (for example http://example.com/#frag), so callers that combine parse() output with another untrusted string, such as quote(parse(untrustedCommand).concat(untrustedArg)), are affected. The fix for CVE-2026-9277 rejected line terminators in the comment's own text, but not in the tokens after it. Fixed in 1.11.0: quote() throws a TypeError when a string after a { comment } token contains a line terminator.

Technical POC Analysis

CWE-78 OS command injection.

Full technical POC analysis - root cause, step-by-step exploitation and patch breakdown - is part of the Pro and Business plans.

Latest POC

1 public PoC link from github

Sign in to open the public PoC links collected for this CVE.

Executive ViewAI

Why It Matters

The Node.js shell-quote library (versions before 1.11.0) contains a critical command injection vulnerability that allows attackers to execute arbitrary shell commands when untrusted input is processed after a comment token. Organizations using this foundational utility in build scripts, CLIs, or server-side command construction are at risk of full system compromise, data theft, and lateral movement. Leadership should prioritize immediate remediation given the severity and broad dependency footprint.

Business Impact: Severe
Compensating Controls

Apply vendor patch.

Threat Intelligence Overview

EPSS Score
0.4%
Top 70% exploitable
Prevalence
Ubiquitous
shell-quote is a very widely depended-on npm shell-argument library
Threat Intel
1
1 source
Social Media
2
Sightings
Data Quality
6 sources
Confidence: High
EUVD NVD CVE.org EPSS Vulnrichment GHSA Vendor CIRCL GitHub VulDB

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity CRITICAL
CISA KEV No
Public POC Yes
EPSS 0.4%
Patch available Yes
Active threat No
Deciding rule
CRITICAL severity + public POC available
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision
Out-of-Cycle
Exploitation
None
System Exposure· derived
Open
Automatable
No
Human Impact
Very High
Technical Impact
Total

Priority Score

66
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +46
PoC: +20
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

OS command injection occurs when an application passes unsanitized user input directly into system shell commands.

More in npm

View all
CVE-2021-43616 CRITICAL POC
9.8 Nov 13

The npm ci command in npm 7.x and 8.x through 8.1.3 proceeds with an installation even if dependency information in pack

CVE-2026-61568 CRITICAL POC
9.6 Sep 15

DNS rebinding against the local Streamable HTTP MCP listener in @zereight/mcp-gitlab before 2.1.30 lets a malicious web

CVE-2026-101894 CRITICAL POC
9.1 Sep 28

Archive extraction in the Node.js decompress package allows a crafted archive containing chained symlink entries to reso

CVE-2026-91127 HIGH POC
8.2 Sep 18

The legacy DOC renderer in File Viewer emits document-controlled hyperlink targets into generated HTML after character e

CVE-2026-102826 HIGH POC
8.1 Sep 29

Untrusted git configuration includes reachable through simple-git before 4.0.0 let an attacker execute arbitrary command

CVE-2026-102281 HIGH POC
7.5 Sep 28

A remote, unauthenticated denial-of-service condition in the NestJS (Nest) microservices framework lets an attacker cras

CVE-2026-102278 HIGH POC
7.5 Sep 28

Deeply nested brace patterns cause unbounded recursion in the npm brace-expansion library, exhausting the native stack a

CVE-2026-102276 HIGH POC
7.5 Sep 28

Stack exhaustion in the npm library brace-expansion (all versions prior to 1.1.19, 2.1.5, 3.0.7, and 5.0.10) lets a craf

CVE-2026-101910 MEDIUM POC
6.9 Sep 28

The JavaScript library ip-address (npm) fails to treat the NAT64 local-use prefix 64:ff9b:1::/48 as private, so applicat

CVE-2026-101912 MEDIUM POC
6.3 Sep 28

Cross-family subnet comparisons in the ip-address npm library (all versions before 10.7.1) can cause isInSubnet and isHo

CVE-2026-101911 MEDIUM POC
6.3 Sep 28

Denial of service in the ip-address JavaScript/npm library (all versions prior to 10.7.1) lets remote attackers stall or

CVE-2026-51996 CRITICAL
9.8 Sep 24

A credential-isolation flaw in geelen mcp-remote 0.1.16 through 0.1.38 allows a remote attacker who controls or can pred

Vendor StatusVendor

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy