// threat brief
pnpm dependency alias path traversal: an indirect dependency can swap project folders for symlinks at install time, even with --ignore-scripts
- CVSS
- 8.8 HIGH
- CISA KEV
- Not listed
- Weakness
- CWE-23
- Topics
- Supply chain
Human review 2026-09-24Command tests: none yetReproduced: not yetVerification record ↓
pnpm didn't block '..' in dependency aliases, so a malicious package deep in the tree can swap project paths for symlinks, even with --ignore-scripts.
| Who is affected | Developers and CI systems running pnpm install with pnpm before 10.34.0, or 11.0.0 up to (not including) 11.4.0. The malicious package can be an indirect dependency you never chose. |
|---|---|
| What happens | The install step itself only changes files: paths such as git hooks, script folders, local GitHub Actions or dist/ can be replaced with attacker content. Later, running git commit, tests, builds, CI steps or publishing may run or package that content. |
| What to do now | Upgrade pnpm to 10.34.0 or later (10.x) or 11.4.0 or later (11.x). The project offers no workaround other than upgrading.View evidence(2)
|
| Affected versions | All versions before 10.34.0; 11.0.0 up to but not including 11.4.0 (per the maintainer GHSA; the CVE structured data says <10.33.4, which contradicts its own description)View evidence: sources disagree(4)
|
| Fixed versions | 10.34.0 or later (10.x); 11.4.0 or later (11.x)View evidence(3)
|
| CVSS vector | Show full vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H |
| Timeline |
|
| CISA KEV | Not listed(Not being in KEV does not mean it has not been exploited)View evidence(2)
|
Blue team playbook
Check, fix / mitigate, respond, harden. Matching the affected versions does not mean you were compromised, and a check that finds nothing does not prove you are safe; each item says what it can and cannot show. Tagged steps point to where the attack flow below can be stopped.
- 01Check your pnpm version
10.x needs 10.34.0 or later, 11.x needs 11.4.0 or later. Check both developer machines and CI, which may pin an older version.
Read-only checkpnpm --version - 02Check whether project paths became symlinks (PlainCVE suggestion)
The project published no detection guidance or indicators of compromise. Based on the paths the advisory lists, check whether any became symlinks pointing into node_modules. In a normal project these are usually ordinary folders.
Read-only checkfind .git/hooks .husky .githooks scripts tools bin tests dist .github/actions -maxdepth 1 -type l 2>/dev/null
- 01Upgrade to 10.34.0 or 11.4.0 or later
The fix rejects aliases with path traversal both when reading package manifests and when creating symlinks. The project offers no workaround besides upgrading.
- 01If you find a suspicious symlink, assume code may have run
This is PlainCVE's inference, not official guidance: any hook or script that ran from a swapped path should be treated as untrusted code execution. Remove the symlink, reinstall with a patched pnpm, and find the package that introduced the alias.
- 02Review credentials and published releases (precaution)
There is no official rotation guidance. If untrusted code is confirmed to have run, rotate the credentials that machine or CI job could reach, and review packages published during that window. This is a precaution.
- 01Don't treat --ignore-scripts as a complete defence
It only stops packages running scripts during install. It doesn't stop the package manager itself writing files where it shouldn't, or code that fires later.
- 02Pin and regularly update pnpm in CI
The same releases also fixed several other pnpm security issues; keeping the package manager itself current matters as much as updating dependencies.
- 03Review new indirect dependencies in lockfile changes
The malicious alias can come from a package you never chose directly; during code review, watch for unfamiliar packages or aliases appearing in the lockfile.
Full remediation steps and notes
- Upgrade pnpm itself first, then reinstall dependencies. Using whatever method you installed pnpm with, move to 10.34.0 or later (10.x) or 11.4.0 or later (11.x), then confirm with
pnpm --version. If your CI configuration pins a pnpm version, update that too. - Order matters. For projects where an old pnpm installed dependencies you’re unsure of, after upgrading first check whether the paths above have become symlinks. Only commit, build or publish once they’re clean, so you don’t trigger a swapped hook or script along the way.
- No official workaround. The advisory offers no mitigation other than upgrading.
- The same releases also fixed several separate pnpm security issues (rejecting patch files that point outside the package, rejecting non-SHA git commit fields, scoping registry credentials to their own registry, and failing hard on tarball integrity mismatches), which is another reason to upgrade.
Attack flow
Read left to right: this is the order the attack happens in. A blue shield means the step can be stopped; the earlier, the better. Click an icon for details.
- Attacker
The attacker publishes a malicious package with a path-traversal alias
The package's registry metadata declares a dependency alias containing '..' (go up one folder). An ordinary-looking package then depends on it.
Defense: Fixed pnpm versions reject aliases containing path traversal as soon as they read the package manifest.
- Your system
A developer or CI job runs pnpm install
The malicious package can be an indirect dependency. Adding --ignore-scripts changes nothing, because the next step needs no script at all.
Defense: Upgrade to 10.34.0 / 11.4.0 or later; review new indirect dependencies in lockfile changes.
- Your system
pnpm uses the alias as a path and replaces a project path with a symlink
Older versions never checked that the final path stayed inside node_modules, so paths such as .git/hooks, .husky, scripts/, .github/actions/ or dist/ can become symlinks to the attacker's package folder. This step changes files; it does not run code.
Defense: The fix also rejects traversal again when creating symlinks. You can periodically check whether these paths have turned into symlinks into node_modules.
- Your system
A later git commit, test, build or CI step uses the swapped path
Only now might the attacker's content run, for example a git hook firing on commit, or pnpm test, pnpm run build or a CI step calling a swapped script.
Defense: Don't rely on --ignore-scripts alone; build and run CI in clean, patched environments.
- External
Tampered build output may get published
The advisory lists dist/ and pnpm publish as possible trigger points; if output is swapped before publishing, downstream users could receive a tampered package. This is an inference from the advisory's impact list.
Defense: Before publishing, confirm dist/ is not a symlink, and publish from patched CI.
Who is affected
| Branch | Affected | Fixed |
|---|---|---|
| 10.x and earlier | before 10.34.0 | 10.34.0 |
| 11.x | 11.0.0 up to (not including) 11.4.0 | 11.4.0 |
The damage happens at install time when both of these hold:
| Condition | Notes |
|---|---|
| You use an affected pnpm version from the table above | Developer machines and CI (continuous integration, the systems that build and test code automatically) both count |
pnpm install runs on a dependency tree containing a malicious package with a traversal alias | It can be a transitive dependency, meaning a package that one of your dependencies depends on |
At that point project paths have already been swapped for symlinks, so the project’s files can no longer be trusted. If the swapped target is an ordinary file, the maintainer advisory says the result is usually denial of service (that file stops working).
What happens later depends on whether something uses the swapped path. If git hooks, test or build scripts, CI steps or publishing later read or run those paths, the problem can escalate to running malicious code or to poisoned published artifacts (for example a swapped dist/ folder being packed and published).
Using --ignore-scripts makes no difference. The sources don’t say whether installing from an existing lockfile (the file recording the exact version of every dependency) with --frozen-lockfile also triggers it.
How it works
pnpm supports “aliases”, which let a project install a package under a different name. The problem: pnpm accepted the alias a package declared in its registry metadata even when it contained .. (go up one folder), then joined that alias onto node_modules to decide where to create a symlink (a filesystem shortcut) during install. It didn’t reject .., and it didn’t check that the final path was still inside node_modules.
The result: a malicious package deep in the dependency tree can make pnpm install replace a path in your project with a symlink to its own folder. The advisory lists possible targets including .git/hooks, .husky, .githooks, scripts/, tools/, bin/, tests/, .github/actions/<name>, dist/ before publishing, and node_modules/.bin. This kind of weakness is called relative path traversal (CWE-23).
Mind the timing: the install step only changes files. It does not mean code runs at install time. The attacker’s content can only run later, when a person or CI job uses the swapped path, for example git commit firing a git hook, pnpm test, pnpm run build, a CI step, or pnpm publish.
Why --ignore-scripts doesn’t help. According to pnpm’s docs, this option stops pnpm running scripts defined in the package.json of the project and its dependencies (such as postinstall). It controls whether packages get to run code. Here, pnpm itself creates the harmful symlink during its normal linking step, and no script is needed at all. --ignore-scripts is still worth using, but it doesn’t cover “the package manager writing files where it shouldn’t”, and it doesn’t cover code that fires later through git hooks, builds or CI.
The flawed approach (conceptual illustration, not pnpm’s source code):
Show code example(js)
// aliasName comes from the package's registry metadata and is untrusted
const target = path.join(nodeModulesDir, aliasName)
createSymlink(packageDir, target) // never checks target is still inside node_modulesThe fixed approach:
Show code example(js)
if (hasTraversalSegment(aliasName)) throw new Error('invalid alias')
const target = path.resolve(nodeModulesDir, aliasName)
if (!isInside(nodeModulesDir, target)) throw new Error('invalid alias')
createSymlink(packageDir, target)According to the release notes, the fixed versions reject aliases with path traversal both when reading package manifests and when creating symlinks.
Timeline
| Date | Event |
|---|---|
| Not public | Reported by researcher aszx87410 |
| 2026-05-27 | pnpm 11.4.0 and 10.34.0 released |
| 2026-05-28 | Maintainer advisory GHSA-hwx4-2j3j-g496 published |
| 2026-06-03 | Advisory updated |
| 2026-06-25 | CVE-2026-50016 published; added to NVD |
| 2026-06-26 | GitHub global advisory database entry published and reviewed; CVE record updated |
| 2026-06-29 | NVD last modified (Analyzed) |
Further reading
- Affected-version data disagrees: the CVE record’s structured data (CNA: GitHub) and NVD’s page summary say
< 10.33.4, but the same CVE’s description text, NVD’s own CPE configuration and the maintainer advisory all say< 10.34.0. The 10.33.4 release notes list only a git tarball integrity fix, not this alias fix, which first appears in 10.34.0. This page follows the maintainer advisory and treats 10.33.4 as still vulnerable. - Scoring: the only score is GitHub’s (CNA) CVSS 3.1 8.8, which NVD lists as secondary; NVD has published no score of its own, and there is no CVSS 4.0 score. CISA’s SSVC assessment is “proof of concept available, not automatable, total technical impact”. A proof of concept is not the same as attacks in the wild.
- Exploitation: no source reports exploitation in the wild. Our 2026-09-24 snapshot of the CISA KEV catalog does not list this CVE; not being listed does not mean it has not been exploited.
- Fix commit: neither the advisory nor the release notes link a specific commit or PR.
- Related but separate issue: pnpm 11.11–11.14 (blog dated 2026-07-18) added further hardening that stops a crafted
pnpm-lock.yamlfrom writing outside the virtual store; that post does not mention this CVE. - Some GitHub release pages were rendered with the year 2024, but the GitHub API and pnpm’s blog both give 2026-05-27.
- Related weakness type: CWE-23 (relative path traversal).
Verification Reviewed and checked against sources; not yet reproduced in our lab
| Reviewed | 2026-09-24 |
|---|
Verification records describe the environment and the result only, never reproduction steps or code that could attack other people’s systems. See our policy.
Sources
- AdvisoryTransitive dependency alias path traversal allows project path override via symlink replacement (GHSA-hwx4-2j3j-g496) · pnpm (GitHub), 2026-05-28 · accessed 2026-09-24
- AdvisoryGHSA-hwx4-2j3j-g496 repository advisory (API) · GitHub / pnpm, 2026-05-28 · accessed 2026-09-24
- AdvisoryGHSA-hwx4-2j3j-g496 global advisory (API) · GitHub, 2026-06-26 · accessed 2026-09-24
- CVE / NVD / OSVCVE-2026-50016 · CVE Program, 2026-06-25 · accessed 2026-09-24
- CVE / NVD / OSVCVE-2026-50016 record JSON · CVE Program (CNA GitHub_M, CISA ADP), 2026-06-25 · accessed 2026-09-24
- CVE / NVD / OSVNVD - CVE-2026-50016 · NIST NVD, 2026-06-25 · accessed 2026-09-24
- CVE / NVD / OSVNVD CVE API record for CVE-2026-50016 · NIST NVD, 2026-06-25 · accessed 2026-09-24
- Patch / releaseRelease v10.34.0 · pnpm (GitHub), 2026-05-27 · accessed 2026-09-24
- Patch / releaseRelease v11.4.0 · pnpm (GitHub), 2026-05-27 · accessed 2026-09-24
- Patch / releaseRelease v10.33.4 · pnpm (GitHub) · accessed 2026-09-24
- Vendorpnpm 11.4 · pnpm, 2026-05-27 · accessed 2026-09-24
- Vendorpnpm 11.11-11.14 · pnpm, 2026-07-18 · accessed 2026-09-24
- Vendorpnpm install · pnpm · accessed 2026-09-24
- AdvisoryCVE-2026-50016: pnpm: Transitive dependency alias path traversal allows project path override via symlink replacement · GitLab Advisory Database · accessed 2026-09-24
Press brief
In one sentence
pnpm is a widely used JavaScript package manager. Its install step had a path traversal flaw: a malicious package deep in the dependency tree could replace project folders, such as git hooks or build output, with symlinks pointing to itself, and the --ignore-scripts option many people rely on against malicious packages did not stop it. Fixed versions 10.34.0 and 11.4.0 were released on May 27, 2026. No source reports exploitation in the wild.
Key facts
- Severity
- CVSS 3.1 8.8 (scored by GitHub as CNA; NVD has no score of its own) services.nvd.nist.gov
- Fixed versions
- 10.34.0 and 11.4.0 (released 2026-05-27) github.com
- Maintainer advisory
- GHSA-hwx4-2j3j-g496, published 2026-05-28 api.github.com
- CVE published
- 2026-06-25 cveawg.mitre.org
- Weakness and reporter
- CWE-23 relative path traversal; reported by aszx87410 github.com
Confirmed
- Affected pnpm versions use an indirect dependency's alias as a path at install time and can replace a project path with a symlink to a malicious package.
- The maintainer advisory, the CVE and NVD all state the path replacement still happens with --ignore-scripts.
- Fixed versions 10.34.0 and 11.4.0 reject aliases containing path traversal.
- CISA's SSVC assessment: proof of concept available, not automatable, total technical impact.
Unconfirmed / disputed
- 10.x affected range: the CVE structured data says <10.33.4, but the maintainer advisory, the CVE description and NVD's CPE configuration all say <10.34.0; the 10.33.4 release notes contain no such fix, so this page uses <10.34.0.
- No source reports exploitation in the wild. Our 2026-09-24 snapshot of the CISA KEV catalog does not list this CVE; not being listed does not mean it has not been exploited.
- Sources don't say whether installing from an older lockfile (--frozen-lockfile) also triggers it.
- No specific fix commit or PR has been publicly linked.
Quotable line
--ignore-scripts takes away a package's ability to run code, but this time the one writing the files was the package manager itself.
Images
Download the share image (PNG) · Attack flow diagram (downloadable)
Please credit "PlainCVE" and link to this page. Full citation format is under "How to cite" below. Found a factual error? Report it.
pnpm dependency alias path traversal: an indirect dependency can swap project folders for symlinks at install time, even with --ignore-scripts pnpm is a widely used JavaScript package manager. Its install step had a path traversal flaw: a malicious package deep in the dependency tree could replace project folders, such as git hooks or build output, with symlinks pointing to itself, and the --ignore-scripts option many people rely on against malicious packages did not stop it. Fixed versions 10.34.0 and 11.4.0 were released on May 27, 2026. No source reports exploitation in the wild. Key facts: - Severity:CVSS 3.1 8.8 (scored by GitHub as CNA; NVD has no score of its own)(https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2026-50016) - Fixed versions:10.34.0 and 11.4.0 (released 2026-05-27)(https://github.com/pnpm/pnpm/security/advisories/GHSA-hwx4-2j3j-g496) - Maintainer advisory:GHSA-hwx4-2j3j-g496, published 2026-05-28(https://api.github.com/repos/pnpm/pnpm/security-advisories/GHSA-hwx4-2j3j-g496) - CVE published:2026-06-25(https://cveawg.mitre.org/api/cve/CVE-2026-50016) - Weakness and reporter:CWE-23 relative path traversal; reported by aszx87410(https://github.com/pnpm/pnpm/security/advisories/GHSA-hwx4-2j3j-g496) Confirmed: - Affected pnpm versions use an indirect dependency's alias as a path at install time and can replace a project path with a symlink to a malicious package. - The maintainer advisory, the CVE and NVD all state the path replacement still happens with --ignore-scripts. - Fixed versions 10.34.0 and 11.4.0 reject aliases containing path traversal. - CISA's SSVC assessment: proof of concept available, not automatable, total technical impact. Unconfirmed / disputed: - 10.x affected range: the CVE structured data says <10.33.4, but the maintainer advisory, the CVE description and NVD's CPE configuration all say <10.34.0; the 10.33.4 release notes contain no such fix, so this page uses <10.34.0. - No source reports exploitation in the wild. Our 2026-09-24 snapshot of the CISA KEV catalog does not list this CVE; not being listed does not mean it has not been exploited. - Sources don't say whether installing from an older lockfile (--frozen-lockfile) also triggers it. - No specific fix commit or PR has been publicly linked. 「--ignore-scripts takes away a package's ability to run code, but this time the one writing the files was the package manager itself.」— PlainCVE https://plaincve.date/en/vulns/cve-2026-50016-pnpm-alias-path-traversal
How to cite this page
This article is CC BY 4.0. Please keep the attribution and link when republishing.
PlainCVE Team (2026). "pnpm dependency alias path traversal: an indirect dependency can swap project folders for symlinks at install time, even with --ignore-scripts". PlainCVE. https://plaincve.date/en/vulns/cve-2026-50016-pnpm-alias-path-traversal (accessed YYYY-MM-DD)BibTeX
@misc{cve202650016pnpmaliaspathtraversal2026,
title = {pnpm dependency alias path traversal: an indirect dependency can swap project folders for symlinks at install time, even with --ignore-scripts},
author = {PlainCVE Team},
year = {2026},
howpublished = {PlainCVE},
url = {https://plaincve.date/en/vulns/cve-2026-50016-pnpm-alias-path-traversal},
note = {Updated 2026-09-24}
}