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·42 visits

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 4 hours ago•CVE-2026-128087
3.7

CVE-2026-128087: Premature Key Exchange Callback Invocation Prior to Host Key Verification in russh

CVE-2026-128087 (GHSA-9264-jvgf-6w2f) is an incorrect behavior order (CWE-696) and improper authorization (CWE-863) vulnerability in the russh Rust SSH library, affecting versions 0.55.0 through 0.65.0. During the initial SSH key exchange (KEX) handshake, the client state machine invokes the client::Handler::kex_done() callback—providing the negotiated raw shared secret bytes—prior to validating the remote server's host key or certificate via check_server_key(). Consequently, an untrusted or rogue SSH server can complete cryptographic key agreement and force a connecting client to execute side-effecting application logic inside kex_done() before the server's identity is checked and rejected.

Amit Schendel
Amit Schendel
4 views•10 min read
•about 5 hours ago•CVE-2026-128082
7.5

CVE-2026-128082: Uncontrolled Recursion and Denial of Service in AutoMapper via Constructor Parameter Mapping

CVE-2026-128082 (GHSA-6vhm-j9h7-f9gh) is an uncontrolled recursion vulnerability (CWE-674) in AutoMapper, a convention-based object-object mapper for .NET. When mapping nested or self-referential types into destination models that rely on parameterized constructors, C# positional records, or recursive ConstructUsing expressions, AutoMapper evaluates child constructor arguments prior to incrementing the parent's recursion depth counter. This ordering flaw bypasses both explicit MaxDepth limits and the default depth limit of 64. An unauthenticated remote attacker can supply deeply nested input payloads to affected endpoints, exhausting the thread call stack and triggering an uncatchable System.StackOverflowException that terminates the hosting .NET process.

Amit Schendel
Amit Schendel
6 views•11 min read
•about 6 hours ago•CVE-2026-128080
5.8

CVE-2026-128080: Sensitive Query Parameter Disclosure on Incoming Server Spans in OpenTelemetry JavaScript (@opentelemetry/instrumentation-http)

An information exposure vulnerability in the @opentelemetry/instrumentation-http package for OpenTelemetry JavaScript versions 0.204.0 prior to 0.222.0 causes incoming HTTP server spans to record raw, unredacted query string parameters under the url.query attribute. While outgoing client spans applied built-in and user-configured query parameter redaction, incoming server spans bypassed this sanitization completely, resulting in the transmission of sensitive credentials such as pre-signed cloud URLs and API tokens to external observability backends.

Alon Barad
Alon Barad
5 views•10 min read
•about 7 hours ago•CVE-2026-128089
7.5

CVE-2026-128089: Uncontrolled Resource Consumption in dnspython WKS Record Parser

CVE-2026-128089 is an uncontrolled resource consumption vulnerability in the dnspython toolkit for Python, affecting all versions prior to 2.9.2. When parsing Well-Known Service (WKS) records from text via dns.rdtypes.IN.WKS.WKS.from_text(), the parser fails to validate that numeric service port identifiers fall within the RFC 1035 valid range of 0 through 65535. An attacker capable of supplying untrusted zone files or RDATA text strings containing an arbitrarily large service port integer can force the parser to allocate an unbounded bitmap array using an inefficient linear append loop, resulting in severe CPU exhaustion, application hangs, or Out-Of-Memory (OOM) process termination.

Amit Schendel
Amit Schendel
5 views•10 min read
•about 8 hours ago•CVE-2026-126347
3.1

CVE-2026-126347: Open Redirect via Triple-Slash Redirect Paths in Tornado RedirectHandler

CVE-2026-126347 (GHSA-5cjw-f85j-cv6r) is an open redirect vulnerability (CWE-601) in Tornado, an asynchronous Python networking library and web framework. The flaw resides in tornado.web.RedirectHandler when dynamic URL redirection templates incorporate unvalidated user input. Due to a parser differential between RFC 3986 (used by Python's urllib.parse.urlsplit) and the WHATWG URL Standard (used by modern web browsers), inputs containing three or more leading slashes bypass Tornado 6.6.0's validation logic, allowing unauthenticated attackers to redirect users to arbitrary external domains.

Alon Barad
Alon Barad
6 views•11 min read
•about 9 hours ago•CVE-2026-128123
5.9

CVE-2026-128123: Uncaught Exception and Denial of Service in SvelteKit @sveltejs/adapter-node

A Denial of Service (DoS) vulnerability exists in @sveltejs/adapter-node versions 5.5.7 and 6.0.0-next.0 through 6.0.0. When a SvelteKit server route returns a direct response from a fetch() call with a Content-Type of text/event-stream, the Node.js adapter attempts to mutate the response headers to disable proxy buffering. Because headers returned directly by the WHATWG Fetch API carry an immutable guard, this mutation throws an unhandled TypeError, terminating the underlying Node.js process and denying service to all active and subsequent clients.

Alon Barad
Alon Barad
5 views•9 min read