Oj::Doc, Stack Buffer Overflow, CVE-2026-XXXXX (High Severity) -DC-Jun2026-509

Listen to this Post

The Oj gem for Ruby is a widely used, high-performance JSON parser and serializer. A critical vulnerability has been discovered in the `Oj::Doceach_child` method, which allows for a reliable Denial of Service (DoS) attack. An attacker can exploit this flaw by providing a specially crafted, deeply nested JSON document to any endpoint that processes untrusted JSON using the `Oj::Doc.open` method in conjunction with a recursive call to each_child.
The root cause of this vulnerability is a two-step chain of errors within the `ext/oj/fast.c` file, specifically in the `doc_each_child` function. First, the function increments a `doc->where` pointer past the end of a fixed-size `where_path` array (MAX_STACK = 100) without performing any bounds checking. Furthermore, it fails to decrement this pointer (doc->where-- is missing), meaning that a recursive call from within the yield block will continuously drive the `doc->where` pointer beyond the allocated array.
On a subsequent entry to the function, it copies the current path into a stack-local buffer, Leaf save_path

</code>. The size of the copy is calculated based on the `doc->where` pointer. When the previous recursive call has pushed `doc->where` past the `where_path[bash]` array, this calculated length (<code>wlen</code>) exceeds <code>MAX_STACK</code>. This leads to a `memcpy` operation that overflows the `save_path` buffer on the C stack.
The `Oj::Doc` parser does not impose a limit on JSON nesting depth; it relies on a C-stack pressure check which is insufficient to prevent this overflow. Consequently, a deeply nested attacker-controlled input can reach this vulnerable code path. On builds with stack protection enabled (the default, <code>-fstack-protector-strong</code>), the stack canary detects the corruption and aborts the process, resulting in a denial of service. The initial heap out-of-bounds write that occurs before the stack overflow is masked by the subsequent crash, and no other impact has been demonstrated.
The issue was reported by Zac Wang (@7a6163) and is fixed in version 3.17.3. The fix introduces a bounds check before incrementing `doc->where` and properly restores the pointer after the loop, raising a clean `Oj::DepthError` instead of aborting.

<h2 style="color: blue;">DailyCVE Form</h2>

Platform: .......

<h2 style="color: blue;">Oj gem for Ruby</h2>

Version: ........

<h2 style="color: blue;">< 3.17.3</h2>

Vulnerability :......

<h2 style="color: blue;">Stack Buffer Overflow</h2>

Severity: .......

<h2 style="color: blue;">High (DoS)</h2>

date: ..........

<h2 style="color: blue;">2026</h2>

<h2 style="color: blue;">Prediction: .......</h2>

<h2 style="color: blue;">2026-06-26</h2>

<h2 style="color: blue;">What Undercode Say</h2>

The vulnerability analysis reveals a classic case of improper bounds checking in a C extension. The `doc_each_child` function fails to validate the `doc->where` index before incrementing it, leading to a stack buffer overflow. The following technical details are critical for understanding and reproducing the issue.

<h2 style="color: blue;">Vulnerable Code Snippet (ext/oj/fast.c):</h2>

[bash]
define MAX_STACK 100
// ...
Leaf save_path[bash]; // 800-byte stack buffer
size_t wlen = doc->where - doc->where_path;
if (0 < wlen) {
memcpy(save_path, doc->where_path, sizeof(Leaf) (wlen + 1));
}

Proof of Concept (PoC):

require 'oj'
depth = 200
payload = '[' depth + '1' + ']' depth
Oj::Doc.open(payload) do |doc|
r = lambda { doc.each_child { |_| r.call } }
r.call
end

This script will cause an abort on vulnerable versions (depth >= 101), while a fixed version will raise Oj::DepthError.

Exploit

An attacker can reliably trigger a Denial of Service (DoS) by sending a JSON payload with a nesting depth of 101 or greater to any application endpoint that uses the vulnerable pattern. The exploit is trivial to execute and requires no special privileges.
1. Craft Payload: Create a JSON string with a nesting depth of at least 101. For example, a string like '[' 101 + '1' + ']' 101.
2. Deliver Payload: Submit this payload to a vulnerable endpoint that processes JSON with `Oj::Doc.open` and recursively iterates over it using each_child.
3. Trigger Crash: The application will process the payload, causing a stack buffer overflow. On systems with stack protection, this will immediately abort the process, leading to a denial of service.

Example of a vulnerable code pattern:

def process_json(json_string)
Oj::Doc.open(json_string) do |doc|
recursive_process(doc)
end
end
def recursive_process(doc)
doc.each_child { |child| recursive_process(child) }
end

Protection

Detection

  • Version Check: The primary method of detection is to check the version of the `oj` gem in use.
    gem list oj
    

Versions prior to `3.17.3` are vulnerable.

Mitigation

  • Immediate Upgrade: The most effective protection is to upgrade the `oj` gem to version `3.17.3` or later.
    gem update oj
    
  • Input Validation: As a temporary workaround, implement input validation to reject JSON payloads with an excessive nesting depth before they reach the vulnerable code.
    MAX_NESTING = 100
    def safe_nesting?(json_string)
    depth = 0
    json_string.each_char do |char|
    depth += 1 if char == '['
    depth -= 1 if char == ']'
    return false if depth > MAX_NESTING
    end
    true
    end
    
  • Avoid Recursive Patterns: Refactor code to avoid recursive patterns with `each_child` on untrusted input until the upgrade is applied.

Impact

  • Denial of Service (DoS): The primary and demonstrated impact is a reliable crash of the Ruby process, leading to a denial of service. Any service that processes untrusted JSON with the vulnerable pattern is at risk.
  • Service Disruption: This vulnerability can be exploited to repeatedly crash application instances, making the service unavailable to legitimate users.
  • Potential for Further Exploitation: While not demonstrated, the initial out-of-bounds write into the `struct _doc` fields on the heap could, in theory, be leveraged for more severe impacts, such as information disclosure or remote code execution, under specific and unlikely circumstances. However, the stack overflow reliably crashes the process first, masking this potential.

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top