Jul 25, 2026·5 min read·8 visits
Unescaped parentheses in shescape on Windows allow attackers to bypass shell escaping and execute arbitrary OS commands when input is processed within parenthesized cmd.exe blocks.
A critical command injection vulnerability in the shescape npm library affects Windows systems when running shell commands using cmd.exe. The escaping function fails to neutralize parentheses, allowing attackers to close shell blocks and execute arbitrary commands.
The shescape npm package is a utility designed to escape command arguments to prevent shell injection vulnerabilities in Node.js applications. This type of mitigation is critical when executing system commands where input is controlled by external users. Applications running on Windows environments that configure shescape to escape arguments for the Windows Command Prompt (cmd.exe) are affected by a severe defense evasion flaw.\n\nThe vulnerability arises due to the improper neutralization of parenthesis characters during the escaping process. When shescape is executed on Windows with CMD as the target shell, it fails to escape ( and ) characters. This omission allows an attacker to inject syntax-grouping tokens that bypass input validation controls.\n\nThe primary weakness belongs to CWE-150 (Improper Neutralization of Escape, Meta, or Control Sequences), which directly leads to CWE-78 (OS Command Injection). If the application interpolates the escaped input inside a parenthesized shell block, arbitrary commands can be executed with the permissions of the Node.js process.
In the Windows cmd.exe interpreter, parentheses serve as control characters used to define syntax blocks. For example, conditional logic blocks (if/else) and loops (for) wrap their body commands inside parentheses. The CMD parser evaluates the closing parenthesis ) as the boundary marker indicating the end of the active instruction block.\n\nWhen arguments containing parenthesis characters are not escaped, the CMD parser treats them as structural symbols rather than literal string inputs. In an unpatched installation, the shescape library's escaping logic for CMD explicitly ignores the parenthesis characters. This design flaw allows an attacker to submit a payload that terminates the intended block prematurely.\n\nTo construct a successful injection, an attacker provides a payload containing a closing parenthesis ). This terminates the initial command block. The attacker then appends a command separator (such as & or ||), followed by the malicious payload, and closes with an opening parenthesis ( to satisfy syntax requirements. This allows arbitrary system execution.
The vulnerability resides in the Windows CMD escaping implementation located in src/internal/win/cmd.js. In vulnerable versions (v2 before 2.1.14 and v3 before 3.0.1), the regular expression used to identify characters requiring caret-escaping omitted parentheses.\n\njavascript\n// Vulnerable implementation in src/internal/win/cmd.js\nconst specials = new RegExp(/([%&<>^|])/g);\n\n\nThe patch, introduced in commit 43d70b59d09bbe5c3fd02ef08b3a123e977ed9de, modifies the regular expression to explicitly include parentheses:\n\njavascript\n// Patched implementation in src/internal/win/cmd.js\nconst specials = new RegExp(/([%&()<>^|])/g);\n\n\nWith this change, any occurrence of ( or ) is neutralized by prepending a caret (^) character, turning them into ^( and ^). This forces cmd.exe to interpret the parentheses as literal string values rather than structural command-grouping elements.\n\nAdditionally, the developers implemented defensive-in-depth improvements for Unix shells in Dash and Zsh. For example, in src/internal/unix/dash.js, tilde (~) escaping was enhanced to cover cases where a tilde follows a colon (:) or equal sign (=), preventing unintended home directory expansions. In src/internal/unix/zsh.js, the characters #, ^, and {/} were added to the specials list to prevent pattern-matching exploitation when EXTENDED_GLOB is enabled.
Exploitation of GHSA-W4HW-QCX7-56PR requires a specific configuration where shescape output is placed inside parenthesized command blocks. An attacker must target a Node.js application running on a Windows system with cmd.exe as the default execution shell. The application must interpolate user inputs inside a parenthesized block.\n\nmermaid\ngraph LR\n A["Attacker Input: x) else (echo MALICIOUS)"] --> B["shescape.escape()"]\n B --> C["Unescaped output interpolated into command template"]\n C --> D["cmd.exe parses ')' and terminates block"]\n D --> E["Execution of malicious block"]\n\n\nConsider a template command constructed by the application: if defined VAR (echo <INPUT>). If the input is x) else if a==a (echo malicious_payload, the unpatched library outputs the string unmodified. The resulting command evaluated by CMD becomes if defined VAR (echo x) else if a==a (echo malicious_payload). Since the first block completes, the interpreter proceeds to evaluate and execute the injected else block containing the malicious command.
The vulnerability carries a CVSS v4.0 score of 9.2, classifying it as Critical. The attack vector is Network (AV:N), as any remote entry point feeding into the escaping utility can be exploited. Attack complexity is Low (AC:L), requiring only basic string manipulation without specific environmental conditions other than the OS and shell type.\n\nSuccessful exploitation results in arbitrary OS command execution (RCE) with the privileges of the executing Node.js process. Attackers can read sensitive local files, modify system configurations, compromise application databases, or establish persistence. The impact on Confidentiality (VC:H), Integrity (VI:H), and Availability (VA:H) is highly severe.\n\nThe exposure is mitigated by specific requirements (AT:P), meaning the victim system must be Windows using CMD, and the backend command template must utilize parentheses. This specific context limits widespread automatic exploitation but remains highly dangerous for systems matching the profile.
The primary remediation strategy is upgrading the shescape dependency to a patched version. For applications using the v2 release line, upgrade to version 2.1.14 or later. For applications using the v3 release line, upgrade to version 3.0.1 or later.\n\nIf upgrading is not immediately possible, implement strict input validation. Developers should implement a filter that rejects any input containing parenthesis characters before parsing it through shescape:\n\njavascript\nfunction validateInput(input) {\n if (/[\\(\\)]/.test(input)) {\n throw new Error('Invalid input: Parentheses are not permitted.');\n }\n return input;\n}\n\n\nAdditionally, avoid interpolating variables inside parenthesized shell blocks. Restructure execution commands to utilize flat argument arrays or handle logical routing in Javascript rather than delegating logical branching and looping blocks to the command interpreter.
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| Product | Affected Versions | Fixed Version |
|---|---|---|
shescape Eric Cornelissen | < 2.1.14 | 2.1.14 |
shescape Eric Cornelissen | >= 3.0.0, < 3.0.1 | 3.0.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-78, CWE-150 |
| Attack Vector | Network |
| CVSS Score | 9.2 (Critical) |
| EPSS Score | N/A |
| Impact | Arbitrary Code Execution (RCE) |
| Exploit Status | poc |
| KEV Status | Not Listed |
The software constructs an OS command using externally-influenced input, but it fails to neutralize or incorrectly neutralizes special elements that can modify the intended command when sent to a downstream component.
An incomplete escaping vulnerability in the npm package 'shescape' allows unauthenticated users to trigger dynamic shell expansions, absolute path disclosure, and command block break-outs on Unix and Windows systems.
An escaping bypass in the npm package shescape on Unix platforms utilizing the Dash shell can result in unauthorized home directory path disclosure. The vulnerability occurs when user input containing specific sequences is passed inside shell variable assignment contexts. Additionally, the patch addresses secondary security gaps related to Zsh extended globbing and Windows CMD command block breakouts.
A high-severity algorithmic-complexity vulnerability in the Node.js library Shescape leads to a Quadratic-Time Denial of Service (DoS) when flag protection is enabled. By supplying inputs containing repetitive control characters and hyphens, remote attackers can trigger an inefficient nested loop in Shescape's argument-composition logic, blocking the Node.js single-threaded event loop and causing total application Denial of Service.
A multi-vector vulnerability advisory in the OmniFaces JavaServer Faces (JSF) utility library covers flaws leading to unauthenticated arbitrary file access, memory exhaustion (DoS), cross-site scripting (XSS), and WebSocket push channel hijacking.
Oh My Posh prior to version 29.35.1 is vulnerable to terminal escape sequence injection. Dynamic strings from directory names or Git repository metadata are written to the prompt output without neutralization, enabling unauthenticated remote code execution, clipboard hijacking, or terminal DoS when users navigate to malicious folders.
A critical-severity template injection vulnerability in Oh My Posh allows for unauthenticated arbitrary command execution. This issue occurs when a user navigates their shell into a directory whose name contains malicious Go template syntax, which is subsequently parsed and executed by the prompt engine.