In the realm of Ruby and JSON, yajl-ruby is a popular gem that provides fast JSON parsing and generation by binding C-based YAJL (Yet Another JSON Library). However, a critical vulnerability, CVE-2022-24795, has been identified in both the 1.x and 2.x branches of yajl-ruby. This bug can lead to heap memory corruption when handling very large (~2GB) JSON inputs, potentially causing applications to crash and affecting process availability.

Let’s break down what this vulnerability is, how it happens, and what you need to do about it, with simple explanations and relevant code snippets.

What’s the Cause?

At its core, this issue is an integer overflow that occurs during buffer reallocation in C code. The problem lives in yajl_buf.c, specifically around line 64—the logic that recalculates the buffer size as large JSON inputs are processed.

When parsing or generating huge amounts of JSON data (about 2GB close to x80000000), the code tries to expand its buffer—using a 32-bit integer (need) to track how large it needs to be. But once you go past that 2GB mark, the integer overflows and wraps around to zero, tricking the program into allocating a *very small* chunk of memory instead of the big one it actually needs.

Subsequent code then treats that buffer as if it were still large, writing data past the end and corrupting memory—this is classic heap buffer overflow territory.

Here’s a simplified (and commented) version of what goes wrong in yajl_buf.c

// This is a simplified example
unsigned int new_size = old_size + need; // 'need' becomes huge near 2GB boundary
buf = realloc(buf, new_size);

if (!buf) {
    // Not enough memory
    return -1;
}

// Later code assumes buf is big enough...
memcpy(buf + old_size, incoming_data, need);

When need is large (about 2GB), new_size overflows to a small number, realloc allocates too little, and memcpy then writes way past the newly allocated memory.

Why does this matter?

* On 32-bit systems, size_t (used to declare buffers) is also 32 bits, so you hit this limit right at 2GB. On 64-bit systems, the limit is astronomically high (exabyte scale…), so it won’t happen under normal use.
* With a corrupted heap, your Ruby app or service could crash, resulting in denial of service.
* According to the maintainers, arbitrary code execution exploits are *unlikely*—so this mostly threatens uptime, not data integrity or secrets.

How could someone trigger this?

All an attacker needs to do is feed your Ruby app a huge (~2GB) JSON object—either directly (think: big API POST) or via file upload.

Example: Malicious Exploit Using Ruby

Suppose your server parses user-uploaded JSON. A malicious user could upload a huge JSON array, either by hand or with code like:

# WARNING: Only for demonstration!
File.open("evil.json", "w") do |f|
  f.write("[")
  f.write("," * (536870912)) # creates an array with ~2^30 elements (','1GB, then doubled with two bytes per number)
  f.write("]")
end

# Now, sending this file to a vulnerable server could cause a crash:
require 'yajl'
data = File.read("evil.json")
Yajl::Parser.parse(data)  # Vulnerable call: could crash app or corrupt heap

Most real-world apps won’t ever handle such a giant input, but internet-facing APIs sometimes do, and attackers can craft such JSONs intentionally.

Is Arbitrary Code Execution Possible?

Maintainers believe exploitation for arbitrary code execution is unlikely. Due to the nature of the overflow and how the buffer is used, this is more about making the app crash (denial of service), rather than taking it over.

Still, any heap corruption is a serious bug, and should be fixed.

Affected Versions

* yajl-ruby 1.x: *Vulnerable* (uses 32-bit variables on 32-bit builds)
* yajl-ruby 2.x: Uses size_t which is 64-bit on modern systems, so the problem only exists if built for 32-bit platforms.

Who’s at risk?

* Anyone using yajl-ruby on a 32-bit operating system or in 32-bit Ruby builds.
* 64-bit users are generally not vulnerable in practice.

Patches and Fixes

* The issue is patched as of yajl-ruby 1.4.2.
* Upgrade to yajl-ruby 1.4.2 or later to be safe. If you’re on 2.x, make sure your build target is 64-bit.

While waiting for a patch or if you cannot upgrade

- Limit input size. Don’t allow huge (~2GB) JSON payloads to be sent to your server. If you use Rails/Rack, set a body size limit.

Validate JSON size before parsing; reject huge files early.

- Prefer 64-bit platforms/builds: This issue is essentially unexploitable on true 64-bit environments.

MAX_JSON_SIZE = 1024 * 1024 * 100 # 100 MB

raise "File too big" if File.size("evil.json") > MAX_JSON_SIZE

Further Reading & References

- yajl-ruby GitHub advisory
- Original CVE report at NIST
- Upstream yajl issue/pull request
- Patch commit example

Summary Table

| Affected Version | Platform | Risk | Impact | Fix |
|-------------------|--------------|----------------|----------------|-----------------------|
| yajl-ruby <=1.4.1 | 32-bit only | High (DoS) | Heap Corruption| Upgrade to 1.4.2 |
| yajl-ruby >=2.x | 32-bit only | High (DoS) | Heap Corruption| Use 64-bit build |
| yajl-ruby >=1.4.2 | Any | None (Patched) | None | No action needed |

Conclusion

CVE-2022-24795 is a serious, but narrowly exploitable, bug in yajl-ruby connected to how the C layer handles huge JSON inputs on 32-bit systems. If your apps or gems use yajl-ruby—especially in scenarios where untrusted users can provide large payloads—*it’s critical to update as soon as possible* or employ the suggested workarounds.

Stay safe—stay patched!

Did you find this useful? Bookmark the references for future risk audits and always keep your Ruby dependencies up to date.

Timeline

Published on: 04/05/2022 16:15:00 UTC
Last modified on: 04/18/2022 10:05:00 UTC