Full Report
Supply chain attacks are very common within package managers, such as node package manager (npm). Malware commonly uses the npm scripts, such as postinstall, preinstall and other methods. In order to protect yourself, npm has a flag called --ignore-scripts. This article goes into bypassing this protection. An npm package can export executable files which can easily be ran. Then, the path for this execution is added to the global $PATH variable when executing npm scripts. This is used through environments like typescript, webpack and other things. So, this begs the question: "what if an attacker attached their own binary to export node or npm?" It turns out, that this is completely possible! This bypasses the --ignore-scripts on installation since the binary has nothing to do with the install scripts. The package.json file simply has the field bin set to npm and node with a bash script to run the custom code. npm promptly fixed this vulnerability but the author claims that there are likely other variants of this out there. Additionally, it doesn't look like any package was using this in a malicious way at the moment, Overall, it's a really good post with a simple bug. If you're looking to find yourself a CVE, this seems ripe for the picking.
Analysis Summary
# Vulnerability: npm 'bin' Field Hijacking Bypasses Script Ignoring
## CVE Details
- CVE ID: Not explicitly assigned in the provided text. The article suggests this is "ripe for the picking."
- CVSS Score: Not explicitly provided.
- CWE: CWE-78 (Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')) is strongly implied through the shell script execution hijacking.
## Affected Systems
- Products: npm package installations/environments using `npm install`.
- Versions: Unspecified, but affects any version of NPM that supports the `bin` field functionality as described.
- Configurations: Any environment running subsequent `npm` scripts (e.g., `npm start`, `npm test`) after a malicious package is installed, even if the initial installation used `--ignore-scripts`.
## Vulnerability Description
This vulnerability, termed "bin script confusion," exploits the `npm` package management feature where packages can define executable files via the `bin` field in `package.json`. These executables are symlinked into `node_modules/.bin`, which subsequently modifies the system `$PATH` when running `npm` scripts (like `postinstall`, `preinstall`, or lifecycle scripts).
An attacker can create a package that sets its `bin` exports to names matching critical executables, specifically `'npm'` and `'node'`. When a user installs this package—even suppressing installation scripts using `npm install --ignore-scripts`—the package's malicious binaries (e.g., a payload shell script) are placed in `$PATH`. Subsequent executions of any `npm` command (even unrelated ones like `npm start` or `npm install <another_package>`) will invoke the attacker's binary instead of the system executable, leading to arbitrary code execution.
## Exploitation
- Status: Proof-of-Concept (PoC) available and demonstrated (`npm-bin-script-poc`).
- Complexity: Low. Requires a simple package structure and relies on standard package installation mechanisms.
- Attack Vector: Local (requires package installation, but execution is triggered by common CLI commands).
## Impact
- Confidentiality: High (Arbitrary code execution allows data exfiltration).
- Integrity: High (Arbitrary code execution allows system modification or further compromise).
- Availability: High (System compromise or denial of service via executed payload).
## Remediation
### Patches
- Npm officially stated they consider this functionality "working as designed" and have no current plans to fix it, as changing it would break many existing workflows relying on default `bin` behavior.
### Workarounds
1. **Use `--bin-scripts=false`**: Developers can use this flag during installation (e.g., `npm install --bin-scripts=false <package>`).
* **Caveat**: This workaround is fragile. It is *not* sticky on a per-package basis, and running dependency updates like `npm ci` will re-enable the behavior.
2. **Avoid Running Subsequent npm Scripts**: Be cautious about running subsequent `npm` commands (especially those involving lifecycle scripts) after installing a package from an untrusted source, even if scripts were ignored during the initial install.
3. **Limit Tool Usage**: Completely avoiding the use of package binaries (e.g., running `webpack` or `typescript` commands directly from node_modules/.bin) may reduce risk, but this is often impractical for modern toolchains.
## Detection
- **Indicators of Compromise (IOCs)**: The presence of suspicious executables named 'npm' or 'node' within the `.bin` directory of any installed package's `node_modules` folder.
- **Detection Methods and Tools**: Socket Security's free GitHub app is cited as a tool capable of detecting this specific risk in `package.json` files before dependencies are installed.
## References
- Vendor Advisories: GitHub/npm considers this "working as designed."
- Relevant Links:
- Socket Blog Post (Defanged): htt ps://socket d ev/blog/npm-bin-script-confusion
- PoC Package (Defanged): htt ps://socket d ev/npm/package/npm-bin-script-poc