GitHub Advisoryadvisory · npm
GHSA-379q-355j-w6rj pnpm v10+ Bypass "Dependency lifecycle scripts execution disabled by default"
HIGH
Official page ↗
- Aliases
- CVE-2025-69264
- Ecosystem
- npm
- Packages
- pnpm
- Severity
- High
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
- Weaknesses
- CWE-693
- Reviewed
- 2026-01-07
Affected packages
• npm pnpm: >= 10.0.0, < 10.26.0 → fixed in 10.26.0
Description
pnpm v10+ Git Dependency Script Execution Bypass
Summary
A security bypass vulnerability in pnpm v10+ allows git-hosted dependencies to execute arbitrary code during `pnpm install`, circumventing the v10 security feature "Dependency lifecycle scripts execution disabled by default". While pnpm v10 blocks `postinstall` scripts via the `onlyBuiltDependencies` mechanism, git dependencies can still execute `prepare`, `prepublish`, and `prepack` scripts during the fetch phase, enabling remote code execution without user consent or approval.
Details
pnpm v10 introduced a security feature to disable dependency lifecycle scripts by default (PR #8897). This is implemented by setting `onlyBuiltDependencies = []` when no build policy is configured:
File: `pkg-manager/core/src/install/extendInstallOptions.ts` (lines 290-291)
```typescript
if (opts.neverBuiltDependencies == null && opts.onlyBuiltDependencies == null && opts.onlyBuiltDependenciesFile == null) {
opts.onlyBuiltDependencies = []
}
```
This creates an allowlist that blocks all packages from running scripts during the BUILD phase in `exec/build-modules/src/index.ts`.
However, git-hosted dependencies are processed differently. During the FETCH phase, git packages are prepared using `preparePackage()`:
File: `exec/prepare-package/src/index.ts` (lines 28-57)
```typescript
export async function preparePackage (opts: PreparePackageOptions, gitRootDir: string, subDir: string) {
// ...
if (opts.ignoreScripts) return { shouldBeBuilt: true, pkgDir } // Only checks ignoreScripts, not onlyBuiltDependencies
const execOpts: RunLifecycleHookOptions = {
// ...
rawConfig: omit(['ignore-scripts'], opts.rawConfig), // Explicitly removes ignore-scripts!
}
// Runs npm/pnpm install
await runLifecycleHook(installScriptName, manifest, execOpts)
// Runs prepare scripts
for (const scriptName of PREPUBLISH_SCRIPTS) { // ['prepublish', 'prepack', 'publish']
await runLifecycleHook(newScriptName, manifest, execOpts)
}
}
```
The `ignoreScripts` option defaults to `false` and is completely separate from `onlyBuiltDependencies`. The `onlyBuiltDependencies` allowlist is never consulted during the fetch phase.
Affected scripts that execute during fetch:
• `prepare`
• `prepublish`
• `prepack`
Attack vectors:
• `git+https://github.com/attacker/malicious.git`
• `github:attacker/malicious`
• `gitlab:attacker/malicious`
• `bitbucket:attacker/malicious`
• `git+ssh://[email protected]/attacker/malicious.git`
• `git+file:///path/to/local/repo`
PoC
Prerequisites:
• pnpm v10.0.0 or later (tested on v10.23.0 and v11.0.0-alpha.1)
• git
Steps to reproduce:
1. Extract the attached poc.zip
2. Run the PoC script:
```bash
cd poc
chmod +x run-poc.sh
./run-poc.sh
```
3. Verify the marker file was created by the malicious script:
```bash
cat /tmp/pnpm-vuln-poc-marker.txt
```
Manual reproduction:
1. Create a malicious package with a `prepare` script:
```json
{
"name": "malicious-pkg",
"version": "1.0.0",
"scripts": {
"prepare": "node -e \"require('fs').writeFileSync('/tmp/pwned.txt', 'RCE!')\""
}
}
```
2. Initialize it as a git repo and commit the files
3. Create a victim project that depends on it (just have to make sure it actually git clones and not just downloads a tarball):
```json
{
"dependencies": {
"malicious-pkg": "git+file:///path/to/malicious-pkg"
}
}
```
4. Run `pnpm install` - the prepare script executes without any warning or approval prompt
Impact
Severity: High
Who is impacted:
• All pnpm v10+ users
• Users who believed they were protected by the v10 "scripts disabled by default" feature
• CI/CD pipelines
Attack scenarios:
1. Supply chain attack: An attacker compromises a dependency, adding to it a malicious git dependency that executes arbitrary code during `pnpm install`
What an attacker can do:
• Execute arbitrary code with the victim's privileges
• Exfiltrate environment variables, secrets, and credentials
• Modify source code or inject backdoors
• Establish persistence or reverse shells
• Access the filesystem and network
Why this bypasses security expectations:
• pnpm v10 changelog explicitly states "Lifecycle scripts of dependencies are not executed during installation by default"
• Users expect git dependencies to follow the same security model as npm registry packages
• There is no warning that git dependencies are treated differently
• The `onlyBuiltDependencies` configuration does not affect git dependencies
Related
Alias · CVE (1)
- CVE-2025-69264 pnpm is a package manager. vulnerability
Weakness · CWE (1)
- CWE-693 Protection Mechanism Failure weakness