CVE-2021-39135

Improper Link Resolution Before File Access ('Link Following')
Affects
Node.js
in
Node.js
No items found.
Versions
>=12.0.0 <12.22.6 >=14.0.0 <14.17.6 >=15.0.0 <=15.14.0 >=16.0.0 <16.8.0

Patch Available.

Exclamation circle icon
Patch Available

This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.

Overview

Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. It uses an event-driven, non-blocking I/O model and is widely used for web applications and server-side development. Every official Node.js distribution ships with npm, the default package manager, so the npm version a developer runs is usually the one bundled with their Node.js release. Starting with npm 7, npm builds and installs the dependency tree through @npmcli/arborist, the library that calculates dependency trees and manages the node_modules folder hierarchy.

A vulnerability (CVE-2021-39135) has been identified in @npmcli/arborist, as bundled with npm in Node.js. Arborist is meant to extract package contents only into a project's node_modules folder. However, if the node_modules folder of the root project or of any dependency has been replaced with a symbolic link, arborist follows that link and writes package contents wherever it points, which can be any location on the file system the installing user can write to.

This flaw maps to CWE-59 (Improper Link Resolution Before File Access, 'Link Following'), and specifically to its child CWE-61 (UNIX Symbolic Link Following), where software opening a file or folder does not account for a link that resolves outside the area it is meant to control. In arborist, the extraction target is trusted to be a real directory without being checked. Because npm runs with the developer's or build system's permissions, writing through that link can lead to arbitrary file creation, file overwrite and code execution.

Symbolic links inside package tarballs are filtered out, so an attacker needs another way to put the link in place. A dependency's preinstall script can replace node_modules with a symlink, although running npm with --ignore-scripts prevents that. Alternatively, an attacker can hand the victim a git repository that already contains a node_modules symlink and ask them to run npm install --ignore-scripts, an action normally assumed not to touch anything outside the project. The vulnerable arborist was bundled with npm 7 up to 7.20.6, which shipped with Node.js 15.x and Node.js 16.x before 16.8.0. Node.js also addressed this CVE in its 12.22.6 and 14.17.6 security releases, which listed the 12.x and 14.x release lines as vulnerable.

‍

Details

Module Info

  • Product: Node.js
  • Affected packages: @npmcli/arborist (bundled with npm in Node.js)
  • Affected versions: >=12.0.0 <12.22.6 >=14.0.0 <14.17.6 >=15.0.0 <=15.14.0 >=16.0.0 <16.8.0
  • GitHub repository: https://github.com/nodejs/node
  • Published packages: https://nodejs.org/en/download
  • Package manager: Not applicable; Node.js is distributed as runtime builds from nodejs.org rather than as a published npm package
  • Fixed in: Node.js 16.8.0 (August 25, 2021), which bundled npm 7.21.0 with @npmcli/arborist 2.8.2, and Node.js 12.22.6 and 14.17.6 (August 31, 2021), whose security releases listed this CVE as addressed; Node.js NES v14.21.4 (14.x line, shipped August 24, 2024) and v12.22.13 (12.x line, shipped November 10, 2025), which also list this CVE as fixed. Node.js 15.x never received a fix

Vulnerability Info

This High-severity vulnerability is found in @npmcli/arborist 2.8.1 and earlier, the dependency-tree library bundled with npm and therefore with Node.js. NVD assigns a CVSS v3.1 score of 7.8.

Arborist is supposed to extract every package into a node_modules folder inside the project. In the vulnerable versions, it did not confirm that the node_modules folder it was writing into was a real directory, so a symbolic link in its place redirected the extraction to the link's target. Arborist 2.8.2 checks, before extracting any package, that the destination node_modules is a real directory and removes it if it is not. See the arborist advisory for the details of the change.

Exploitation requires the victim to run npm install on a codebase or dependency the attacker controls. No privileges on the target system are needed beyond getting that install to run, and the impact covers the confidentiality, integrity and availability of anything the installing account can write. The --ignore-scripts flag blocks the preinstall-script route but not the pre-placed symlink in a supplied repository.

Note: Until the fix is applied, do not run npm install on an untrusted codebase without first confirming that its node_modules folder is not a symbolic link. Projects that deliberately symlink node_modules to share dependencies will stop working after the fix; npm link, explicit file: dependencies or workspaces are the supported alternatives.

‍

Mitigation

Users of the affected components should apply one of the following mitigations:

  • Upgrade to a currently supported Node.js LTS release (22.x or 24.x), both of which bundle an npm version that includes this fix.
  • Migrate affected applications away from the End-of-Life Node.js release lines.
  • Leverage a commercial support partner like HeroDevs for post-EOL security support, through Node.js NES.

‍

Credits

  • JarLob (finder)
Vulnerability Details
Severity
Level
CVSS Assessment
Low
>=0 <4
Medium
>=4 <6
High
>=6 <8
Critical
>=8 <10
High
ID
CVE-2021-39135
PROJECT Affected
Node.js
Versions Affected
>=12.0.0 <12.22.6 >=14.0.0 <14.17.6 >=15.0.0 <=15.14.0 >=16.0.0 <16.8.0
NES Versions Affected
Published date
October 1, 2026
≈ Fix date
August 24, 2024
Category
Improper Link Resolution Before File Access ('Link Following')
Vex Document
Download VEXHow do I use it?
Sign up for the latest vulnerability alerts fixed in
NES for Node.js
Rss feed icon
Subscribe via RSS
or

By submitting the form I acknowledge receipt of our Privacy Policy.

Thanks for signing up for our Newsletter! We look forward to connecting with you.
Oops! Something went wrong while submitting the form.