raw
current commit
261007.9 · doc: clarify node binary misuse after compromise

Security

Reporting a bug in Node.js

Report security bugs in Node.js via HackerOne.

Normally, your report will be acknowledged within 5 days, and you’ll receive a more detailed response to your report within 10 days indicating the next steps in handling your submission. These timelines may extend when our triage volunteers are away on holiday, particularly at the end of the year.

After the initial reply to your report, the security team will endeavor to keep you informed of the progress being made towards a fix and full announcement, and may ask for additional information or guidance surrounding the reported issue.

If you do not receive an acknowledgement of your report within 6 business days, or if you cannot find a private security contact for the project, you may escalate to the OpenJS Foundation CNA at security@lists.openjsf.org.

If the project acknowledges your report but does not provide any further response or engagement within 14 days, escalation is also appropriate.

Node.js bug bounty program

The Node.js project no longer has a bug bounty program.

Reporting a bug in a third-party module

Security bugs in third-party modules should be reported to their respective maintainers.

Disclosure policy

Here is the security disclosure policy for Node.js

Code of Conduct and Vulnerability Reporting Guidelines

When reporting security vulnerabilities, reporters must adhere to the following guidelines:

  1. Code of Conduct Compliance: All security reports must comply with our Code of Conduct. Reports that violate our code of conduct will not be considered and may result in being banned from future participation.

  2. No Harmful Actions: Security research and vulnerability reporting must not:

    • Cause damage to running systems or production environments.
    • Disrupt Node.js development or infrastructure.
    • Affect other users’ applications or systems.
    • Include actual exploits that could harm users.
    • Involve social engineering or phishing attempts.
  3. Responsible Testing: When testing potential vulnerabilities:

    • Use isolated, controlled environments.
    • Do not test on production systems without prior authorization. Contact the Node.js Technical Steering Committee (tsc@iojs.org) for permission or open a HackerOne report.
    • Do not attempt to access or modify other users’ data.
    • Immediately stop testing if unauthorized access is gained accidentally.
  4. Report Quality

    • Provide clear, detailed steps to reproduce the vulnerability.
    • Include reproducible code written in JavaScript.
    • Include only the minimum proof of concept required to demonstrate the issue.
    • Remove any malicious payloads or components that could cause harm.

Failure to follow these guidelines may result in:

The Node.js threat model

In the Node.js threat model, there are trusted elements such as the underlying operating system. Vulnerabilities that require the compromise of these trusted elements are outside the scope of the Node.js threat model.

For a vulnerability to be eligible for a bug bounty, it must be a vulnerability in the context of the Node.js threat model. In other words, it cannot assume that a trusted element (such as the operating system) has been compromised.

Experimental platforms

Node.js maintains a tier-based support system for operating systems and hardware combinations (Tier 1, Tier 2, and Experimental). For platforms classified as “Experimental” in the supported platforms documentation:

This policy recognizes that experimental platforms may not compile, may not pass the test suite, and do not have the same level of testing and support infrastructure as Tier 1 and Tier 2 platforms.

Experimental features behind compile-time flags, experimental runtime flags, and V8 flags

Node.js includes certain experimental features that are only available when Node.js is compiled with specific flags or that are only enabled with experimental runtime flags. These features are intended for development, debugging, or testing purposes and are not enabled or supported in official releases.

Node.js may also expose V8 features that are controlled by V8 command-line flags (e.g., --js-staging, --max_old_space_size). These flags enable or modify V8-level JavaScript engine behavior that is not part of the ECMAScript specification that Node.js implements and is not part of the Node.js documented API surface.

Runtime gated experimental features

Experimental features behind runtime flags can fall into one of three categoriesgithub:

Security vulnerabilities that only affect experimental features in either the 1.0 or 1.1 stages, and that are gated with an --experimental-* runtime flag requiring explicit opt-in by the user to enable, will not be accepted as valid security issues unless the vulnerability can be exploited in a way that impacts the security of a stable feature when the associated --experimental-* flag is not enabled.

Security vulnerabilities that affect experimental features in the 1.2 stage are acceptable as valid security issues.

Compile-time gated experimental features and V8 flags

This policy recognizes that experimental features behind compile-time flags are not ready for public consumption and may have incomplete implementations, missing security hardening, or other limitations that make them unsuitable for production use. Similarly, V8 flags expose internal V8 engine options that are not part of the Node.js documented API surface, are not enabled by default in production builds, and may have incomplete implementations or missing security hardening.

Security triage dispositions

When triaging a report, the project classifies it into one of the following dispositions:

What constitutes a vulnerability

Being able to cause the following through control of the elements that Node.js does not trust is considered a vulnerability:

If Node.js loads configuration files or runs code by default (without a specific request from the user), and this is not documented, it is considered a vulnerability. Vulnerabilities related to this case may be fixed by a documentation update.

Denial of Service (DoS) vulnerabilities

For a behavior to be considered a DoS vulnerability, the PoC must meet the following criteria:

Node.js does NOT trust:

In other words, if the data passing through Node.js to/from the application can trigger actions other than those documented for the APIs, there is likely a security vulnerability. Examples of unwanted actions are polluting globals, causing an unrecoverable crash, or any other unexpected side effects that can lead to a loss of confidentiality, integrity, or availability.

For example, if trusted input (like secure application code) is correct, then untrusted input must not lead to arbitrary JavaScript code execution.

Node.js trusts everything else. Examples include:

Any unexpected behavior from the data manipulation from Node.js Internal functions may be considered a vulnerability if they are exploitable via untrusted resources.

In addition to addressing vulnerabilities based on the above, the project works to avoid APIs and internal implementations that make it “easy” for application code to use the APIs incorrectly in a way that results in vulnerabilities within the application code itself. While we don’t consider those vulnerabilities in Node.js itself and will not necessarily issue a CVE, we do want them to be reported privately to Node.js first. We often choose to work to improve our APIs based on those reports and issue fixes either in regular or security releases depending on how much of a risk to the community they pose.

Examples of vulnerabilities

Improper Certificate Validation (CWE-295)

Inconsistent Interpretation of HTTP Requests (CWE-444)

Missing Cryptographic Step (CWE-325)

External Control of System or Configuration Setting (CWE-15)

Examples of non-vulnerabilities

Defense-in-depth issues

Malicious protocol peers

Unauthorized or untrusted HTTP proxy deployments

Malicious Third-Party Modules (CWE-1357)

Same-process self-harm

Prototype Pollution Attacks (CWE-1321)

Uncontrolled Search Path Element (CWE-427)

External Control of System or Configuration Setting (CWE-15)

Uncontrolled Resource Consumption (CWE-400) on outbound connections

Vulnerabilities affecting software downloaded by Corepack

Exposing Application-Level APIs to Untrusted Users (CWE-653)

Build System Attacks Requiring Control of the Build Environment (CWE-78, CWE-114, CWE-276)

Unhandled ’error’ Events on EventEmitters (CWE-248)

Exceptions Thrown by Application Callbacks (CWE-248)

Permission Model Boundaries (--permission)

The Node.js Permission Model (--permission) is an opt-in mechanism that limits which resources a Node.js process may access. It is designed to reduce the blast radius of mistakes in trusted application code, not to act as a security boundary against intentional misuse or a compromised process.

Permission Model reports are triaged in three lanes:

The following are not vulnerabilities in Node.js:

QUIC and HTTP/3

The experimental QUIC and HTTP/3 implementation in Node.js is a complex new protocol stack and API that is still under active development and should not be used for production workloads. Reports that only affect QUIC or HTTP/3 are not considered Node.js vulnerabilities at this time. It is expected that the QUIC and HTTP/3 implementation will continue to evolve, and security issues will be addressed as the implementation matures.

Virtual File System (node:vfs)

The experimental Virtual File System (node:vfs) is a virtualized file-system API for tests, fixtures, embedded assets, and application-managed storage. It is not a sandbox, permission system, or security boundary for untrusted code.

Code that can load node:vfs, receive a VirtualFileSystem instance, install a mount, choose a provider, or pass paths to VFS APIs is trusted application code. A VFS mount only redirects matching file-system calls; it does not hide or restrict access to the host file system. RealFSProvider root checks and read-only providers are implementation behavior, not security guarantees.

Reports that rely on using VFS to isolate untrusted JavaScript, native code, or user-controlled paths are not considered Node.js vulnerabilities. Use OS-level isolation, such as separate users, containers, or platform sandboxes, when a security boundary is required.

V8 Sandbox

The V8 sandbox is an in-process isolation mechanism internal to V8 that is not a Node.js security boundary. Node.js does not guarantee or document the V8 sandbox as a security feature, and it is not enabled in a way that provides security guarantees in production Node.js builds. Reports about escaping the V8 sandbox are not considered Node.js vulnerabilities; they should be reported directly to the V8 project.

CRLF Injection in writeEarlyHints()

ServerResponse.writeEarlyHints() accepts a link header value that is set by the application. Passing arbitrary strings, including CRLF sequences, as the link value is an application-level misuse of the API, not a Node.js vulnerability. Node.js validates the structure of Early Hints per the HTTP spec but does not sanitize free-form application data passed to it; that is the application’s responsibility.

Receiving security updates

Security notifications will be distributed via the following methods.

CVE publication timeline

When security releases are published, there is a built-in delay before the corresponding CVEs are publicly disclosed. This delay occurs because:

  1. After the security release, we request the vulnerability reporter to disclose the details on HackerOne.
  2. If the reporter does not disclose within one day, we proceed with forced disclosure to publish the CVEs.
  3. The disclosure then goes through HackerOne’s approval process before the CVEs become publicly available.

As a result, CVEs may not be immediately available when security releases are published, but will typically be disclosed within a few days of the release.

Comments on this policy

If you have suggestions on how this process could be improved, please visit the nodejs/security-wggithub repository.

Incident Response Plan

In the event of a security incident, please refer to the Security Incident Response Plangithub.

Node.js Security Team

Node.js security team members are expected to keep all information that they have privileged access to by being on the team completely private to the team. This includes agreeing to not notify anyone outside the team of issues that have not yet been disclosed publicly, including the existence of issues, expectations of upcoming releases, and patching of any issues other than in the process of their work as a member of the security team.

Node.js Security Team Membership Policy

The Node.js Security Team has access to security-sensitive issues and patches that aren’t appropriate for public availability.

The policy for inclusion is as follows:

  1. All members of @nodejs/TSC have access to private security reports and private patches.
  2. Members of the @nodejs/releasers team have access to private security patches in order to produce releases.
  3. On a case-by-case basis, individuals outside the Technical Steering Committee are invited by the TSC to have access to private security reports or private patches so that their expertise can be applied to an issue or patch. This access may be temporary or permanent, as decided by the TSC.

Membership on the security teams can be requested via an issue in the TSC repo.

Team responsible for Triaging security reports

The responsibility of Triage is to determine whether Node.js must take any action to mitigate the issue, and if so, to ensure that the action is taken.

Mitigation may take many forms, for example, a Node.js security release that includes a fix, documentation, an informational CVE or blog post.

Team with access to private security reports against Node.js

TSC voting membersgithub have access.

In addition, these individuals have access:

The list is from the member page for the Node.js program on HackerOne.

Team with access to private security patches to Node.js