Listen to this Post
The Oj gem for Ruby provides a fast JSON parser and serializer. A vulnerability was discovered in how `Oj.load` handles JSON parsing when the `:object` mode is used. The flaw resides in the `form_attr()` function within the `ext/oj/intern.c` file.
When parsing a JSON object with a key that is 254 bytes or longer, the code allocates a heap buffer `b` to hold the long key. However, due to a programming error, it passes the uninitialized stack buffer `buf` (which is only 256 bytes) to the `rb_intern3()` function, instead of the correctly populated heap buffer b. Consequently, `rb_intern3` reads uninitialized stack memory. For keys longer than 256 bytes, this read extends past the bounds of the `buf` array, resulting in an out-of-bounds read (CWE-125).
The bytes read from this uninitialized or out-of-bounds memory are then interned and can be returned to the caller. This leak can manifest either through the produced Symbol object or within the error message of an `EncodingError` that is raised when the invalid UTF-8 data is processed. A Proof of Concept using a key of 300 “A” characters triggers this issue, raising an `EncodingError` whose message contains approximately 1500 bytes of stack memory, with the exact length varying between runs (e.g., 1491 vs 1516 bytes), confirming the data is from uninitialized memory.
This defect is a duplicate of a previously fixed issue in ext/oj/usual.c, but the `intern.c` file held a copy of the vulnerable code that was missed during the initial patch. The issue was reported by Zac Wang (@7a6163) and is fixed in Oj version 3.17.3.
DailyCVE Form
Platform: ……. Oj (Ruby gem)
Version: …….. < 3.17.3
Vulnerability :.. Uninitialized memory read / OOB read
Severity: ……. Medium (CVSS 5.3)
Date: ……….. 2026-06-19 (Disclosure/Patch)
Prediction: ….. Patched (3.17.3)
What Undercode Say
Analytics:
The vulnerability is triggered specifically when using `Oj.load` in `:object` mode with a JSON key of 254 bytes or more. The following bash command and Ruby script demonstrate how an attacker can reproduce the memory leak.
Bash Command to test:
ruby -e "require 'oj'; key = 'A' 300; json = %Q[{\"^o\":\"Object\",\"{key}\":1}]; Oj.load(json, mode: :object) rescue puts $!.message"
Vulnerable Code Snippet (ext/oj/intern.c):
static VALUE form_attr(const char str, size_t len) {
char buf[bash];
if (sizeof(buf) - 2 <= len) { // long-key path (len >= 254)
char b = OJ_R_ALLOC_N(char, len + 2);
// ... b is filled correctly ...
id = rb_intern3(buf, len + 1, oj_utf8_encoding); // BUG: reads `buf`
OJ_R_FREE(b);
return id;
}
// ...
}
Exploit:
An attacker can exploit this vulnerability by providing a crafted JSON payload to an application that uses the vulnerable version of the Oj gem with `:object` mode. The exploit is triggered when the application parses untrusted JSON containing a key that is 254 bytes or longer.
1. Craft Payload: The attacker creates a JSON object with a long key (e.g., 300 “A” characters).
2. Trigger Vulnerability: The application parses this JSON using Oj.load(json, mode: :object).
3. Memory Leak: The `form_attr()` function mishandles the long key, causing `rb_intern3` to read from uninitialized stack memory.
4. Information Disclosure: The uninitialized data is either returned as a Symbol or included in the `EncodingError` message, which is then potentially returned to the attacker, leaking sensitive process stack memory.
Protection:
- Upgrade Oj: The most effective protection is to upgrade to Oj version 3.17.3 or later, which contains the fix.
- Avoid `:object` Mode: Do not use `Oj.load` with the `:object` mode for untrusted input, as it is already discouraged due to its deserialization risks.
- Use Safe Methods: Prefer using `Oj.safe_load()` which uses the most strict and safest options.
Impact
- Information Disclosure: Successful exploitation can lead to the disclosure of process stack memory, which may contain sensitive information such as:
- Environment variables
- File paths
- Partial source code
- Other application data resident in memory
- Out-of-Bounds Read (CWE-125): For keys of 256 bytes or longer, the vulnerability also causes an out-of-bounds read, which could lead to a crash or further memory corruption.
- CVSS Score: The severity is rated as Medium (CVSS 5.3) due to several preconditions: it requires `:object` mode (discouraged for untrusted input), the leaked bytes are uncontrolled, and the data only reaches an attacker if the application surfaces the resulting Symbol or `EncodingError` back to them.
🎯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

