Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessTarget app deriving GCM tagLength from received tag
-
DeliverySend ciphertext with empty or missing authentication tag
-
ExploitEmpty computed tag matches empty supplied tag
-
Executiondecipher.finish() returns true unauthenticated
-
ImpactApplication accepts forged or modified plaintext as authentic
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A08:2025 - Software or Data Integrity Failures
ASVS 5.0
V15 - Secure Coding and Architecture Integrity verification
|
| Exploitation Conditions | Exploitation requires the application to call forge.cipher.createDecipher('AES-GCM') and pass a zero-like tagLength value - specifically 0, null, false, '', or '0' (any value that Number()-converts to 0) - most commonly when tagLength is derived from the length of a received authentication tag (e.g. receivedTag.length * 8 for an empty tag) or left as an unset/zero configuration value. The attacker must also supply an empty or missing tag. Limiting factors that sharply narrow real-world exposure: applications that omit tagLength entirely (using the 128-bit default) or pass any fixed valid NIST tag length (128, 120, 112, 104, 96, 64 or 32 bits) are NOT affected, and the flaw only exists in node-forge <= 1.4.0. The impact is restricted to integrity (message forgery/modification); there is no confidentiality or availability impact. |
| Impact | This is a genuine but conditional integrity flaw, not a blanket critical issue. The CVSS 3.1 vector (AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N, 5.9 Moderate) is internally consistent with the mechanism: the attack is network-reachable and needs no attacker privileges or user interaction (PR:N/UI:N), but AC:H correctly reflects that success depends on a condition outside the attacker's control - the application must call forge.cipher.createDecipher('AES-GCM') with a zero-like tagLength (0, null, false, '', '0'), typically one derived from the length of a received tag. Impact is integrity-only (C:N/I:H/A:N): an empty computed tag makes decipher.finish() accept any ciphertext as authentic, enabling message forgery and, because GCM is a stream cipher, targeted plaintext modification. No EPSS score, KEV listing, or SSVC automatable/technical-impact values were provided in the input, so probabilistic exploitation signals are absent and cannot be weighed. The vuln.today decision label is 'this_month' (not act_now/emergency), and the vendor rates it Moderate; there is no CISA KEV entry, so this should be treated as a scheduled-remediation item rather than an emergency. One divergence worth noting: the vendor's informational CVSS 4.0 vector scores it 8.2 (High) because 4.0 weights the attack preconditions (AT:P) differently; the authoritative rating follows CVSS 3.1 at 5.9. The real-world risk is concentrated in the subset of deployments that derive tagLength from received data - applications that omit tagLength (128-bit default) or pass a fixed valid length are not affected at all. |
| Exploit ScenarioDerived | An attacker who can deliver ciphertext to an application that starts an AES-GCM decipher with a tagLength derived from received data - e.g. tagLength: receivedTag.length * 8, which is 0 for an empty tag - submits attacker-chosen bytes with an empty or missing authentication tag; on node-forge <= 1.4.0 decipher.finish() returns true, so the forged data is accepted as authentic, and because GCM is a stream cipher an attacker who knows the plaintext can also flip it to chosen values. The GHSA advisory (GHSA-5cwg-6vw7-rj6p) includes a working proof-of-concept snippet demonstrating this; it is a public PoC reference and not independently verified here as standalone weaponized exploit code. Network vector with no authentication or user interaction, but AC:H because it only works when the application already passes a zero-like tagLength. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Oct 29, 2026
AES-GCM authentication bypass in node-forge (digitalbazaar) versions up to and including 1.4.0: when an application passes a zero-like tagLength (0, null, false, '', or '0') to forge.cipher.createDecipher('AES-GCM') and the supplied authentication tag is empty or missing, decipher.finish() returns true for arbitrary attacker-chosen ciphertext, so forged or modified messages are accepted as authentic. Exploitation is conditional - it requires the application to derive tagLength from received data (for example receivedTag.length * 8 for an empty tag) or to leave it as an unset/zero configuration value; applications that omit tagLength (128-bit default) or pass a fixed valid NIST tag length are not affected. The flaw is integrity-only (C:N/I:H/A:N, CVSS 3.1 5.9 with AC:H) and a public PoC reference exists in the GHSA advisory showing the tagLength: 0 / empty-tag construction; no confirmed active exploitation (CISA KEV) or working exploit code was identified at time of analysis.
RemediationAI
Vendor-released patch: node-forge 1.4.1 (https://github.com/digitalbazaar/forge/releases/tag/v1.4.1), which validates tagLength in modes.gcm.start(), permits only 128, 120, 112, 104, 96, 64 or 32 bits, defaults null/undefined to 128, and throws 'Invalid tag length.' for 0, false, '', '0', 8, 256 and similar values. Upgrade to 1.4.1 or later, then audit every forge.cipher.createDecipher('AES-GCM') call site for a tagLength derived from received data or from configuration, since such code will now throw rather than silently misbehave; note the advisory's compatibility warning that data previously encrypted with an empty tag can no longer be decrypted. If upgrading is not immediately possible, the vendor workaround is to never derive tagLength from received data - pass a fixed valid tag length or omit it for the 128-bit default - and to check the received tag length before start(), e.g. if(tag.length !== 16) { throw new Error('Invalid tag.'); } before decipher.start({iv: iv, tag: tag}); the trade-off is that this guard must be added at every decryption site and does not cover callers that intentionally pass short NIST tag lengths without the corresponding check. Details are in the advisory at https://github.com/digitalbazaar/forge/security/advisories/GHSA-5cwg-6vw7-rj6p and the fix commit at https://github.com/digitalbazaar/forge/commit/236845d96c71207259f91638d0138bba8e2fd624.
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 2 packages in npm, euvd
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
node-forge is a pure-JavaScript implementation of TLS and cryptographic primitives for Node.js and browsers, and its GCM mode lives in lib/cipherModes.js with dispatch logic in lib/cipher.js. The root cause class is CWE-354 (improper validation of integrity check value), with the advisory also classifying it as CWE-1284 (improper validation of a specified quantity). modes.gcm.prototype.start() stored the caller-supplied tagLength without validation, and the documentation even stated the option accepted '0-128'. On finish, afterFinish() truncated the 16-byte authentication tag with truncate(16 % (tagLength / 8)); for a value that Number()-converts to 0 this becomes 16 % 0 = NaN, and truncating by NaN yields an empty tag. On decryption the start-time length check (supplied tag must be tagLength / 8 bytes) trivially passes for an empty tag, so the final comparison compares two empty strings and returns true. NIST SP 800-38D section 5.2.1.2 permits only 128, 120, 112, 104 and 96 bits (plus 64 and 32 for specific applications); the fix in 1.4.1 converts tagLength with Number(), treats null/undefined as the 128-bit default, rejects anything outside that NIST set with 'Invalid tag length.', and still accepts numeric strings such as '128'. Because GCM is a stream cipher, an attacker who knows part of a captured message's plaintext can also rewrite it to chosen values once the tag check is bypassed. The trigger is documented precisely in the GHSA, including PoC code and regression tests in tests/unit/aes.js.
Know when Forge gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N
Network-delivered forgery needing no attacker privileges or interaction (PR:N/UI:N), but AC:H because success depends on the app using a zero-like tagLength outside attacker control; integrity-only impact.
Primary rating from Vendor (GitHub_M).
CVSS VectorVendor: GitHub_M
Lifecycle Timeline
2DescriptionCVE.org
Forge (also called node-forge) is a native implementation of Transport Layer Security in JavaScript. Prior to 1.4.1, node-forge did not validate the AES-GCM tagLength option passed to start() during decryption through forge.cipher.createDecipher(). When an application derived tagLength from received data or used an unset or zero-like configuration value, a value that converted to zero together with an empty or missing authentication tag caused the calculated and supplied tags to compare as empty, so decipher.finish() accepted unauthenticated ciphertext. Applications that omit tagLength to use the 128-bit default or pass a fixed valid tag length are unaffected. This issue is fixed in version 1.4.1.
Blast Radius
ecosystem impact- 6 npm packages depend on node-forge (3 direct, 3 indirect)
Ecosystem-wide dependent count for version 1.4.1.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Authentication bypass attacks exploit flaws in the verification mechanisms that control access to systems and applications.
An interpretation-conflict (CWE-436) vulnerability in node-forge versions 1.3.1 and earlier enables unauthenticated atta
The package node-forge before 0.10.0 is vulnerable to Prototype Pollution via the util.setPath function. Rated high seve
RSA PKCS#1 v1.5 signature forgery in node-forge through v1.4.0 enables unauthenticated network attackers to craft signat
Forge (also called `node-forge`) is a native implementation of Transport Layer Security in JavaScript. Rated high severi
Regular expression denial of service in node-forge's pem.decode() allows remote, unauthenticated attackers to block the
Denial of service in node-forge (Forge) 1.3.2 through 1.4.0 lets remote, unauthenticated attackers exhaust CPU time and
Denial of service in node-forge's JavaScript TLS implementation: a connection created with forge.tls.createConnection()
Call stack exhaustion in node-forge's TLS record processing (all versions through 1.4.0) allows a remote peer to crash o
PKCS#12 MAC forgery and constant-key password-based decryption in node-forge 1.4.0 and earlier let anyone who does not k
Forge (also called `node-forge`) is a native implementation of Transport Layer Security in JavaScript. Rated high severi
Forge (also called `node-forge`) is a native implementation of Transport Layer Security in JavaScript. Rated high severi
Certificate chain validation in node-forge (Forge) through version 1.4.0 can be bypassed because the parser maps the dep
EUVD-2026-113363
GHSA-5cwg-6vw7-rj6p
NVD
CVE.org
EPSS
Vulnrichment
Exploit-DB