VYPR
High severityNVD Advisory· Published Mar 23, 2026· Updated Mar 23, 2026

CVE-2026-4598

CVE-2026-4598

Description

Versions of the package jsrsasign before 11.1.1 are vulnerable to Infinite loop via the bnModInverse function in ext/jsbn2.js when the BigInteger.modInverse implementation receives zero or negative inputs, allowing an attacker to hang the process permanently by supplying such crafted values (e.g., modInverse(0, m) or modInverse(-1, m)).

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

The jsrsasign library before 11.1.1 contains an infinite loop in BigInteger.modInverse for zero or negative inputs, enabling denial of service via crafted values.

Vulnerability

Description The vulnerability resides in the bnModInverse function within ext/jsbn2.js of the jsrsasign library (all versions before 11.1.1). The function implements a binary extended GCD algorithm that assumes its input is a positive integer coprime to the modulus. When provided with zero (e.g., modInverse(0, m)) or negative (e.g., modInverse(-1, m)) inputs, the algorithm fails to converge: zero input results in an unreachable exit condition because gcd(0, m) = m ≠ 1, while negative input causes oscillation between positive and negative values during subtraction steps. This corresponds to CWE-835: Loop with Unreachable Exit Condition [1][2].

Attack

Surface and Exploitation Any code path that calls BigInteger.modInverse with attacker-controlled input is vulnerable. Internal uses include RSA blinding factor computations, elliptic curve point operations (via ECFieldElementFp.prototype.divide), and DSA/ECDSA signature verification (where a zero signature component s triggers the hang). An attacker who can supply crafted values to such operations can cause a permanent process hang, effectively resulting in a denial of service (DoS) [1][2].

Impact

Successful exploitation leads to a denial of service by hanging the process indefinitely. This can affect server-side applications using jsrsasign for cryptographic operations, such as signature verification or key generation, potentially disrupting availability. The vulnerability does not require authentication if the attacker can influence input used in modInverse [1][2].

Mitigation

Status The issue is fixed in jsrsasign version 11.1.0 (released after the vulnerability was reported). The fix, contributed via commit ca5b027, normalizes negative inputs by reducing modulo m and returns zero for zero inputs [4]. Users are advised to upgrade to version 11.1.1 or later. Note that the jsrsasign project announced end-of-support effective June 3, 2026, and will no longer receive updates after that date [3]. No official workarounds are available for unpatched versions.

AI Insight generated on May 18, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
jsrsasignnpm
< 11.1.111.1.1

Affected products

2

Patches

1
ca5b02724028

Merge pull request #648 from Kr0emer/fix/bug-004-modinverse-dos

https://github.com/kjur/jsrsasignKenji UrushimaFeb 20, 2026via ghsa
2 files changed · +19 4
  • ext/jsbn2.js+6 4 modified
    @@ -508,15 +508,17 @@ function bnpModInt(n) {
     
     // (public) 1/this % m (HAC 14.61)
     function bnModInverse(m) {
    +  if(m.signum() == 0) return BigInteger.ZERO;
    +  var x = this.mod(m);
       var ac = m.isEven();
    -  if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
    -  var u = m.clone(), v = this.clone();
    +  if((x.isEven() && ac) || x.signum() == 0) return BigInteger.ZERO;
    +  var u = m.clone(), v = x.clone();
       var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
       while(u.signum() != 0) {
         while(u.isEven()) {
           u.rShiftTo(1,u);
           if(ac) {
    -        if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
    +        if(!a.isEven() || !b.isEven()) { a.addTo(x,a); b.subTo(m,b); }
             a.rShiftTo(1,a);
           }
           else if(!b.isEven()) b.subTo(m,b);
    @@ -525,7 +527,7 @@ function bnModInverse(m) {
         while(v.isEven()) {
           v.rShiftTo(1,v);
           if(ac) {
    -        if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
    +        if(!c.isEven() || !d.isEven()) { c.addTo(x,c); d.subTo(m,d); }
             c.rShiftTo(1,c);
           }
           else if(!d.isEven()) d.subTo(m,d);
    
  • test/qunit-do-crypto.html+13 0 modified
    @@ -257,6 +257,19 @@
       "reject mod(0)");
     });
     
    +test("BigInteger.modInverse returns quickly for zero input", function() {
    +  var biM = new BigInteger("97", 10);
    +  var biR = new BigInteger("0", 10).modInverse(biM);
    +  equal(biR.compareTo(BigInteger.ZERO), 0, "0 has no inverse");
    +});
    +
    +test("BigInteger.modInverse normalizes negative input", function() {
    +  var biM1 = new BigInteger("7", 10);
    +  var biM2 = new BigInteger("97", 10);
    +  equal(new BigInteger("-1", 10).modInverse(biM1).toString(10), "6", "-1 mod 7");
    +  equal(new BigInteger("-13", 10).modInverse(biM2).toString(10), "82", "-13 mod 97");
    +});
    +
     test("MessageDigest test", function() {
       expect(10);
       var md1 = new KJUR.crypto.MessageDigest({"alg": "sha1", "prov": "cryptojs"});
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.