CVE-2026-0994: Google Protobuf Flaw Enables Remote Denial-of-Service Attacks

CVE-2026-0994 — Google Protobuf JSON Any Parsing DoS (Python)

CVE Name: Recursive JSON Any Parsing Denial-of-Service
CVE ID: CVE-2026-0994
CVSS Score: 8.2 (High)
Severity: High – Denial of Service resulting in application crash or worker outage
Exploitability: Attackers can send crafted JSON to trigger excessive recursion without any privileges
Exploit Availability: Public proof-of-concept exists in public issue threads
Official Patch / Upgrade: Link provided below


What This Vulnerability Actually Is

This vulnerability affects how the Python implementation of Google Protocol Buffers (protobuf) handles JSON input that includes deeply nested Any type messages.

In many Python services, developers receive JSON payloads from clients, convert that JSON into protobuf message objects, and then process those objects. The conversion function most people use is json_format.ParseDict() from the google.protobuf library.

Within protobuf, there’s a special message type called Any. Its job is to wrap arbitrary message types in a standardized envelope. You can think of Any as a generic container. The problem with CVE-2026-0994 is that when ParseDict() encounters nested Any containers, the code that handles them did not count those nested structures toward the recursion limit that the library is supposed to enforce.

In simpler terms:

  • The parser tries to limit how deep the JSON can nest to prevent runaway recursion
  • Any containers were being handled in a code path that didn’t count toward that limit
  • Attackers can craft JSON with many levels of Any wrapping inside Any
  • The parser keeps going until Python’s recursion limit is hit
  • Once Python hits that limit, it raises a RecursionError and the process may crash

Most services don’t catch this specific exception in a controlled way, so the result is often a crashed worker or an entire service outage on endpoints that parse JSON into protobuf.


How an Attacker Could Exploit This

If you operate a service or function that takes JSON from external clients and converts it to protobuf messages using standard tooling like json_format.ParseDict(), here’s what an attacker can do:

  1. Locate an endpoint that accepts JSON — REST API, gRPC JSON transcoding, webhook receivers, or any client-driven input endpoint.
  2. Create a JSON document where each object wraps another object via Any. That looks like many nested layers of {"@type": "...google.protobuf.Any...", "value": { ... }}.
  3. Send this payload to your API or ingestion service.
  4. The protobuf parser starts decoding and goes deeper with each nested Any.
  5. Because the parser fails to count those against its recursion checks, the call stack grows until Python itself refuses to go deeper and throws a RecursionError.
  6. If your service does not catch and handle this exception safely, that worker dies, your thread exits, or the service may restart.

From an attacker’s perspective, this is a very low-effort attack. You don’t need special credentials. You don’t need to be authenticated. You only need to find an endpoint that reaches protobuf JSON parsing logic.


What Happens Inside the Code

At its core, this flaw happens because of a subtle mistake: the part of the code responsible for unpacking Any messages bypassed the function that tracks recursion depth. In typical protobuf parsing, a counter increments at each nested level so that developers can supply a max_recursion_depth value. That counter ensures untrusted input can’t bog the parser down forever.

Unfortunately, the portion that handles Any wraps turns that logic off for every nested Any. That means you can nest dozens or hundreds of layers without tripping the safety check. Python will keep pushing new stack frames for each level until it simply says, “no more” — and raises a RecursionError.


Proof-of-Concept (PoC) Behavior

The publicly discussed PoC doesn’t exploit any remote service; it runs locally against the vulnerable library to demonstrate the failure mode.

A typical PoC will:

  • Construct a JSON object with repeated nested Any objects
  • Call ParseDict() with a strict max_recursion_depth setting like 5 or 10
  • Observe that the library does not throw a normal parse-error at the configured depth
  • Instead, Python throws RecursionError: maximum recursion depth exceeded because the recursion limit got bypassed

This tells us two things:

  1. The depth check isn’t functioning correctly for nested Any
  2. Python runs out of stack before the library throws a controlled exception

In real attack scenarios, you’d see this behavior manifest as timeouts, crashes, or worker exits.


Signs of a Successful Exploit or Attempt

Detecting exploit attempts or actual crashes involves watching logs and service behavior very closely.

App Logs

Watch your application logs for:

  • Python RecursionError tracebacks
  • Stack frames pointing into protobuf JSON parsing modules
  • Abnormal error rates or crashes immediately after receiving JSON input

For example, if your service logs contain entries like:

RecursionError: maximum recursion depth exceeded
  at google.protobuf.json_format
  at _ConvertAnyMessage

that’s a clear sign someone fed deeply nested Any containers to your endpoint.

Service Behavior

  • Worker processes restarting frequently
  • Sudden rise in 5xx responses from JSON intake endpoints
  • Timeouts on endpoints immediately after receiving large JSON bodies

How to Detect Exploit Attempts

You can use several detection techniques depending on your logging and infrastructure stack.

Log Monitoring

Install alerts that look for:

  • RecursionErrors containing protobuf parser references
  • Exception messages where parsing fails with stack frames pointing to JSON parsing logic

Request Inspection

Count how many times "@type":"type.googleapis.com/google.protobuf.Any" shows up in incoming JSON. A normal JSON request usually has one or two such entries. Attack attempts carry dozens or hundreds.

For example:

  • Alert if occurrence count of any @type mention > 10 within a single request body
  • Reject requests where JSON nesting depth exceeds conservative thresholds

WAF / API Gateway Rules

If you have a Web Application Firewall or API gateway:

  • Set rules to reject JSON with excessive nesting
  • Set safeguards for deeply nested containers of similar types
  • Optionally, drop any untrusted JSON that contains repeated Any containers

Detection Signatures You Can Use

Whether you use SIEM, ELK, Splunk, or another system, here are simple detection examples:

Error Log Pattern

Capture any Python exception with:

  • RecursionError
  • google.protobuf.json_format
  • _ConvertAnyMessage

This combination strongly signals an exploit attempt using deep nesting.

JSON Content Monitoring

Inspect request bodies for repeated patterns:

"@type":"type.googleapis.com/google.protobuf.Any"

If a single payload contains that more than N times (you define N), flag it.


How to Fix It

This vulnerability is not something you can reliably guard against by just filtering inputs — the underlying library itself must be fixed.

Google’s protobuf project has already addressed this by fixing the code path so that nested Any parsing correctly increments and checks the recursion depth counter.

You should:

  1. Upgrade the Python protobuf package to a version that includes the patch
    → Official patch/upgrade: https://github.com/protocolbuffers/protobuf/pull/25239
  2. Rebuild and redeploy services that depend on google.protobuf after the upgrade
  3. Test JSON intake paths after the upgrade to confirm they no longer crash when faced with deeply nested Any types

Short-Term Mitigations

If you can’t immediately upgrade:

  • Add strict input validation at the edge (API gateway, firewall)
  • Reject payloads with excessive nesting or repeated Any markers
  • Limit execution time or CPU usage for JSON parsing functions
  • Catch and handle RecursionError cleanly so workers don’t crash

These don’t fix the vulnerability, but they reduce the risk of service outage.


Final Takeaway

CVE-2026-0994 lets attackers crash or disrupt Python services that use protobuf JSON parsing because Any containers didn’t count against the recursion limit. Attackers exploit this by sending many nested Any messages. You’ll see Python recursion errors in logs and service instability. To fix this correctly, you must upgrade to the protobuf release that includes the official patch linked above. In the meantime, use strong input filtering and log-based detection to catch and block malicious payloads.


Aegiron

Backed by 11+ years in cybersecurity and incident response, we decode the latest threats shaping today’s digital battlefield. This blog cuts through the noise with clear insights on vulnerabilities, emerging exploits, and the cyber news defenders can’t afford to miss.