chore(deps): update dependency node-forge to v1.4.0 [security]#143
Open
renovate[bot] wants to merge 1 commit intodevelopfrom
Open
chore(deps): update dependency node-forge to v1.4.0 [security]#143renovate[bot] wants to merge 1 commit intodevelopfrom
renovate[bot] wants to merge 1 commit intodevelopfrom
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
1.3.3→1.4.0GitHub Vulnerability Alerts
CVE-2026-33894
Summary
RSASSA PKCS#1 v1.5 signature verification accepts forged signatures for low public exponent keys (e=3). Attackers can forge signatures by stuffing “garbage” bytes within the ASN structure in order to construct a signature that passes verification, enabling Bleichenbacher style forgery. This issue is similar to CVE-2022-24771, but adds bytes in an addition field within the ASN structure, rather than outside of it.
Additionally, forge does not validate that signatures include a minimum of 8 bytes of padding as defined by the specification, providing attackers additional space to construct Bleichenbacher forgeries.
Impacted Deployments
Tested commit:
8e1d527fe8ec2670499068db783172d4fb9012e5Affected versions: tested on v1.3.3 (latest release) and recent prior versions.
Configuration assumptions:
schemeuses RSASSA-PKCS1-v1_5)._parseAllDigestBytes: true(default setting).Root Cause
In
lib/rsa.js,key.verify(...), forge decrypts the signature block, decodes PKCS#1 v1.5 padding (_decodePkcs1_v1_5), parses ASN.1, and comparescapture.digestto the provided digest.Two issues are present with this logic:
_parseAllDigestBytes) only guarantees all bytes are parsed, not that the parsed structure is the canonical minimal DigestInfo shape expected by RFC 8017 verification semantics. A forged EM with attacker-controlled additional ASN.1 content inside the parsed container can still pass forge verification while OpenSSL rejects it._decodePkcs1_v1_5comments mention that PS < 8 bytes should be rejected, but does not implement this logic.Reproduction Steps
v24.9.0) and clonedigitalbazaar/forgeat commit8e1d527fe8ec2670499068db783172d4fb9012e5.repro_min.js) withnode repro_min.jsin the same level as theforgefolder.4096bits,e=3), creates a normal control signature, then computes a forged candidate using cube-root interval construction._parseAllDigestBytes: true), andcrypto.verifywithRSA_PKCS1_PADDING).control-forge-strict: truecontrol-node: trueforgery (forge library, strict): trueforgery (node/OpenSSL): falseProof of Concept
Overview:
_parseAllDigestBytes: true, also forge default).repro_min.js
Suggested Patch
PS >= 8) in_decodePkcs1_v1_5before accepting the block.Here is a Forge-tested patch to resolve the issue, though it should be verified for consumer projects:
Resources
lib/rsa.jskey.verify(...)at lines ~1139-1223.lib/rsa.js_decodePkcs1_v1_5(...)at lines ~1632-1695.Credit
This vulnerability was discovered as part of a U.C. Berkeley security research project by: Austin Chu, Sohee Kim, and Corban Villa.
CVE-2026-33891
Summary
A Denial of Service (DoS) vulnerability exists in the node-forge library due to an infinite loop in the BigInteger.modInverse() function (inherited from the bundled jsbn library). When modInverse() is called with a zero value as input, the internal Extended Euclidean Algorithm enters an unreachable exit condition, causing the process to hang indefinitely and consume 100% CPU.
Affected Package
Package name: node-forge (npm: node-forge)
Repository: https://github.com/digitalbazaar/forge
Affected versions: All versions (including latest)
Affected file: lib/jsbn.js, function bnModInverse()
Root cause component: Bundled copy of the jsbn (JavaScript Big Number) library
Vulnerability Details
Type: Denial of Service (DoS)
CWE: CWE-835 (Loop with Unreachable Exit Condition)
Attack vector: Network (if the application processes untrusted input that reaches modInverse)
Privileges required: None
User interaction: None
Impact: Availability (process hangs indefinitely)
Suggested CVSS v3.1 score: 5.3–7.5 (depending on the context of usage)
Root Cause Analysis
The BigInteger.prototype.modInverse(m) function in lib/jsbn.js implements the Extended Euclidean Algorithm to compute the modular multiplicative inverse of this modulo m.
Mathematically, the modular inverse of 0 does not exist — gcd(0, m) = m ≠ 1 for any m > 1. However, the implementation does not check whether the input value is zero before entering the algorithm's main loop. When this equals 0, the algorithm's loop condition is never satisfied for termination, resulting in an infinite loop.
The relevant code path in lib/jsbn.js:
Attack Scenario
Any application using node-forge that passes attacker-controlled or untrusted input to a code path involving modInverse() is vulnerable. Potential attack surfaces include:
DSA/ECDSA signature verification — A crafted signature with s = 0 would trigger s.modInverse(q), causing the verifier to hang.
Custom RSA or Diffie-Hellman implementations — Applications performing modular arithmetic with user-supplied parameters.
Any cryptographic protocol where an attacker can influence a value that is subsequently passed to modInverse().
A single malicious request can cause the Node.js event loop to block indefinitely, rendering the entire application unresponsive.
Proof of Concept
Environment Setup
Reproduction (poc.js)
A single script that safely detects the vulnerability using a child process with timeout. The parent process is never at risk of hanging.
Expected Output
node-forge v1.3.1 (latest at time of writing)
Node.js v18.x / v20.x / v22.x
macOS / Linux / Windows
Impact
Availability: An attacker can cause a complete Denial of Service by sending a single crafted input that reaches the modInverse() code path. The Node.js process will hang indefinitely, blocking the event loop and making the application unresponsive to all subsequent requests.
Scope: node-forge is a widely used cryptographic library with millions of weekly downloads on npm. Any application that processes untrusted cryptographic parameters through node-forge may be affected.
Suggested Fix
Add a zero-value check at the entry of bnModInverse() in lib/jsbn.js:
Alternatively, return BigInteger.ZERO if that behavior is preferred, though throwing an error is more mathematically correct and consistent with other BigInteger implementations (e.g., Java's BigInteger.modInverse() throws ArithmeticException).
CVE-2026-33895
Summary
Ed25519 signature verification accepts forged non-canonical signatures where the scalar S is not reduced modulo the group order (
S >= L). A valid signature and itsS + Lvariant both verify in forge, while Node.jscrypto.verify(OpenSSL-backed) rejects theS + Lvariant, as defined by the specification. This class of signature malleability has been exploited in practice to bypass authentication and authorization logic (see CVE-2026-25793, CVE-2022-35961). Applications relying on signature uniqueness (i.e., dedup by signature bytes, replay tracking, signed-object canonicalization checks) may be bypassed.Impacted Deployments
Tested commit:
8e1d527fe8ec2670499068db783172d4fb9012e5Affected versions: tested on v1.3.3 (latest release) and all versions since Ed25519 was implemented.
Configuration assumptions:
ed25519.verify(...)).Root Cause
In
lib/ed25519.js,crypto_sign_open(...)uses the signature's last 32 bytes (S) directly in scalar multiplication:There is no prior check enforcing
S < L(Ed25519 group order). As a result, equivalent scalar classes can pass verification, including a modified signature whereS := S + L (mod 2^256)when that value remains non-canonical. The PoC demonstrates this by mutating only the S half of a valid 64-byte signature.Reproduction Steps
v24.9.0) and clonedigitalbazaar/forgeat commit8e1d527fe8ec2670499068db783172d4fb9012e5.poc.js) withnode poc.jsin the same level as theforgefolder.crypto.verify).{ "forge": { "original_valid": true, "tweaked_valid": true }, "crypto": { "original_valid": true, "tweaked_valid": false } }Proof of Concept
Overview:
poc.js
Suggested Patch
Add strict canonical scalar validation in Ed25519 verify path before scalar multiplication. (Parse S as little-endian 32-byte integer and reject if
S >= L).Here is a patch we tested on our end to resolve the issue, though please verify it on your end:
Resources
Credit
This vulnerability was discovered as part of a U.C. Berkeley security research project by: Austin Chu, Sohee Kim, and Corban Villa.
CVE-2026-33896
Summary
pki.verifyCertificateChain()does not enforce RFC 5280 basicConstraints requirements when an intermediate certificate lacks both thebasicConstraintsandkeyUsageextensions. 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, theverifyCertificateChain()function (around lines 3147-3199) has two conditional checks for CA authorization:keyUsagecheck (which includes a sub-check requiringbasicConstraintsto be present) is gated onkeyUsageExt !== nullbasicConstraints.cAcheck is gated onbcExt !== nullWhen 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:
The absence of
basicConstraintsshould result in rejection, not acceptance.Proof of Concept
Results:
basicConstraints.cA=false: correctly rejectedkeyUsage(nokeyCertSign): correctly rejectedAttack Scenario
An attacker who obtains any valid leaf certificate (e.g., a regular TLS certificate for
attacker.com) that lacksbasicConstraintsandkeyUsageextensions can use it to sign certificates for ANY domain. Any application using node-forge'sverifyCertificateChain()will accept the forged chain.This affects applications using node-forge for:
CVE Precedent
This is the same vulnerability class as:
Not a Duplicate
This is distinct from:
Suggested Fix
Add an explicit check for absent
basicConstraintson non-leaf certificates:Disclosure Timeline
Credits
Discovered and reported by Doruk Tan Ozturk (@peaktwilight) — doruk.ch
Forge has a basicConstraints bypass in its certificate chain verification (RFC 5280 violation)
CVE-2026-33896 / GHSA-2328-f5f3-gj25
More information
Details
Summary
pki.verifyCertificateChain()does not enforce RFC 5280 basicConstraints requirements when an intermediate certificate lacks both thebasicConstraintsandkeyUsageextensions. 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, theverifyCertificateChain()function (around lines 3147-3199) has two conditional checks for CA authorization:keyUsagecheck (which includes a sub-check requiringbasicConstraintsto be present) is gated onkeyUsageExt !== nullbasicConstraints.cAcheck is gated onbcExt !== nullWhen 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:
The absence of
basicConstraintsshould result in rejection, not acceptance.Proof of Concept
Results:
basicConstraints.cA=false: correctly rejectedkeyUsage(nokeyCertSign): correctly rejectedAttack Scenario
An attacker who obtains any valid leaf certificate (e.g., a regular TLS certificate for
attacker.com) that lacksbasicConstraintsandkeyUsageextensions can use it to sign certificates for ANY domain. Any application using node-forge'sverifyCertificateChain()will accept the forged chain.This affects applications using node-forge for:
CVE Precedent
This is the same vulnerability class as:
Not a Duplicate
This is distinct from:
Suggested Fix
Add an explicit check for absent
basicConstraintson non-leaf certificates:Disclosure Timeline
Credits
Discovered and reported by Doruk Tan Ozturk (@peaktwilight) — doruk.ch
Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Forge has Denial of Service via Infinite Loop in BigInteger.modInverse() with Zero Input
CVE-2026-33891 / GHSA-5m6q-g25r-mvwx
More information
Details
Summary
A Denial of Service (DoS) vulnerability exists in the node-forge library due to an infinite loop in the BigInteger.modInverse() function (inherited from the bundled jsbn library). When modInverse() is called with a zero value as input, the internal Extended Euclidean Algorithm enters an unreachable exit condition, causing the process to hang indefinitely and consume 100% CPU.
Affected Package
Package name: node-forge (npm: node-forge)
Repository: https://github.com/digitalbazaar/forge
Affected versions: All versions (including latest)
Affected file: lib/jsbn.js, function bnModInverse()
Root cause component: Bundled copy of the jsbn (JavaScript Big Number) library
Vulnerability Details
Type: Denial of Service (DoS)
CWE: CWE-835 (Loop with Unreachable Exit Condition)
Attack vector: Network (if the application processes untrusted input that reaches modInverse)
Privileges required: None
User interaction: None
Impact: Availability (process hangs indefinitely)
Suggested CVSS v3.1 score: 5.3–7.5 (depending on the context of usage)
Root Cause Analysis
The BigInteger.prototype.modInverse(m) function in lib/jsbn.js implements the Extended Euclidean Algorithm to compute the modular multiplicative inverse of this modulo m.
Mathematically, the modular inverse of 0 does not exist — gcd(0, m) = m ≠ 1 for any m > 1. However, the implementation does not check whether the input value is zero before entering the algorithm's main loop. When this equals 0, the algorithm's loop condition is never satisfied for termination, resulting in an infinite loop.
The relevant code path in lib/jsbn.js:
Attack Scenario
Any application using node-forge that passes attacker-controlled or untrusted input to a code path involving modInverse() is vulnerable. Potential attack surfaces include:
DSA/ECDSA signature verification — A crafted signature with s = 0 would trigger s.modInverse(q), causing the verifier to hang.
Custom RSA or Diffie-Hellman implementations — Applications performing modular arithmetic with user-supplied parameters.
Any cryptographic protocol where an attacker can influence a value that is subsequently passed to modInverse().
A single malicious request can cause the Node.js event loop to block indefinitely, rendering the entire application unresponsive.
Proof of Concept
Environment Setup
Reproduction (poc.js)
A single script that safely detects the vulnerability using a child process with timeout. The parent process is never at risk of hanging.
Expected Output
node-forge v1.3.1 (latest at time of writing)
Node.js v18.x / v20.x / v22.x
macOS / Linux / Windows
Impact
Availability: An attacker can cause a complete Denial of Service by sending a single crafted input that reaches the modInverse() code path. The Node.js process will hang indefinitely, blocking the event loop and making the application unresponsive to all subsequent requests.
Scope: node-forge is a widely used cryptographic library with millions of weekly downloads on npm. Any application that processes untrusted cryptographic parameters through node-forge may be affected.
Suggested Fix
Add a zero-value check at the entry of bnModInverse() in lib/jsbn.js:
Alternatively, return BigInteger.ZERO if that behavior is preferred, though throwing an error is more mathematically correct and consistent with other BigInteger implementations (e.g., Java's BigInteger.modInverse() throws ArithmeticException).
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:HReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Forge has signature forgery in RSA-PKCS due to ASN.1 extra field
CVE-2026-33894 / GHSA-ppp5-5v6c-4jwp
More information
Details
Summary
RSASSA PKCS#1 v1.5 signature verification accepts forged signatures for low public exponent keys (e=3). Attackers can forge signatures by stuffing “garbage” bytes within the ASN structure in order to construct a signature that passes verification, enabling Bleichenbacher style forgery. This issue is similar to CVE-2022-24771, but adds bytes in an addition field within the ASN structure, rather than outside of it.
Additionally, forge does not validate that signatures include a minimum of 8 bytes of padding as defined by the specification, providing attackers additional space to construct Bleichenbacher forgeries.
Impacted Deployments
Tested commit:
8e1d527fe8ec2670499068db783172d4fb9012e5Affected versions: tested on v1.3.3 (latest release) and recent prior versions.
Configuration assumptions:
schemeuses RSASSA-PKCS1-v1_5)._parseAllDigestBytes: true(default setting).Root Cause
In
lib/rsa.js,key.verify(...), forge decrypts the signature block, decodes PKCS#1 v1.5 padding (_decodePkcs1_v1_5), parses ASN.1, and comparescapture.digestto the provided digest.Two issues are present with this logic:
_parseAllDigestBytes) only guarantees all bytes are parsed, not that the parsed structure is the canonical minimal DigestInfo shape expected by RFC 8017 verification semantics. A forged EM with attacker-controlled additional ASN.1 content inside the parsed container can still pass forge verification while OpenSSL rejects it._decodePkcs1_v1_5comments mention that PS < 8 bytes should be rejected, but does not implement this logic.Reproduction Steps
v24.9.0) and clonedigitalbazaar/forgeat commit8e1d527fe8ec2670499068db783172d4fb9012e5.repro_min.js) withnode repro_min.jsin the same level as theforgefolder.4096bits,e=3), creates a normal control signature, then computes a forged candidate using cube-root interval construction._parseAllDigestBytes: true), andcrypto.verifywithRSA_PKCS1_PADDING).control-forge-strict: truecontrol-node: trueforgery (forge library, strict): trueforgery (node/OpenSSL): falseProof of Concept
Overview:
_parseAllDigestBytes: true, also forge default).repro_min.js
Suggested Patch
PS >= 8) in_decodePkcs1_v1_5before accepting the block.Here is a Forge-tested patch to resolve the issue, though it should be verified for consumer projects:
Resources
lib/rsa.jskey.verify(...)at lines ~1139-1223.lib/rsa.js_decodePkcs1_v1_5(...)at lines ~1632-1695.Credit
This vulnerability was discovered as part of a U.C. Berkeley security research project by: Austin Chu, Sohee Kim, and Corban Villa.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:NReferences