CVE-2022-4450
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. Node.js compiles its own copy of OpenSSL from deps/openssl in the Node.js source tree, and the built-in crypto, tls and https modules rely on that bundled copy, including for reading certificates and keys in PEM format.
A vulnerability (CVE-2022-4450) has been identified in the OpenSSL library bundled with Node.js. OpenSSL's PEM_read_bio_ex() function, which parses a PEM file into its name, headers and payload, mishandles a PEM file whose payload decodes to zero bytes: it reports failure but leaves the caller holding a pointer to a header buffer it has already freed. A caller that frees that buffer then frees it a second time, which will most likely crash the process.
This flaw maps to CWE-415 (Double Free), where software releases the same memory twice, corrupting the allocator's state. In OpenSSL, the failure path of PEM_read_bio_ex() frees its own buffers but does not clear the pointers it has already handed back. Any code that follows the function's normal rule of freeing those buffers ends up freeing them again, so an attacker who can supply a malicious PEM file for parsing can cause a denial of service.
The functions PEM_read_bio() and PEM_read() are thin wrappers around PEM_read_bio_ex() and are directly affected, and so are functions that call it internally, such as PEM_X509_INFO_read_bio_ex() and SSL_CTX_use_serverinfo_file(). Some internal users of the function are not affected because they do not free the header after a failure, including the PEM_read_bio_TYPE() functions (for example PEM_read_bio_X509() and PEM_read_bio_PrivateKey()) and the decoders introduced in OpenSSL 3.0. This issue affects every Node.js release line whose bundled OpenSSL is 1.1.1 through 1.1.1s or 3.0.0 through 3.0.7, up to the versions listed above.
Details
Module Info
- Product: Node.js
- Affected packages: node (bundles OpenSSL under deps/openssl)
- Affected versions: >=10.16.0 <=10.24.1 >=11.9.0 <=11.15.0 >=12.0.0 <=12.22.12 >=13.0.0 <=13.14.0 >=14.0.0 <14.21.3 >=15.0.0 <=15.14.0 >=16.0.0 <16.19.1 >=17.0.0 <=17.9.1 >=18.0.0 <18.14.1 >=19.0.0 <19.6.1
- 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 14.21.3, 16.19.1, 18.14.1 and 19.6.1 (all February 16, 2023), security releases that upgraded the bundled OpenSSL to 1.1.1t or 3.0.8; Node.js NES v16.20.3 (16.x line, shipped July 30, 2024), a later cumulative build carrying the same fix. The other release lines listed above never received an updated OpenSSL
Vulnerability Info
This Medium-severity vulnerability is found in the OpenSSL library that Node.js bundles and statically links at deps/openssl, in Node.js releases whose bundled OpenSSL predates 1.1.1t or 3.0.8. OpenSSL rates the issue Moderate under its own severity policy, which is the basis of the Medium rating here; NVD assigns a higher CVSS v3.1 score of 7.5 (High), treating it as a remotely triggerable crash that needs no privileges.
When PEM_read_bio_ex() succeeds, it hands the caller newly allocated buffers for the PEM name, headers and decoded data, and the caller is responsible for freeing them. When it fails, it is supposed to free those buffers itself and leave the caller with nothing to free. In the vulnerable versions, a PEM block with an empty payload caused a failure in which the function freed the header buffer but left the caller's pointer to it in place. The fix clears the header and data pointers on failure so that no dangling pointer is returned. See the OpenSSL 1.1.1 fix commit and the OpenSSL 3.0 fix commit for the exact changes.
Exploitation requires getting the application to parse an attacker-supplied PEM file through one of the affected functions. The expected result is a crash, and so a denial of service, of the process doing the parsing.
Note: The PEM_read_bio_TYPE() functions and the OpenSSL 3.0 decoders, which handle the common cases of loading a certificate or a private key, are not vulnerable because they do not free the header after a failure. OpenSSL 1.0.2 is not affected, so Node.js releases that bundle it, 9.x and earlier, are not exposed by this issue.
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 OpenSSL 3.5, which 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
- CarpetFuzz (finder)
- Dawei Wang (reporter)
- Marc Schönefeld (reporter, independent report)
- Kurt Roeckx (remediation developer)
- Matt Caswell from the OpenSSL project (remediation developer)