Mar 7, 2026·5 min read·0 visits
The shescape library failed to recursively resolve symbolic links for shell paths, leading to potential shell misidentification. This mismatch allows attackers to bypass argument escaping and execute arbitrary commands (RCE). Fixed in version 2.1.9.
A high-severity vulnerability exists in the `shescape` npm package (versions prior to 2.1.9) due to improper resolution of symbolic link chains when identifying the system shell. This flaw allows the library to misidentify the target shell, applying incorrect escaping rules. Attackers can exploit this to bypass protections and inject arbitrary OS commands if the application executes commands in a shell configured via a symlink chain.
The shescape library is a security-focused tool designed to sanitize user input for safe inclusion in shell commands. It operates by identifying the target shell (e.g., Bash, PowerShell, CMD) and applying the specific escaping syntax required by that interpreter. Correct identification of the shell is paramount; applying Bash escaping rules to a Windows CMD environment, or vice versa, typically results in incomplete protection.
The vulnerability, tracked as GHSA-6f6w-6j58-rq76, resides in the logic responsible for determining the shell type from a file path. Specifically, the library failed to handle "link chains"—scenarios where a symbolic link points to another symbolic link. When the configured shell path involved multiple layers of indirection, shescape would halt resolution prematurely. This resulted in the library making security decisions based on an intermediate link name rather than the final executable, leading to the application of incorrect escaping strategies.
The root cause is an Incorrect Comparison (CWE-697) stemming from shallow symbolic link resolution. When an application invokes shescape, it may provide a path to a shell, or rely on the system default. On many Unix-like systems, standard shell paths are often symlinks (e.g., /usr/bin/sh might link to /bin/dash or /bin/bash depending on the distribution and configuration tools like update-alternatives).
Prior to version 2.1.9, shescape likely utilized a non-recursive method to resolve the path (such as a single call to readlink or checking the filename directly). If the path was a chain (Link A -> Link B -> Executable), the library would inspect Link B rather than the Executable. If Link B's name suggested a different shell flavor than the final Executable, shescape would select the wrong escaping module. Consequently, input containing characters special to the actual shell might be passed through unescaped because they are safe in the misidentified shell, resulting in OS Command Injection (CWE-78).
The remediation involved switching from a shallow resolution strategy to a fully recursive one. The logic must follow the symbolic link chain until it terminates at a canonical file path.
Vulnerable Logic (Conceptual): In the vulnerable versions, the code likely inspected the immediate target of a link or the path string itself without verifying the final destination on disk. This is insufficient for deep system configurations.
// Conceptual representation of the flaw
const shellPath = "/usr/local/bin/myshell"; // Symlink -> /bin/sh -> /bin/dash
// Flawed: Only resolves one level or relies on the name 'myshell'
// Result: Might default to generic 'sh' escaping or fail to identify 'dash' specificities
const shellName = path.basename(shellPath);
if (shellName === 'sh') {
applyShEscaping();
}Fixed Logic (v2.1.9): The fix, implemented in PR #2388, forces the library to resolve the real path recursively. This ensures that no matter how many symlinks exist in the chain, the decision is based on the actual binary that will execute the command.
// Corrected: Fully resolves the chain to the final executable
// Result: Resolves to '/bin/dash', allowing correct identification
const realPath = fs.realpathSync(shellPath);
const actualShellName = path.basename(realPath);
if (actualShellName === 'dash') {
applyDashEscaping();
}By using recursive resolution (mechanically similar to realpath), the library guarantees that the escaping rules match the runtime environment exactly.
Exploitation requires the application to use shescape in an environment where the shell path is a symlink chain. This is a common configuration in Linux environments utilizing package managers that manage shell alternatives.
Attack Scenario:
/bin/sh links to /etc/alternatives/sh, which links to /bin/zsh.shescape inspects /bin/sh and assumes the target is a standard Bourne shell, applying basic sh escaping.zsh, which has different parsing rules for certain expansions or globbing characters compared to a strict POSIX sh.sh escaping does not neutralize. The input is passed to the shell, interpreted as code, and executed.While the attack complexity is low (no authentication or race conditions required), the environmental prerequisite (symlink chains) acts as a limiting factor for widespread indiscriminate exploitation.
The impact of this vulnerability is critical, rated at CVSS 8.7 (High).
shescape.This is a classic Command Injection scenario where the mitigation layer (the escaping library) fails silently, leaving the application fully exposed.
The vulnerability is addressed in shescape version 2.1.9. Developers utilizing this library must upgrade immediately to ensure safe shell argument handling.
Immediate Actions:
npm install shescape@latest or specifically npm install shescape@2.1.9.package-lock.json or yarn.lock reflects the updated version to prevent regression during CI/CD builds.shescape is used correctly. While the patch fixes the identification bug, developers should strictly limit the use of shell execution (child_process.exec) in favor of child_process.execFile or spawn where arguments are passed as arrays, bypassing the shell entirely. Using execFile or spawn is the most effective architectural mitigation against shell injection.CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
shescape ericcornelissen | < 2.1.9 | 2.1.9 |
| Attribute | Detail |
|---|---|
| CVE / GHSA ID | GHSA-6f6w-6j58-rq76 |
| CWE ID | CWE-78 (OS Command Injection) |
| Secondary CWE | CWE-697 (Incorrect Comparison) |
| CVSS Score | 8.7 (High) |
| Attack Vector | Network |
| Impact | Remote Code Execution (RCE) |
Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')