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-54696

CVE-2026-54696: Heap-based Buffer Overflow in Ruby json Gem Native C Extension

Alon Barad
Alon Barad
Software Engineer

Jul 23, 2026·6 min read·3 visits

Executive Summary (TL;DR)

A dynamic buffer capacity calculation error in the Ruby json gem's C extension allows attackers to trigger a heap-based buffer overflow and crash the application by sending strings close to 16 KB during IO-based streaming serialization.

A heap-based buffer overflow vulnerability exists in the native C extension of the Ruby json gem (versions 2.9.0 through 2.19.8) during IO-based streaming serialization. An incorrect buffer size calculation can lead to memory corruption and process termination when processing large strings.

Vulnerability Overview

The Ruby json gem relies on a native C extension for performance-critical serialization operations. Within this extension, the library manages memory through a custom dynamic buffer structure named FBuffer. This structure is designed to aggregate small chunks of serialized JSON output before writing them to an IO stream, minimizing system call overhead during serialization tasks.

This dynamic buffering process exposes an attack surface when applications stream untrusted input or serialize database fields containing user-provided strings. The vulnerability manifests when the serialized payload contains a string element close to the internal buffer's threshold, specifically near 16 KB.

The underlying flaw is a heap-based buffer overflow (CWE-122) arising from a size calculation failure (CWE-131). When triggered, the vulnerability results in memory corruption within the application heap. Under standard runtime conditions, this corruption causes immediate process termination, leading to a Denial of Service.

Root Cause Analysis

The technical root cause of CVE-2026-54696 lies within the capacity management logic defined in ext/json/ext/fbuffer/fbuffer.h. Specifically, the function fbuffer_do_inc_capa(FBuffer *fb, size_t requested) ensures that the buffer has sufficient space to hold an upcoming write of size requested. When writing to an IO destination, the generator flushes the existing buffer when its capacity exceeds FBUFFER_IO_BUFFER_SIZE (16 KB) and resets the length.

The logical error occurs during the validation check executed immediately after checking the IO stream status. The vulnerable code executes a conditional comparison: if (RB_LIKELY(requested < fb->capa)) { return; }. This statement assumes that if the incoming request size is smaller than the total capacity of the buffer, the data will fit safely within the remaining buffer limits.

This assumption is flawed because it ignores the current utilization of the buffer, represented by fb->len. If the buffer already contains serialized data (fb->len > 0), the actual available capacity is the total capacity minus the written length (fb->capa - fb->len). If the requested write size is smaller than fb->capa but larger than the remaining free space, the function returns prematurely without expanding the buffer or flushing the existing data.

Code Analysis

The vulnerability can be traced by analyzing the vulnerable implementation of the dynamic capacity adjustment function. Below is the vulnerable code segment:

static void fbuffer_do_inc_capa(FBuffer *fb, size_t requested)
{
    if (RB_UNLIKELY(fb->io)) {
        if (fb->capa < FBUFFER_IO_BUFFER_SIZE) {
            fbuffer_realloc(fb, FBUFFER_IO_BUFFER_SIZE);
        } else {
            fbuffer_flush(fb);
        }
 
        // VULNERABLE CHECK: Only compares requested size against total capacity
        // Ignores the remaining space available (fb->capa - fb->len)
        if (RB_LIKELY(requested < fb->capa)) {
            return; 
        }
    }
    // ... standard resizing code ...
}

The remediation commit (996bac686d64e4e3aaeae03b14a7f9ee9695ebdb) refactors this logic to ensure that memory is flushed cleanly and capacity calculations are robust. The patched version operates as follows:

static void fbuffer_do_inc_capa(FBuffer *fb, size_t requested)
{
    if (RB_UNLIKELY(fb->io)) {
        if (fb->capa != 0) {
            fbuffer_flush(fb); // Unconditionally flush existing buffer contents
            if (RB_LIKELY(requested < fb->capa)) {
                return; // Safe because fb->len is now guaranteed to be 0
            }
        }
    }
 
    size_t new_capa = fb->capa ? fb->capa : fb->initial_length;
    size_t needed_capa = requested + fb->len; // Correctly includes existing length
 
    while (new_capa < needed_capa) {
        new_capa *= 2;
    }
 
    fbuffer_realloc(fb, new_capa);
}

By ensuring that fbuffer_flush is executed and sets fb->len to 0, the check requested < fb->capa becomes safe. Additionally, the subsequent logic calculates needed_capa using the sum of the requested size and the current length, preventing sizing omissions during non-IO operations.

Exploitation Methodology

Exploitation of CVE-2026-54696 requires specific operational prerequisites. The target application must serialize data directly to an IO object, such as a file descriptor, network socket, or StringIO wrapper, using the native C extension engine. This pattern is commonly implemented via JSON.dump(obj, io) or when setting up custom generator states with stream destinations.

The attacker must supply a payload string that is processed and serialized by the application. To trigger the vulnerability, the payload must contain a string element designed to match the boundary state of the dynamic buffer. Specifically, the string must be large enough to trigger the capacity calculation mismatch (near 16 KB) without triggering an automatic flush via alternative logic blocks.

When the serialization engine invokes the flawed check, the capacity validation logic returns without resizing the heap allocation. The subsequent copy instruction executes a MEMCPY operation that writes beyond the bounds of the allocated buffer. This action corrupts adjacent heap metadata, typically causing the interpreter process to abort immediately.

Impact Assessment

The primary security impact of this vulnerability is a Denial of Service (DoS) condition. Because the memory corruption occurs on the heap, the Ruby interpreter's internal state becomes unstable, leading to an immediate crash. In web applications or background workers processing queue messages, repeated exploit attempts can result in a complete disruption of service availability.

The CVSS v3.1 base score is 3.7 (Low Severity), reflecting the high complexity of the attack vector and the restricted impact. The vector string is CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L. This indicates that while the vulnerability can be reached remotely without authentication, triggering the precise memory layout conditions requires specific configurations and execution paths.

At present, there are no weaponized public exploits or documented instances of active exploitation in the wild. The vulnerability does not appear in the CISA Known Exploited Vulnerabilities (KEV) catalog, and its Exploit Prediction Scoring System (EPSS) score remains low at 0.00301 (22.29th percentile), indicating a low probability of imminent widespread exploitation.

Detection and Remediation Guidance

The definitive mitigation is upgrading the json gem to version 2.19.9 or higher. This release integrates the corrected capacity check implementation and enforces clean buffer flushes. Systems relying on vendored Ruby gems or pre-packaged distribution libraries should verify their package configurations to ensure the patched versions are utilized.

When immediate patching of the native extension is not feasible due to environment constraints, applications can apply a temporary code-level workaround. By serializing the target object entirely in memory before writing it to the IO destination, developers can bypass the vulnerable streaming code path.

# Vulnerable dynamic streaming pattern
JSON.dump(user_data, io_stream)
 
# Temporary mitigated pattern (bypasses dynamic streaming buffer)
serialized_json = JSON.fast_generate(user_data)
io_stream.write(serialized_json)

This workaround shifts the serialization burden to the standard Ruby virtual machine heap allocation, which does not utilize the vulnerable FBuffer IO-stream capacity management code. However, this may result in elevated transient memory utilization for very large objects.

Fix Analysis (1)

Technical Appendix

CVSS Score
3.7/ 10
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L
EPSS Probability
0.30%
Top 78% most exploited

Affected Systems

Ruby application environments running json gem version 2.9.0 up to 2.19.8Operating system packages hosting pre-packaged native Ruby JSON libraries within the affected version ranges

Affected Versions Detail

Product
Affected Versions
Fixed Version
json gem
Ruby
>= 2.9.0, <= 2.19.82.19.9
AttributeDetail
CWE IDCWE-122
Attack VectorNetwork (AV:N)
CVSS v3.1 Score3.7
EPSS Score0.00301 (22.29th percentile)
ImpactLow (Denial of Service via process crash)
Exploit StatusNone
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1203Exploitation for Client Execution
Execution
T1068Exploitation for Privilege Escalation
Privilege Escalation
CWE-122
Heap-based Buffer Overflow

A heap-based buffer overflow condition is a buffer overflow where the buffer that can be overwritten is allocated in the heap portion of memory, which generally means that the buffer was allocated using a function such as malloc().

Vulnerability Timeline

CVE Published
2026-06-30
NVD Metadata Updated
2026-07-02

References & Sources

  • [1]Official GitHub Release
  • [2]GitHub Security Advisory (GHSA)
  • [3]Fix Commit (GitHub)
  • [4]CVE.org Record
  • [5]NVD Detail

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 2 hours ago•CVE-2026-59938
5.3

CVE-2026-59938: Uncontrolled Memory Allocation (DoS) in pypdf Image Parsing

An uncontrolled memory allocation vulnerability (CWE-789) exists in pypdf prior to version 6.14.0. The library blindly trusted user-controlled image dimensions (/Width and /Height) from PDF metadata, allowing attackers to trigger physical memory exhaustion and an Out-of-Memory crash via tiny, malformed files.

Amit Schendel
Amit Schendel
1 views•8 min read
•about 3 hours ago•CVE-2026-59936
8.7

CVE-2026-59936: Infinite Loop in pypdf Inline Image Parser Leads to Denial of Service

An infinite loop vulnerability exists in the pure-python PDF library pypdf prior to version 6.14.1. This vulnerability occurs during the processing of malformed or truncated page content streams containing inline images. Specifically, the parser fails to validate the End-of-Stream condition during inline image dictionary parsing. This results in continuous backward stream-seeking and an infinite loop that consumes 100% CPU on the processing thread.

Alon Barad
Alon Barad
4 views•6 min read
•about 4 hours ago•CVE-2026-59935
8.7

CVE-2026-59935: Infinite Loop Denial of Service in pypdf via Malformed Inline Images

An infinite loop vulnerability exists in the pypdf library prior to version 6.14.2 when processing malformed PDF inline images that utilize ASCII85 or ASCIIHex decoders. Attackers can exploit this vulnerability by submitting crafted PDF files containing incomplete streams, causing the parsing thread to consume 100% CPU resource indefinitely and leading to Denial of Service.

Amit Schendel
Amit Schendel
4 views•7 min read
•about 5 hours ago•CVE-2026-59937
7.5

CVE-2026-59937: CPU Exhaustion via Quadratic-Time Cross-Reference Recovery Loop in pypdf

A critical CPU exhaustion vulnerability exists in the pypdf library before version 6.14.0. When parsing PDF files with malformed or corrupt standard cross-reference (xref) table entries, the library falls back to sequentially scanning the entire file buffer via regular expression search. An attacker can exploit this algorithmic bottleneck by supplying a crafted PDF with numerous malformed xref entries, leading to denial of service.

Alon Barad
Alon Barad
4 views•4 min read
•about 6 hours ago•GHSA-8FPG-XM3F-6CX3
7.4

GHSA-8FPG-XM3F-6CX3: Authentication Fail-Open via Unvalidated Server Responses in Auth.js

In Auth.js (specifically next-auth version 5), server-side configuration errors or backend exceptions can cause existence-based authentication and authorization checks to fail open. When the underlying core engine (@auth/core) encounters a configuration error or runtime exception, it returns an HTTP 500 Internal Server Error response containing a JSON-formatted error description payload. Prior to the fix, the next-auth wrappers read this response body using response.json() without validating the HTTP status code. Because any parsed JavaScript object evaluates to truthy, common existence-based checks incorrectly evaluated to true, letting unauthenticated requests pass.

Alon Barad
Alon Barad
4 views•7 min read
•about 8 hours ago•CVE-2026-6790
5.3

CVE-2026-6790: Host/Authority Header Desynchronization in Eclipse Jetty

A host/authority desynchronization vulnerability exists in Eclipse Jetty's handling of HTTP/2 and HTTP/3 requests. When both an ':authority' pseudo-header and a standard 'Host' header are present in a request, Jetty fails to validate that they represent the same target host. This desynchronization creates a host-confusion or 'split-brain' state, enabling attackers to bypass access control lists, escape virtual host isolation, poison web caches, or manipulate redirect targets in backend applications.

Amit Schendel
Amit Schendel
5 views•5 min read