CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-71847

CVE-2026-71847: Use-After-Free in Ruby JSON Gem ResumableParser

Alon Barad
Alon Barad
Software Engineer

Aug 8, 2026·6 min read·1 visit

Executive Summary (TL;DR)

A Use-After-Free (UAF) bug in the native C extension of the Ruby json gem allows remote attackers to trigger a process crash and denial of service via malformed streaming JSON data with duplicate keys.

A technical analysis of the use-after-free (UAF) vulnerability in the Ruby JSON gem (CVE-2026-71847) that impacts versions 2.20.0 through 2.21.1. This vulnerability occurs when parsing incomplete stream data containing duplicate keys.

Vulnerability Overview

CVE-2026-71847 is a high-severity use-after-free vulnerability identified within the native C extension of the Ruby json gem. The vulnerability resides specifically within the JSON::ResumableParser class, which handles chunk-by-chunk stream parsing. Under conditions involving incomplete stream inputs containing duplicate keys, the parser invokes memory-unsafe operations on deallocated storage.

The vulnerability is categorized under CWE-416 (Use After Free). In multi-threaded or memory-sensitive Ruby environments, dereferencing these stale pointers can lead to memory leakage, immediate process crash via segmentation fault, or potential memory corruption. This compromise directly affects system availability and potentially system integrity.

The issue impacts versions of the json gem starting from 2.20.0 up to, but excluding, 2.21.2. Applications that rely on streaming parsers to handle large, unauthenticated user payloads are particularly exposed. Remediation requires an immediate update to version 2.21.2.

Root Cause Analysis

The root cause of this vulnerability lies in the memory management of the native C extension inside ext/json/ext/parser/parser.c. During the streaming parse cycle, when a chunk of data is completed, the function cResumableParser_parse clears the associated input buffer by calling json_str_clear(parser->buffer). While the buffer's Ruby object reference is updated, the internal parsing state (parser->state) retains dangling pointers.

Specifically, the structure fields state.start, state.cursor, and state.end are not re-initialized to null. These fields continue pointing to the memory address of the newly freed heap allocation. This creates a classic dangling pointer condition where subsequent execution flows can access invalid locations.

The execution path triggers when a consumer calls JSON::ResumableParser#partial_value to extract the current parsing state of an incomplete stream. If the parsed stream contains duplicate object keys, the native parser triggers a warning path via emit_parse_warning to issue a deprecation alert. This warning path invokes cursor_position which reads and dereferences the stale pointer values to calculate the line and column numbers of the duplicate key.

Here is a sequence diagram illustrating the lifecycle of the dangling pointers during resumable parsing:

Code Analysis

To understand the mechanism of the vulnerability, we inspect the vulnerable version of the source code in ext/json/ext/parser/parser.c. In the vulnerable implementation, the clearing of the buffer is done without safety checks or pointer nullification:

// Vulnerable implementation in cResumableParser_parse
if (eos(&parser->state)) {
    json_str_clear(parser->buffer);
    parser->buffer = Qfalse;
    // state.start, state.cursor, and state.end are left pointing to the freed buffer
}

This vulnerability is resolved in commit 2c332bfe2bfb0e754da07e2a0310ef106bf46482 by explicitly nullifying these pointers upon freeing the buffer. The patch also prevents coordinate calculations for warnings when a resumable parser context is active:

// Patched implementation in cResumableParser_parse
if (eos(&parser->state)) {
    json_str_clear(parser->buffer);
    parser->buffer = Qfalse;
    // Nullify dangling pointers to prevent Use-After-Free
    parser->state.start = parser->state.cursor = parser->state.end = 0;
}

Additionally, the patch alters emit_parse_warning to avoid calling cursor_position when the parsing context runs in resumable mode, since tracking absolute positions on incomplete streams is unreliable:

// Patched warning emission path
static void emit_parse_warning(const char *message, JSON_ParserState *state)
{
    VALUE warning;
    if (state->parser) { 
        // Avoid calculation entirely; use plain message to bypass cursor_position
        warning = rb_utf8_str_new_cstr(message);
    } else {
        long line, column;
        cursor_position(state, &line, &column);
        warning = rb_sprintf("%s at line %ld column %ld", message, line, column);
    }
    rb_funcall(mJSON, rb_intern("deprecation_warning"), 1, warning);
}

Exploitation

An attack targeting this vulnerability relies on sending malformed, streaming JSON inputs to an application that processes data using the JSON::ResumableParser class. The payload must satisfy two specific structural properties to trigger the vulnerable path: duplicate object keys and a truncated or incomplete structure.

First, the attacker must initiate a stream with duplicate keys, such as {"key": 1, "key": 2, ...}. The presence of duplicate keys guarantees that the native extension executes the warning generation path. Second, the JSON payload must be cut off prematurely, ensuring that the stream remains incomplete and the application calls #partial_value to recover the partial state.

When the application reads the incomplete stream, it processes the initial chunk, reaches the end of the input segment, and frees the buffer while retaining pointers. The subsequent invocation of #partial_value forces the C extension to attempt pointer arithmetic on these freed segments to calculate line offsets. This attempt results in a read access violation and terminates the executing Ruby worker process.

The following script structure illustrates how a regression payload can be constructed to trigger the vulnerability when sent over a stream:

# Trigger sequence in Ruby test suite
parser = JSON::ResumableParser.new
parser << '{"a":1,"a":2,"pad":"' + ('x' * 4194304)
parser.parse
parser << '",'
parser.parse
parser.partial_value # Dereferences freed pointer in cursor_position

Impact Assessment

The main outcome of successful exploitation is a persistent denial-of-service (DoS) condition. Because the memory dereference happens within a native C library, the Ruby VM cannot catch the resulting segmentation fault through standard exception handlers like rescue. The entire parent process or worker thread terminates immediately.

In multi-threaded web application servers (such as Puma or Passenger), a repeated execution of this payload against the server endpoints will deplete available workers. This leads to a denial of service for legitimate users. If the application environment lacks automatic worker recovery, manual intervention is required to restore the service.

The primary CVSS score for this vulnerability is assessed at 8.7 under the CVSS v4.0 standard. While the impact is primarily centered on system availability (VA:H), vulnerability researchers must recognize that heap-use-after-free vulnerabilities can occasionally be combined with other heap-grooming techniques to achieve remote code execution (RCE) in scenarios where memory allocators do not randomize allocations.

Remediation

Remediation requires upgrading the json gem to version 2.21.2 or higher. The patch fully mitigates the vulnerability by clearing the dangling pointers inside cResumableParser_parse and short-circuiting the warning generation path to bypass the unsafe memory scanner when resumable parsing is active.

For legacy systems that cannot immediately update the gem, a structural workaround involves implementing input validation filters prior to passing stream data to the resumable parser. Specifically, a lightweight Ruby-based filter can check incoming payloads for duplicate key signatures or verify formatting before deep parsing.

Additionally, system administrators should configure containerized runtimes to automatically restart application processes that exit abnormally. Enforcing maximum memory limits per worker process can also prevent heap-grooming activities that facilitate memory exploitation.

Fix Analysis (2)

Technical Appendix

CVSS Score
8.7/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

Affected Systems

Ruby applications utilizing the JSON::ResumableParser class in json gem versions 2.20.0 to 2.21.1.

Affected Versions Detail

Product
Affected Versions
Fixed Version
json (gem)
Ruby
>= 2.20.0, < 2.21.22.21.2
AttributeDetail
CWE IDCWE-416 (Use After Free)
Attack VectorNetwork
CVSS v4.08.7 (High)
Exploit StatusPoC (Proof of Concept)
ImpactDenial of Service (Process Crash)
Affected Gem Versions>= 2.20.0, < 2.21.2

MITRE ATT&CK Mapping

T1203Exploitation for Client Execution
Execution
T1499Endpoint Denial of Service
Impact
CWE-416
Use After Free

The product uses a pointer after it has been freed, which can lead to a crash, unexpected behavior, or execution of arbitrary code.

Known Exploits & Detection

GitHub (Advisory)Includes regression testing details simulating truncated duplicate-key streams in resumable parser.

References & Sources

  • [1]GitHub Security Advisory GHSA-9hj4-r449-hfvc
  • [2]CVE-2026-71847 on CVE.org

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 1 hour ago•CVE-2026-67422
7.5

CVE-2026-67422: Regular Expression Denial of Service in pymdown-extensions

A high-severity Regular Expression Denial of Service (ReDoS) vulnerability in pymdown-extensions versions prior to 11.0.1 affects the Caret, Tilde, BetterEm, and MagicLink inline processors. When parsing user-supplied Markdown content containing malicious sequences of formatting delimiters, the regular expression engine is forced into catastrophic backtracking, resulting in CPU exhaustion and application denial of service.

Alon Barad
Alon Barad
1 views•5 min read
•about 3 hours ago•CVE-2026-71848
5.3

CVE-2026-71848: Algorithmic Complexity Denial of Service in Hono languageDetector Middleware

An Algorithmic Complexity Denial of Service (DoS) vulnerability exists in the Hono web application framework within its languageDetector middleware. From version 4.12.0 to 4.12.33, the progressive language-tag truncation routine (normalizeLanguage) performs string operations with a quadratic time complexity O(N^2) relative to the number of hyphen-separated subtags in the user-supplied language tag. This allows an unauthenticated remote attacker to cause resource exhaustion and CPU spikes, resulting in a full denial of service of the single-threaded JavaScript runtime.

Alon Barad
Alon Barad
3 views•5 min read
•about 4 hours ago•CVE-2026-71849
3.7

CVE-2026-71849: Information Exposure via Hop-by-Hop Header Leakage in Hono Proxy Helper

A vulnerability in the Hono framework's Proxy Helper allows the exposure of connection-scoped, internal, or session-specific metadata to unauthorized actors. The proxy helper fails to remove header fields dynamically listed in the response's Connection header, violating RFC 9110 Section 7.6.1.

Amit Schendel
Amit Schendel
3 views•6 min read
•about 5 hours ago•CVE-2026-71850
4.8

CVE-2026-71850: Server-Side Rendering Data Exposure in Hono JSX Memoization

A session data exposure vulnerability in the Hono web application framework (hono/jsx module) allows consecutive users to receive cached HTML outputs containing private data. When JSX components wrapped in `memo()` are rendered on the server, the caching mechanism utilizes a module-level closure that persists across independent HTTP requests. When subsequent requests occur with matching props, the components are not re-evaluated, and cached HTML is served. If these components read request-scoped or session-specific data via ambient APIs, the data of the first user is exposed to subsequent users.

Amit Schendel
Amit Schendel
3 views•6 min read
•about 6 hours ago•CVE-2026-71851
9.0

CVE-2026-71851: Use of Cryptographically Weak PRNG in crypto-js (Ill Bloom)

A severe, twelve-year-old cryptographic weakness in crypto-js (versions < 4.0.0) generated pseudorandom numbers using a custom Multiply-With-Carry (MWC) algorithm seeded from the non-secure Math.random(). This reduces 128-bit and 256-bit key spaces to just 2^39 and 2^47 possibilities, allowing offline brute-force attacks.

Alon Barad
Alon Barad
5 views•7 min read
•about 7 hours ago•CVE-2026-71870
4.8

CVE-2026-71870: Uncontrolled Resource Consumption (DoS) in pypdf ToUnicode CMap Parsing

An uncontrolled resource consumption vulnerability (CWE-400) exists in pypdf prior to version 6.15.0. When extracting text from a specially crafted PDF document, the parser fails to restrict token lengths within /ToUnicode CMap streams, causing unbounded memory allocation and process termination via Out-of-Memory (OOM) crashes.

Amit Schendel
Amit Schendel
6 views•7 min read