CVE-2025-69264 is a high-severity (CVSS 8.8) CWE-693 vulnerability in pnpm. A fix is available for pnpm — see the affected versions and patch details below.
pnpm v10+ Bypass "Dependency lifecycle scripts execution disabled by default"
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
- A successful exploit gives an attacker total control of the affected component, not partial access.
Exploitation and automatability from CISA’s SSVC triage for CVE-2025-69264.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
Where this sits among everything scored
Real-World Exposure
How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.
pnpmnpmDescription
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)
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)
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:
prepareprepublishprepack
Attack vectors:
git+https://github.com/attacker/malicious.gitgithub:attacker/maliciousgitlab:attacker/maliciousbitbucket:attacker/maliciousgit+ssh://[email protected]/attacker/malicious.gitgit+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:
-
Extract the attached poc.zip
-
Run the PoC script:
cd poc chmod +x run-poc.sh ./run-poc.sh -
Verify the marker file was created by the malicious script:
cat /tmp/pnpm-vuln-poc-marker.txt
Manual reproduction:
-
Create a malicious package with a
preparescript:{ "name": "malicious-pkg", "version": "1.0.0", "scripts": { "prepare": "node -e \"require('fs').writeFileSync('/tmp/pwned.txt', 'RCE!')\"" } } -
Initialize it as a git repo and commit the files
-
Create a victim project that depends on it (just have to make sure it actually git clones and not just downloads a tarball):
{ "dependencies": { "malicious-pkg": "git+file:///path/to/malicious-pkg" } } -
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:
- 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
onlyBuiltDependenciesconfiguration does not affect git dependencies
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 📦npm | pnpm | ≥ 10.0.0&&< 10.26.0 | 10.26.0npm install pnpm@10.26.0 |
Affected Products
pnpmpnpmDetection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for pnpm, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update pnpm to 10.26.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2025-69264 is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
Fixing This On Your OS
If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.
Mitigation for this issue is either not available or the currently available options do not meet the Red Hat Product Security criteria comprising ease of use and deployment, applicability to widespread installation base or stability.Source: Red Hat security advisory for CVE-2025-69264 (CC BY 4.0)
Frequently Asked Questions
Is CVE-2025-69264 in your dependencies?
Find it across npm, including transitive dependencies.