CVE-2026-24810

RethinkDB cJSON Heap Overflow: When "Measure Twice, Cut Once" Goes Horribly Wrong

Amit Schendel
Amit Schendel
Senior Security Researcher

Jan 28, 2026·7 min read·4 visits

Executive Summary (TL;DR)

RethinkDB's internal JSON parser has a critical RCE flaw. A specific Unicode escape sequence can trick the parser into writing past its allocated buffer. CVSS 10.0.

A critical heap-based buffer overflow in RethinkDB's cJSON parsing logic allows remote attackers to execute arbitrary code. The vulnerability stems from a discrepancy between the memory allocation pass and the string copying pass within the `parse_string` function. By supplying a malformed JSON string with a truncated Unicode escape sequence, an attacker can trick the parser into jumping over the terminating quote, causing it to copy heap data into a finite buffer indefinitely.

The Hook: The Database That Forgot How to Read

RethinkDB pitched itself as the open-source database for the real-time web, a MongoDB killer that pushed JSON to your clients faster than you could say "eventual consistency." But as it turns out, in its haste to process your documents, it forgot one of the cardinal rules of C programming: if you're going to manually manage memory, you better be damn sure your math is perfect.

At the heart of this catastrophe is cJSON, a lightweight C library used for—you guessed it—parsing JSON. It's fast, it's simple, and in this specific implementation, it's fatally flawed. We aren't looking at a complex logic bug buried deep in the replication protocol. We are looking at a classic, 1990s-style heap corruption triggered by a string that looks a bit weird.

CVE-2026-24810 isn't just a Denial of Service (though it does that beautifully). It's a full-blown Remote Code Execution (RCE) vector because the overflow happens on the heap, adjacent to function pointers and vtables that, when clobbered, hand over the keys to the kingdom. It is a stark reminder that even modern databases are often just one while loop away from disaster.

The Flaw: The Two-Pass Treachery

To understand why this breaks, you have to understand how cJSON handles strings. It uses a "Two-Pass" approach. In C, you can't just resize arrays on the fly efficiently, so the code does this:

  1. Pass 1 (The Surveyor): Walk through the input string, counting characters to figure out exactly how much memory is needed.
  2. Allocation: malloc(length + 1) based on that count.
  3. Pass 2 (The Carpenter): Walk through the input string again, decoding escape sequences (like \n or \u0041) and writing the final bytes into the new memory.

The vulnerability is a desynchronization between the Surveyor and the Carpenter. The Surveyor assumes valid input. The Carpenter, however, gets confident. When processing a Unicode escape sequence (e.g., \uXXXX), the code manually advances the input pointer by 4 bytes to skip the hex digits.

Here is the punchline: The code never checked if those 4 bytes actually existed before advancing. If you end your string with "\u" (and no hex digits), the pointer addition jumps over the closing quote of the string. The loop condition while (*ptr != '"') never sees the end of the string because we just vaulted right past it. The parser blindly continues into adjacent heap memory, treating whatever garbage it finds as part of the string, and writing it into a buffer that is now far too small.

The Code: Anatomy of a Heap Smash

Let's look at the smoking gun in src/cjson/cJSON.cc. This is a textbook example of why pointer arithmetic is dangerous.

The Vulnerable Logic:

// Pass 2: The Loop
while (*ptr != '\"' && *ptr) {
    if (*ptr != '\\') {
        *ptr2++ = *ptr++;
    } else {
        ptr++; // Skip the backslash
        switch (*ptr) {
            // ... other cases ...
            case 'u': 
                // DANGER ZONE
                uc = parse_hex4(ptr+1);
                ptr += 4; // <--- The Blind Jump
                // ... encoding logic ...
                break;
        }
    }
}

See that ptr += 4? It assumes there are 4 characters to skip. If the input is "fail\u", the pointer is currently at u. ptr += 4 pushes it past the closing quote. The loop continues, reading memory until it randomly hits a quote character or crashes.

The Fix (PR #7163): The developers had to introduce a hard stop. They calculated end_ptr during the first pass and forced the second pass to respect it.

// The patched loop condition
while (ptr < end_ptr) { // <--- strict boundary check
    // ...
    case 'u':
        uc = parse_hex4(ptr+1);
        ptr += 4;
        
        // The Safety Net
        if (ptr >= end_ptr) {
            return 0; // Bail out if we jumped too far
        }
        break;
}

This simple check prevents the pointer from running off into the sunset (and your heap metadata).

The Exploit: Jumping the Fence

Exploiting this requires finesse. We aren't just crashing the server; we want to control it. The goal is to groom the heap so that interesting objects lie immediately after our malicious string.

The Attack Chain:

  1. Heap Feng Shui: Send multiple small requests to fragment the heap, then allocate a large block followed by our target object (e.g., a connection handler with a vtable pointer).
  2. The Payload: Send a JSON document containing the poison pill: {"hax": "AAAAAAAA\u"}. Note the trailing \u without digits.
  3. The Trigger:
    • The parser sees the \u.
    • It advances ptr by 4 bytes, skipping the closing " and landing in the next chunk of memory.
    • It continues copying "data" from the next chunk into our current string buffer.
  4. The Overwrite: Since the allocation size was calculated based on the original string length, the buffer is small. As the parser keeps copying extra data from the heap, it overflows the write buffer (ptr2).

By carefully crafting the data that lies after the quote (in the next chunk), or simply letting the copy run until it hits a naturally occurring quote, we overwrite the metadata of the next allocated object. When RethinkDB tries to use that object (e.g., calling a virtual destructor), it jumps to an address we control. Game over.

The Impact: Why You Should Panic

This is a CVSS 10.0 for a reason. RethinkDB is often exposed to internal microservices or, God forbid, the public internet (don't do that).

Availability (DoS): Trivial. Sending a single malformed packet crashes the server instantly due to a segmentation fault when the reader hits unmapped memory.

Integrity & Confidentiality (RCE): High. A skilled attacker can turn this memory corruption into arbitrary code execution. Once inside, they have full access to the data stored in the DB, can modify records, or pivot to the underlying OS. Since the database often runs with significant privileges to manage files and network sockets, the blast radius is the entire server.

This affects all versions up to v2.4.4. If you are running an older RethinkDB instance, you are sitting on a powder keg.

The Fix: Patch or Perish

If you are running RethinkDB, stop reading and check your version. If it is 2.4.4 or older, you are vulnerable.

Remediation Steps:

  1. Upgrade Immediately: The fix is merged in Pull Request #7163. Build from source or grab the latest release that includes this patch.
  2. Network Segmentation: Why is your database port (28015) exposed to untrusted networks? Firewall that thing. Only trusted application servers should be able to talk to RethinkDB.
  3. WAF / IDS: While not a perfect fix, you can configure Snort or a WAF to drop JSON payloads ending in a naked backslash or truncated unicode escape (\u at the end of a string).

This vulnerability is a harsh lesson in legacy C code maintenance. Always validate your boundaries, especially when your loop involves pointer arithmetic.

Technical Appendix

CVSS Score
10.0/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/S:N/AU:Y/R:U/V:C/RE:M/U:Red
EPSS Probability
0.04%
Top 87% most exploited

Affected Systems

RethinkDB Server

Affected Versions Detail

Product
Affected Versions
Fixed Version
RethinkDB
RethinkDB
<= 2.4.4Post-v2.4.4 (See PR #7163)
AttributeDetail
CWECWE-120 (Buffer Copy without Checking Size of Input)
CVSS v4.010.0 (Critical)
Attack VectorNetwork (Remote)
ImpactRemote Code Execution (RCE) / Denial of Service
Affected Componentsrc/cjson/cJSON.cc (parse_string)
Exploit StatusProof of Concept likely achievable
CWE-120
Classic Buffer Overflow

Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')

Vulnerability Timeline

CVE Published to NVD
2026-01-27
PR #7163 Submitted to fix vulnerability
2026-01-27

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.