CVE-2026-54898
NoneCVSS
—
EPSS
0.1%
Published
Jul 1, 2026
CISA due date
—
Cloudanix analysis
A Ruby JSON parsing library can crash certain applications if parsing callbacks modify the data being parsed, so affected software should be updated.
- Exploitation
- Local Privilege
- Attacker needs
- Local User
- Complexity
- Moderate
- Impact
- Denial Of Service
- Component
- Library
- Class
- Use After Free
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
Oj versions prior to 3.17.2 contain a heap use-after-free in Oj::Parser#parse when using SAJ/SAJ2-style callbacks. During parsing, the native C engine keeps a raw pointer into a Ruby String buffer; if a callback mutates or resizes that same input string, such as replacing it with a longer value, Ruby can reallocate the buffer and free the memory the parser still references. The next parser read can then dereference stale memory, resulting in process instability, memory-safety faults, or a crash. Based on the published scoring, the practical impact is primarily local availability loss rather than confirmed remote code execution or data compromise.
Why it matters to the business
Applications or background jobs that use vulnerable Oj parsing with callbacks may crash when processing crafted or unusual JSON flows that trigger input mutation during parsing. The most likely operational consequence is intermittent service failure, job interruption, or degraded availability in Ruby services that depend on Oj. The issue is not in CISA KEV, has very low EPSS, and has no reported exploit maturity, so urgency is lower than actively exploited internet-facing vulnerabilities, but affected systems should still be upgraded because memory-safety bugs can be difficult to reason about and may become more serious as research matures.
How an attack unfolds
An attacker first needs a way to influence a Ruby execution path that invokes Oj::Parser#parse with SAJ or SAJ2 callbacks and causes one of those callbacks to mutate the same JSON input string while parsing is still in progress. The attacker then supplies JSON that reaches the vulnerable callback sequence. When the callback resizes the original Ruby String, Ruby may move the string data to a new heap allocation and free the old buffer. The native Oj parser continues using its stale pointer into the freed buffer; on the next character read, the process can hit a use-after-free condition and crash. In most deployments, exploitation is likely constrained to denial of service because it depends on application-specific callback behavior and there is no public indication of reliable code execution.
How to fix it
Upgrade the Oj Ruby gem to version 3.17.2 or later wherever it is installed. If immediate upgrade is not possible, review all uses of Oj::Parser#parse with SAJ/SAJ2 callbacks and ensure callbacks do not mutate the input JSON String being parsed. As a defense-in-depth mitigation, pass an immutable or duplicated copy into the parser, avoid String#replace or other resizing operations on the parsed buffer during callbacks, and isolate JSON parsing in worker processes that can fail safely without taking down critical services. Rebuild and redeploy all application images, bundles, and lockfiles that pin Oj below 3.17.2.
How to confirm the fix worked
Confirm dependency resolution shows Oj 3.17.2 or later, for example through Gemfile.lock, bundle list, gem list oj, container SBOMs, and production artifact manifests. Search source code for Oj::Parser#parse, SAJ, SAJ2, hash_start, array_start, and callbacks that call String#replace, String#concat, String#<<, force_encoding, clear, or other mutating String methods on the input buffer. Run regression tests that exercise SAJ/SAJ2 parsing paths after the upgrade. For high-assurance validation, run targeted tests under AddressSanitizer or Ruby crash monitoring and verify the prior use-after-free or segmentation fault signature is no longer reproducible.
Typical attack path
- Identify a Ruby application, worker, plugin, or local script that uses Oj versions before 3.17.2.
- Find a code path that uses Oj::Parser#parse with SAJ or SAJ2 callbacks.
- Determine whether a callback can mutate or resize the same input JSON String during parsing.
- Provide JSON input that drives execution into the mutating callback path.
- Trigger String reallocation while the native parser still holds a pointer to the previous buffer.
- Cause the parser to dereference freed memory, leading to a crash or other memory-safety failure.
How to detect it
There are no public, reliable network indicators for prior exploitation because exploitation depends on in-process Ruby callback behavior rather than a distinctive remote payload. To assess whether the issue was triggered, review application logs, process supervisor logs, container logs, Ruby crash reports, core dumps, APM error traces, and system logs for crashes involving Oj::Parser#parse, SAJ/SAJ2 callbacks, or native faults in the Oj extension. Look for segmentation faults, bus errors, allocator errors, AddressSanitizer use-after-free reports, or repeated worker restarts occurring while processing JSON. Correlate crash timestamps with inbound requests, queue messages, file imports, or API payloads containing JSON, especially where the same endpoint or job repeatedly causes parser crashes. If core dumps are available, inspect native backtraces for Oj parser frames and Ruby String mutation callbacks such as hash_start or array_start. Absence of these artifacts does not prove absence of exposure; it only suggests the vulnerable condition has not obviously crashed the process.
- Oj::Parser#parse
- parser.c:607
- heap-use-after-free
- use-after-free
- AddressSanitizer: heap-use-after-free
- SEGV
- SIGSEGV
- segmentation fault
- bus error
- Oj::Saj
- Oj::Saj2
- hash_start
- array_start
- String#replace
- oj-3.17.1
- oj-3.17.0
- oj (3.17.1)
- oj (3.17.0)
What your security team should do
- Inventory Ruby applications, containers, gems, and build artifacts for Oj versions earlier than 3.17.2.
- Prioritize upgrading internet-facing services, shared parsing libraries, queue workers, and systems that process untrusted JSON, even though current exploitation likelihood is low.
- Patch by updating Oj to 3.17.2 or later and redeploying all affected application artifacts rather than relying only on source dependency changes.
- Review SAJ/SAJ2 callback implementations for mutation of the parsed input string and refactor unsafe callback behavior.
- Add dependency scanning or SBOM policy gates to prevent introduction of Oj versions below 3.17.2.
- Monitor application crash logs for segmentation faults, aborts, or sanitizer findings involving Oj::Parser#parse or parser.c around the vulnerable read path.
- Because this is not KEV-listed and has very low EPSS, treat remediation as standard-priority unless the affected parser is reachable through untrusted JSON processing or causes high-availability services to crash.
The record
Oj (Optimized JSON) is a JSON parser and Object marshaller packaged as a Ruby gem. In versions prior to 3.17.2,Oj::Parser#parse is vulnerable to a heap use-after-free when a SAJ/SAJ2 callback mutates the input JSON string during parsing. The C engine holds a raw const byte * pointer into the Ruby string's internal buffer. If a callback (e.g. hash_start) resizes the string — for example by calling String#replace with a longer value — Ruby reallocates the string buffer and frees the old one. The C parser's pointer is left dangling; the next character read at parser.c:607 is a use-after-free. This issue has been fixed in version 3.17.2.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|
Related vulnerabilities
- CVE-2026-109618 PHP uses longjmp() for out-of-memory (OOM) errors to exit the current context and abort… CWE-416
- CVE-2026-109619 PHP has various global state that temporarily points into request memory. CWE-416
- CVE-2026-112402 Pillow is a Python imaging library. CWE-416
- CVE-2026-112396 Pillow is a Python imaging library. CWE-416
- CVE-2025-55654 A use-after-free in the gf_filter_pid_get_packet function (filter_core/filter_pid.c) of… CWE-416
- CVE-2026-17591 A flaw was found in libarchive. CWE-416
- CVE-2026-92392 During an upload, curl mishandles HTTP/2 `RST_STREAM` received from the server (with… CWE-416
- CVE-2026-109268 ImageMagick before 6.9.13-57 and 7.x before 7.1.2-32 contains a use after free… CWE-416