Skip to content
AttackFeed by Joe Wagner | Cybersecurity News from Across the Internet

AttackFeed by Joe Wagner

Cybersecurity News from Across the Internet

  • Attack/News Feeds
  • Gov Alerts/ISAC Feeds
  • Vulnerability Alerts
  • Privacy/Governance Feeds
  • Fraud Feeds
  • iOS App
  • Android App
  • Home
  • Attack Feeds
  • Node.js Trust Falls: Dangerous Module Resolution on Windows  – Zero Day Initiative – Blog
AttackFeed by Joe Wagner | Node.js Trust Falls: Dangerous Module Resolution on Windows  - Zero Day Initiative - Blog

Node.js Trust Falls: Dangerous Module Resolution on Windows  – Zero Day Initiative – Blog

Posted on April 8, 2026 By Bobby Gould and Michael DePlante
Attack Feeds

In September of 2024, ZDI received a vulnerability submission from an anonymous researcher affecting npm CLI that revealed a fundamental design issue in Node.js. This blog details how it continues to expose applications to local privilege escalation (LPE) attacks on Windows systems, including the Discord desktop app (CVE-2026-0776 0-Day), which remains unpatched and vulnerable.

The issue is straightforward: when Node.js resolves modules, the runtime searches for packages in C:node_modules as part of its default behavior. Since low-privileged Windows users can create this directory and plant malicious modules there, any Node.js application with missing or optional dependencies becomes vulnerable to privilege escalation.

This issue is not new. Concerned discussions about Node.js’s module search path behavior date back to 2013 and 2014.

Node.js has explicitly stated that they consider this behavior intentional:

“Node.js trusts the file system.”

They do not treat CWE-427 (Uncontrolled Search Path Element) as a vulnerability, pushing responsibility onto application developers.

AttackFeed by Joe Wagner | Node.js Trust Falls: Dangerous Module Resolution on Windows  - Zero Day Initiative - Blog

Figure 1: The vendor’s security policy stance on CWE-427 as a non-issue

As the case studies below demonstrate, this stance has dangerous consequences. Developers are largely unaware of this attack surface, and the result is a proliferation of exploitable applications. We will show examples in npm CLI and Discord, but there are likely many more applications that are impacted by this.

Root Cause

The root cause lies in the way Node.js performs module resolution. This is documented here. Although UNIX paths are used in the documentation provided by Node.js, the same logic is applied on Windows.

When a Node.js application calls require(‘bar’), the runtime searches for the module in the following order:

  1. C:UsersAdministratorprojectsnode_modulesbar.js
  2. C:UsersAdministratornode_modulesbar.js
  3. C:Usersnode_modulesbar.js
  4. C:node_modulesbar.js <– The problem

If the legitimate package is missing, whether due to optional dependencies, development packages removed in production, or installation failures, the resolution search will eventually reach the root of the drive. Any user can create C:node_modules and place a malicious package there. Once the low-privileged user has populated C:node_modulesbar.js, Node.js will load and execute it in the context of the current user. In the following case studies, we will provide evidence of how, despite properly following NPM’s guidelines, third-party dependencies end up triggering this vulnerability anytime you launch the application.

Case Studies: Real-World Manifestations

The Optional Dependency Pattern:
npm supports optional dependencies to be specified in the project’s package.json file. The recommended pattern for checking for these dependencies is as follows:

AttackFeed by Joe Wagner | Node.js Trust Falls: Dangerous Module Resolution on Windows  - Zero Day Initiative - Blog

Figure 2: npm Docs showing optionalDependencies example code

This pattern silently catches errors when optional packages are missing, allowing execution to continue. So what’s the problem? On Windows, Node.js will search all the way up to C:node_modules where an attacker may have planted a malicious replacement. This search behavior mirrors UNIX conventions where /node_modules at the filesystem root is typically only writable by root. Windows systems by default allow any user to create C:node_modules. Once require is called, Node.js will traverse the search path and execute any matching module it finds.

Important things to note:

  1. This pattern can be found in third party libraries deep in a dependency tree, as we will see in the following examples.
  2. There is no runtime indication to either the developers or the end users that such a vulnerability exists without looking at the filesystem logs with Procmon.
  3. The optional dependency pattern itself would not be dangerous if Node.js did not search for packages in C:node_modules.

Let’s take a deeper look at both cases and see why this is so dangerous.

Case 1: npm CLI (ZDI-26-043 / ZDI-CAN-25430 / CVE-2026-0775).

Prior to version 11.2.0, npm CLI used a library called “promise-inflight”, which contained an optional dependency on a package called “bluebird”.

AttackFeed by Joe Wagner | Node.js Trust Falls: Dangerous Module Resolution on Windows  - Zero Day Initiative - Blog

Figure 3: npm CLI repo snippet showing require call for missing bluebird package dependency

When Node.js is installed on the system, npm is included by default without the bluebird package. This vulnerability was introduced when bluebird was removed through a well-intentioned pull request (https://github.com/npm/cli/pull/1438/changes), demonstrating how easy it is for developers to unknowingly create this attack surface.

We can see Node’s package resolution logic at work in the screenshot below:

AttackFeed by Joe Wagner | Node.js Trust Falls: Dangerous Module Resolution on Windows  - Zero Day Initiative - Blog

Figure 4: Procmon log showing the package resolution behavior of Node.js via CVE-2026-0775

First, the application looks for the bluebird.js package in the Node.js installation directory. Node.js sequentially searches back to the system root until it finds the package. If an attacker has placed C:node_modulesbluebird.js, the require call will find, read, and execute the malicious payload in the context of any user running npm on the system.

This vulnerability is especially dangerous because it is triggered when many npm * cli commands are used. Common development commands such as npm install, npm –l, and npm prune will all execute the malicious bluebird.jspackage.

Case 2: Discord (ZDI-26-040/ ZDI-CAN-27057 / CVE-2026-0776/ UNPATCHED)

On April 22, 2025, ZDI received a report for a similar vulnerability in Discord reported by T. Doğa Gelişli. Discord uses the ws WebSocket library, which contains an optional dependency on utf-8-validate for compatibility with older Node.js versions:

AttackFeed by Joe Wagner | Node.js Trust Falls: Dangerous Module Resolution on Windows  - Zero Day Initiative - Blog

Figure 5: websockets library repo snippet showing require call for missing utf-8-validate package dependency

Discord does not ship with the utf-8-validate package. As a result, the following Procmon logs show the same behavior as Case 1. Anytime Discord is launched, the attacker controlled C:node_modulesutf-8-validate.js is executed.

AttackFeed by Joe Wagner | Node.js Trust Falls: Dangerous Module Resolution on Windows  - Zero Day Initiative - Blog

Figure 6: Procmon log showing the package resolution behavior of Node.js via CVE-2026-0776

The ws library does support disabling this check via the WS_NO_UTF_8_VALIDATE environment variable, but this requires the consuming application (Discord) to set it explicitly. Here’s a quick video demonstrating the bug by popping the calc app when opening Discord:

Discord automatically opens on login by default, so in practice code execution happens immediately without any user interaction. Strangely, the Discord Security team made it clear to us in their responses that they do not consider local attack vectors as valid security issues.

The Bigger Picture

The cases above represent only a few of the applications affected by this pattern. During our investigation we found many other independent reports.  These issues in Mongo DB Compass and Mongo DB Shell are just two other examples.

Every Windows application built on Node.js with missing or optional dependencies is potentially vulnerable. This includes desktop applications that utilize Electron as well as popular web frameworks such as Next.js and React.

Each vendor has clearly stated that they will not treat these issues as vulnerabilities:

NPM’s response to our report:

“exploits that require local access to a machine are considered ineligible for npm CLI

Discord’s response to our report:

“We do not consider physical/local attacks as valid security issues”

Node.js, in the “Examples of non-vulnerabilities” section of their Security Policy:

“Node.js trusts the file system in the environment accessible to it. Therefore, it is not a vulnerability if it accesses/loads files from any path that is accessible to it.”

Conclusion

The vulnerability pattern described in this blog stems from a deliberate design decision by Node.js maintainers. While Node.js’s position that “applications should trust their filesystem” may hold true on properly administered UNIX systems, it creates a systemic vulnerability on Windows where low-privileged users can write to C:node_modules. Without a fix from Node.js, the burden silently falls on application developers.

Making matters worse, the vulnerable code may not live in the application code itself. The optional dependencies that trigger this behavior could come from third-party libraries buried in the dependency tree as we saw with both Discord and npm CLI.

We encourage security researchers to further review this issue and investigate other applications for this dangerous behavior. You can find us online at @bobbygould5 and @izobashi, and follow the team on Twitter, Mastodon, LinkedIn, or Bluesky for the latest in exploit techniques and security patches.

 

DISCLOSURE TIMELINES

 

NPM CLI:

2024-11-13 – ZDI submitted the report to the vendor

2024-11-13 – The vendor acknowledged the receipt of the report

2024-11-13 – The vendor communicated that the reported behavior was by design and they do not consider local attacks as valid security issues

2025-08-05 – ZDI encouraged the vendor to re-assess the issue

2025-12-18 – ZDI notified the vendor of the intention to publish the case as a 0-day advisory

 

DISCORD:

2025-07-08 – ZDI notified vendor

2025-09-11 – ZDI followed up with vendor

2025-09-15 – Vendor stated they do not consider local attacks as valid security issues

2025-12-01 – ZDI explained why we believe the issue is still valid

2025-12-10 – Vendor replied that the vulnerability is still out of scope 

2025-12-11 – ZDI informed vendor of intent to publish 0-day 

  

REFERENCES

https://nodejs.org/api/modules.html#loading-from-node_modules-folders

https://docs.npmjs.com/cli/v10/configuring-npm/package-json#optionaldependencies

https://groups.google.com/g/nodejs/c/5BGr5dliUIk/m/abJEH3sPymcJ?pli=1

https://github.com/nodejs/node-v0.x-archive/issues/8830

https://bounty.github.com/ineligible.html#vulnerability_in_upstream_dependencies:~:text=eligible%20for%20rewards.-,Local%20access,-Vulnerabilities%20which%20require

https://github.com/nodejs/node/security/policy#examples-of-non-vulnerabilities

  –

Read More  – Zero Day Initiative – Blog 

Post navigation

❮ Previous Post: APT28 Deploys PRISMEX Malware in Campaign Targeting Ukraine and NATO Allies  – The Hacker News
Next Post: Hack-for-hire spyware campaign targets journalists in Middle East, North Africa  – CyberScoop ❯

You may also like

Attack Feeds
Smashing Security podcast #456: How to lose friends and DDoS people  – GRAHAM CLULEY
February 25, 2026
AttackFeed by Joe Wagner | Atlas Menu Data Breach Exposes 64,000 GTA V and CS2 Cheat Service Users  - Hackread – Cybersecurity News, Data Breaches, AI and More
Attack Feeds
Atlas Menu Data Breach Exposes 64,000 GTA V and CS2 Cheat Service Users  – Hackread – Cybersecurity News, Data Breaches, AI and More
June 5, 2026
AttackFeed by Joe Wagner | Chrome V8 Zero-Day CVE-2026-11645 Exploited in the Wild - Patch Now  - The Hacker News
Attack Feeds
Chrome V8 Zero-Day CVE-2026-11645 Exploited in the Wild – Patch Now  – The Hacker News
June 9, 2026
AttackFeed by Joe Wagner | Trivy Hack Spreads Infostealer via Docker, Triggers Worm and Kubernetes Wiper  - The Hacker News
Attack Feeds
Trivy Hack Spreads Infostealer via Docker, Triggers Worm and Kubernetes Wiper  – The Hacker News
March 23, 2026
  • Attack Feeds
  • Privacy/Governance Feed
  • Gov/ISAC Feeds
  • Alert Feeds
  • Privacy Policy
  • Wagner Cybersecurity

Copyright © 2026 AttackFeed by Joe Wagner.

Theme: Oceanly News Dark by ScriptsTown

We are using cookies for analytics purposes only.  We do not store, track or sell user information.

You can find out more about which cookies we are using or switch them off in .

AttackFeed by Joe Wagner
Powered by  GDPR Cookie Compliance
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.

Strictly Necessary Cookies

Strictly Necessary Cookie should be enabled at all times so that we can save your preferences for cookie settings.