Vulnerability details

7.4/10
CVSS 3.1
GHSA-5x38-2vff-x55p
in_triage Published 2026-10-30 Updated 2026-10-30
Vulnerability Data from Dependency-Track
Description
### Summary node-forge parses certificate extensions with the deprecated OIDs `2.5.29.10` and `2.5.29.13` as `basicConstraints`, and `forge.pki.verifyCertificateChain()` used the first extension with that name. A certificate with a forged deprecated-OID extension (`cA` TRUE) before its genuine `basicConstraints` extension (`cA` FALSE) is accepted as a CA certificate, and the same technique can hide a `pathLenConstraint`. Fixed in node-forge 1.4.1. ### Details `lib/oids.js` maps the deprecated certificate extension OIDs `2.5.29.10` and `2.5.29.13` to the name `basicConstraints`, the same name as the RFC 5280 extension `2.5.29.19`. `certificateExtensionFromAsn1()` in `lib/x509.js` decodes extensions by name, so these extensions are decoded into the same `cA` and `pathLenConstraint` fields. `cert.getExtension()` returns the first extension with a matching name, and `pki.verifyCertificateChain()` looked up `basicConstraints` by name. As a result, a certificate that contains a `2.5.29.10` (or `2.5.29.13`) extension with `cA` TRUE before its genuine `basicConstraints` extension with `cA` FALSE is accepted as a CA certificate. The same technique can hide a CA certificate's `pathLenConstraint`. A deprecated-OID extension on its own also satisfies the check added for GHSA-2328-f5f3-gj25 (CVE-2026-33896) that `basicConstraints` is present. RFC 5280 section 4.2.1.9 defines basicConstraints only as `id-ce 19` (`2.5.29.19`), and the path validation checks in section 6.1.4 apply to that extension. The fix makes chain verification look up basicConstraints by OID (`cert.getExtension({id: '2.5.29.19'})`). This covers both the `cA` and the `pathLenConstraint` checks. Certificate parsing, the OID table and `cert.getExtension('basicConstraints')` are unchanged. #### Patches Fixed in node-forge 1.4.1. Chain verification now uses only the `basicConstraints` extension with OID `2.5.29.19`. #### Workarounds None in node-forge itself. Applications that pass an `options.verify` callback to `pki.verifyCertificateChain()` (or `verify` to `forge.tls.createConnection()`) can reject chains in which a non-leaf certificate has no `2.5.29.19` extension with `cA` TRUE, for example with `cert.getExtension({id: '2.5.29.19'})`. CA operators can avoid copying unrecognized extensions from certificate requests. #### Credits WorkOS Security Team· [security@workos.com](mailto:security@workos.com) (@nickcollisson-workos) ### Proof of concept Have a trusted CA issue an end-entity certificate whose extensions are, in this order: a `2.5.29.10` (or `2.5.29.13`) extension with the value of a basicConstraints `cA` TRUE (DER `30 03 01 01 FF`), then the CA's own `2.5.29.19` basicConstraints with `cA` FALSE, and no `keyUsage`. For example, `openssl x509 -req -copy_extensions copy` with an extensions file that sets `basicConstraints = CA:FALSE` copies the extension from the CSR and produces this order. Use that certificate's key to sign a leaf certificate for any name. On node-forge <= 1.4.0, `forge.pki.verifyCertificateChain(caStore, [leaf, eeCert])` accepts the chain, and `eeCert.getExtension('basicConstraints')` returns the `2.5.29.10` extension with `cA` true. The same certificate without the deprecated-OID extension is rejected ("Certificate basicConstraints indicates the certificate is not a CA."). A certificate with only the deprecated-OID extension is also accepted. The fix adds regression tests in `tests/unit/x509.js` and the reporter's PoC as `tests/pocs/ghsa-5x38-2vff-x55p.js`. ### Impact Applications that verify certificate chains with `forge.pki.verifyCertificateChain()`, including TLS peer certificate verification in `forge.tls`, are affected. Exploitation requires a CA trusted by the application to issue a certificate that contains the attacker-supplied deprecated-OID extension, typically a CA that copies extensions from certificate signing requests. For example, `openssl x509 -req -copy_extensions copy` (or `copyall`) with an extensions file that sets `basicConstraints = CA:FALSE` and no `keyUsage` produces such a certificate. If the issuing CA adds a `keyUsage` extension without `keyCertSign`, node-forge rejects the chain. The holder of such a certificate can then issue certificates for any name that `pki.verifyCertificateChain()` accepts. In forge's own TLS stack this allows impersonating servers (or clients, where client certificates are verified) and intercepting traffic.
Analysis Read only

CVE is a trademark and the CVE logo is a registered trademark of The MITRE Corporation. CVE data may be incomplete, delayed, or inaccurate. This website and all information provided are offered on an “as is” basis without warranties of any kind. This site is not affiliated with, endorsed by, or sponsored by the CVE Program or The MITRE Corporation.

This site uses data from the National Vulnerability Database (NVD), obtained through Dependency-Track, but is not endorsed or certified by the NVD or the National Institute of Standards and Technology (NIST). NVD data may be incomplete, delayed, or inaccurate.

CVSS (Common Vulnerability Scoring System) is owned and managed by FIRST.Org, Inc. and used by permission. The links on CVSS vectors open the FIRST CVSS calculators (CVSS 3.0, 3.1 and 4.0), or the NVD calculator for CVSS 2.0. This site is not affiliated with, endorsed by, or sponsored by FIRST.

GitHub is a trademark of GitHub, Inc. GHSA identifiers and advisory data come from the GitHub Advisory Database, licensed under CC-BY 4.0. GHSA data may be incomplete, delayed, or inaccurate. This site is not affiliated with, endorsed by, or sponsored by GitHub, Inc.

Source of the EUVD data: European Vulnerability Database (EUVD), © European Union Agency for Cybersecurity (ENISA), reused with acknowledgement of the source as provided by the ENISA legal notice and IPR policy. Changes: CVEManager does not display the EUVD records as such; it uses their aliases to link the CVE and GHSA identifiers designating the same vulnerability. EUVD data may be incomplete, delayed, or inaccurate. This site is not affiliated with, endorsed by, or sponsored by ENISA or the European Union.