CVE-2022-3786

Stack-based Buffer Overflow
Affects
Node.js
in
Node.js
No items found.
Versions
>=18.0.0 <18.12.1; >=19.0.0 <19.0.1
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 the V8 JavaScript engine. It uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, and is widely used to build scalable server-side applications. Node.js ships with its own bundled copy of OpenSSL, which provides the TLS and cryptography behind the tls, https and crypto modules.

A buffer overflow vulnerability (CVE-2022-3786) has been identified in the OpenSSL library bundled with Node.js, which allows a remote attacker to crash a Node.js process by presenting an X.509 certificate containing a crafted email address. During certificate name constraint checking, the punycode decoder writes an arbitrary number of period characters (decimal 46) past the end of a stack buffer, which can lead to a Denial of Service.

Per MITRE, CWE-120 (Buffer Copy without Checking Size of Input) occurs when “the product copies an input buffer to an output buffer without verifying that the size of the input buffer is less than the size of the output buffer, leading to a buffer overflow.” Because every byte written past the end of the buffer is the same period character, the attacker controls how much memory is overwritten but not what it is overwritten with, and the outcome documented upstream is a crash rather than code execution.

This issue affects every release of the Node.js 18.x line up to and including v18.12.0, and Node.js v19.0.0. Node.js 14.x and 16.x are not affected because those release lines bundle OpenSSL 1.1.1, which does not contain the vulnerable punycode decoder. The same upstream advisory also covers a separate defect in the same decoder, CVE-2022-3602.

Details

Module Info

  • Product: Node.js
  • Affected packages: nodejs/node (the Node.js runtime; the vulnerable code is the OpenSSL copy bundled at deps/openssl, file crypto/punycode.c)
  • Package manager: Not applicable. Node.js is distributed as runtime binaries and source tarballs rather than as a registry package.
  • Affected versions:
    • >=18.0.0 <18.12.1
    • >=19.0.0 <19.0.1
  • Bundled component affected: OpenSSL 3.0.0 through 3.0.6
  • GitHub repository: https://github.com/nodejs/node
  • Published packages: https://nodejs.org/en/download
  • Upstream advisory: Node.js November 2022 Security Releases and the OpenSSL Security Advisory of 1 November 2022
  • GitHub Security Advisory: GHSA-h8jm-2x53-xhp5 (filed against the OpenSSL source distribution, not against a Node.js package; no Node.js-ecosystem GHSA exists for this CVE)
  • Upstream fixed in: Node.js v18.12.1 and v19.0.1, which bundle OpenSSL 3.0.7. Both of those release lines are now themselves End-of-Life.
  • Fixed in: Node.js NES v16.20.3 (shipped July 30, 2024, as part of NES's cumulative OpenSSL 3.0.x catch-up release)

Vulnerability Info

This High-severity vulnerability is found in the OpenSSL library bundled with the Node.js runtime, in every published release of the Node.js 18.x line up to v18.12.0 and in Node.js v19.0.0. It is tracked upstream in the OpenSSL security advisory of November 1, 2022 and in the November 2022 security releases announcement.

OpenSSL 3.0 added support for internationalized email addresses in X.509 certificates, carried in a subject alternative name of type otherName: SmtpUTF8Mailbox as defined in RFC 8398. To compare such an address against a certificate authority's name constraints, OpenSSL converts the ASCII-compatible punycode form of the address domain back into Unicode. That conversion is performed by ossl_a2ulabel() in crypto/punycode.c, which walks the domain one label at a time, decodes each label into a fixed-size buffer on the stack, and writes a period separator between labels.

The defect is that the function did not stop when the output buffer was full. Once the buffer filled, ossl_a2ulabel() recorded the failure but kept iterating over the remaining labels, and kept writing the period separator with no bounds check. A certificate whose email domain ends in a long run of empty punycode labels (each the literal xn--) therefore writes an attacker-chosen number of 0x2e bytes past the end of the stack buffer. The function also failed to NUL-terminate its output on some paths. The fix, OpenSSL commit c42165b, rewrites the function to bounds check every character written and to terminate the output correctly.

Name constraint checking runs after the certificate chain signature has been verified, so reaching the vulnerable code requires either that a certificate authority in the trust store signed the malicious certificate, or that the application continues verification after failing to build a path to a trusted issuer. In a Node.js TLS or HTTPS client (tls.connect(), https.request()), the path can be reached by connecting to a malicious server. In a Node.js TLS or HTTPS server, it can be reached when the server asks for client certificates with requestCert: true and a malicious client connects. The result is a run of period bytes written past the end of the stack buffer, which upstream describes as a crash causing a Denial of Service.

Note: The Node.js 14.x and 16.x release lines are not affected. They bundle OpenSSL 1.1.1, which has no punycode decoder and no SmtpUTF8Mailbox name constraint support. Node.js 17.x also bundled OpenSSL 3.x but had already reached End-of-Life on June 1, 2022, before this fix shipped, and was never updated to receive it.

Note: This issue is one of two separate defects disclosed in the same OpenSSL punycode decoder on November 1, 2022. Its twin, CVE-2022-3602, is a four-byte overflow with attacker-controlled content that was pre-announced as Critical and released as High. The two have separate fixes, and Node.js addressed both in the same v18.12.1 and v19.0.1 releases.

Steps to Reproduce

The outline below is drawn from the public OpenSSL advisory and from Rapid7's published analysis of this issue. HeroDevs has not published a proof of concept for CVE-2022-3786.

  1. Build a certificate whose subject alternative name carries an otherName: SmtpUTF8Mailbox entry whose email domain ends in a long run of empty punycode labels. Rapid7's public analysis uses a domain of this shape:
a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.xn--.xn--.xn--.xn--.xn--.xn--.xn--
  1. Have that certificate signed by a certificate authority the Node.js process trusts, with an email name constraint on the issuing CA so that name constraint checking runs.
  2. Present the certificate from a TLS server and connect with an affected Node.js build, for example:
const tls = require('node:tls');

tls.connect({ host: 'malicious.example', port: 443, ca: [caPem] });
  1. Alternatively, run an affected Node.js TLS or HTTPS server that requests client certificates and have a malicious client present the certificate:
const tls = require('node:tls');

tls.createServer({ key, cert, requestCert: true, ca: [caPem] })
  .listen(8443);
  1. On an affected build the run of period bytes is written past the end of the stack buffer during verification and the process typically crashes. On Node.js v18.12.1, v19.0.1 or later, the decode is bounds checked and the certificate is rejected without an overflow.

Mitigation

The Node.js 18.x and 19.x release lines are both End-of-Life and will not receive any further updates to address this or any future issue. For more information see here.

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

  • Upgrade to a Node.js release line that is still in Long Term Support.
  • 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

  • Viktor Dukhovni (finder)
  • Dr Paul Dale (remediation developer)
Vulnerability Details
Severity
Level
CVSS Assessment
Low
>=0 <4
Medium
>=4 <6
High
>=6 <8
Critical
>=8 <10
High
ID
CVE-2022-3786
PROJECT Affected
Node.js
Versions Affected
>=18.0.0 <18.12.1; >=19.0.0 <19.0.1
NES Versions Affected
Published date
September 11, 2026
≈ Fix date
November 4, 2022
Category
Stack-based Buffer Overflow
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.