GitHub Advisoryadvisory · npm
GHSA-h6cr-wjv9-3cpp Forge: Denial of Service via infinite loop in BigInteger.modInverse() with negative input (incomplete fix of CVE-2026-33891)
LOW
Official page ↗
- Aliases
- CVE-2026-118781
- Ecosystem
- npm
- Packages
- node-forge
- Severity
- Low
- CVSS vector
- CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L
- Weaknesses
- CWE-835
- Reviewed
- 2026-10-30
Affected packages
• npm node-forge: < 1.4.1 → fixed in 1.4.1
Description
Summary
`BigInteger.prototype.modInverse()` in node-forge's bundled jsbn library enters an infinite loop when the value or the modulus is negative, for example when a negative public exponent is passed to `forge.pki.rsa.generateKeyPair()`. This is an incomplete fix of CVE-2026-33891 (GHSA-5m6q-g25r-mvwx), which handled only a zero value. Fixed in node-forge 1.4.1.
Details
`bnModInverse()` (`lib/jsbn.js`, exposed as `forge.jsbn.BigInteger.prototype.modInverse`) implements the binary extended Euclidean algorithm (Handbook of Applied Cryptography, Algorithm 14.61), which is defined for positive integers. With a negative operand the loop cannot terminate: `rShiftTo` is an arithmetic shift, so a negative value never moves towards zero, and the loop's exit condition (`u` reaching zero) is never met. The calling thread spins at 100% CPU indefinitely; in Node.js this blocks the event loop. Memory does not grow.
node-forge 1.4.0 fixed CVE-2026-33891 (GHSA-5m6q-g25r-mvwx) by returning zero early when `this.signum() == 0`, although its changelog describes the check as "= 3`.
• Do not call `BigInteger#modInverse()` with negative operands. Reduce the value modulo a positive modulus first (`x.mod(m).modInverse(m)`).
Proof of concept
A negative public exponent passed to RSA key generation never returns (also with the callback form and with `createKeyPairGenerationState()` / `stepKeyPairGenerationState()`):
var forge = require('node-forge');
forge.pki.rsa.generateKeyPair({bits: 256, e: -1}); // hangs at 100% CPU
Calling `modInverse()` directly with a negative value or modulus hangs the same way:
var BigInteger = forge.jsbn.BigInteger;
new BigInteger('-1').modInverse(new BigInteger('7')); // hangs
new BigInteger('3').modInverse(new BigInteger('-7')); // hangs
With the fix, these calls return zero. The regression tests are in `tests/unit/jsbn.js`.
Impact
Applications are affected only if they:
• pass an untrusted value as the RSA public exponent `e` to `forge.pki.rsa.generateKeyPair()`, `forge.pki.rsa.createKeyPairGenerationState()` or `forge.pki.rsa.stepKeyPairGenerationState()`, or
• call `forge.jsbn.BigInteger#modInverse()` directly with negative values derived from untrusted input.
An attacker who can supply such a value makes the call hang indefinitely at 100% CPU, which blocks the Node.js event loop (denial of service). Keys and other data parsed by node-forge (DER, PEM, JWK, PKCS#12, X.509, TLS) cannot trigger this issue, and the documented usage of key generation passes a constant exponent (65537). There is no effect on confidentiality or integrity.
Related
Alias · CVE (1)
- CVE-2026-118781 Forge (also called node-forge) is a native implementation of Transport Layer Security in JavaScript. vulnerability
Weakness · CWE (1)
- CWE-835 Loop with Unreachable Exit Condition weakness
References
- https://github.com/digitalbazaar/forge/security/advisories/GHSA-h6cr-wjv9-3cpp web
- https://nvd.nist.gov/vuln/detail/CVE-2026-118781 advisory
- https://github.com/digitalbazaar/forge/commit/e96c47b7f006dec66fb7bb1934e7375498b04a72 web
- https://github.com/digitalbazaar/forge package
- https://github.com/digitalbazaar/forge/releases/tag/v1.4.1 web