CVE-2026-54592: Oj: Stack Buffer Overflow in Oj::Doc#each_child via Deeply Nested Input

Published Jun 19, 2026
·
Updated

Summary

Oj::Doc#eachchild, when invoked recursively over a deeply nested JSON document, overflows a fixed-size stack buffer and aborts the process. This is a denial of service reachable from untrusted JSON.

Details

Two-step chain in ext/oj/fast.c:

1. doceachchild (~line 1501) increments doc->where past the wherepath[MAXSTACK = 100] array with no bounds check, and never restores it (doc->where-- is missing). Calling eachchild recursively from inside the yield block therefore drives doc->where beyond the array.

2. On the next entry (~line 1478) the function copies the path into a stack-local buffer:

c Leaf savepath[MAXSTACK]; // 800-byte stack buffer sizet wlen = doc->where - doc->wherepath; if (0 < wlen) { memcpy(savepath, doc->wherepath, sizeof(Leaf) (wlen + 1)); }

When the previous recursive call left doc->where past wherepath[100], wlen exceeds MAXSTACK and the memcpy overflows savepath on the C stack.

The Oj::Doc parser imposes no JSON nesting-depth limit (it relies on a C-stack pressure check), so deeply nested attacker input reaches this path.

Proof of Concept

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

Recursion depth <= 99 iterates normally; depth >= 101 aborts. lldb backtrace on the affected build (ruby 3.3.8 / arm64-darwin24):

SIGABRT #2 abort #3 stackchkfail #4 doceachchild (oj.bundle, fast.c)

Impact

Reliable denial of service: any endpoint that calls Oj::Doc.open(untrusted) { |d| d.eachchild ... } recursively can be crashed with a small deeply-nested payload. On builds with a stack protector (the default, -fstack-protector-strong) the canary aborts the process before the saved return address is used. The Step-1 heap OOB writes into struct doc fields do occur, but are masked in practice because the Step-2 stack overflow crashes first; turning them into anything beyond a crash has not been demonstrated.

Patches

Fixed in 3.17.3: doceachchild now bounds-checks before incrementing doc->where (raising Oj::DepthError) and restores doc->where after the loop, matching the existing eachleaf pattern. Verified on the fixed build: depth >= 101 raises a clean Oj::DepthError instead of aborting.

Credit

Reported by Zac Wang (@7a6163).

Other sources

Oj (Optimized JSON) is a JSON parser and Object marshaller packaged as a Ruby gem. In versions prior to 3.17.3, Oj::Doc#eachchild, when invoked recursively over a deeply nested JSON document, overflows a fixed-size stack buffer and aborts the process, leading to DoS. In a two-step chain in ext/oj/fast.c, doceachchild increments doc->where past the wherepath[MAXSTACK = 100] array with no bounds check and never restores it (the doc->where-- is missing), so calling eachchild recursively from inside the yield block drives doc->where beyond the array. On the next entry the function copies the path into the 800-byte stack-local buffer savepath[MAXSTACK] using wlen = doc->where - doc->wherepath, so when the previous recursive call left doc->where past wherepath[100] the wlen exceeds MAXSTACK and the memcpy overflows savepath on the C stack; because the Oj::Doc parser imposes no JSON nesting-depth limit (relying on a C-stack pressure check), deeply nested attacker input reaches this path. This issue has been fixed in version 3.17.3.

NVD

Oj (Optimized JSON) is a JSON parser and Object marshaller packaged as a Ruby gem. In versions prior to 3.17.3, Oj::Doc#eachchild, when invoked recursively over a deeply nested JSON document, overflows a fixed-size stack buffer and aborts the process, leading to DoS. In a two-step chain in ext/oj/fast.c, doceachchild increments doc-where past the wherepath[MAXSTACK = 100] array with no bounds check and never restores it (the doc-where-- is missing), so calling eachchild recursively from inside the yield block drives doc-where beyond the array. On the next entry the function copies the path into the 800-byte stack-local buffer savepath[MAXSTACK] using wlen = doc-where - doc-wherepath, so when the previous recursive call left doc-where past wherepath[100] the wlen exceeds MAXSTACK and the memcpy overflows savepath on the C stack; because the Oj::Doc parser imposes no JSON nesting-depth limit (relying on a C-stack pressure check), deeply nested attacker input reaches this path. This issue has been fixed in version 3.17.3.

IBM

Affected Software

2 affected componentsFixes available
rubygems/oj<3.17.3
3.17.3
IBM Aspera Enterprise WebApps<=1.0.0 - 1.0.5

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade rubygems/oj to a version that resolves this vulnerability.

    Fixed in 3.17.3
  2. Upgrade

    Upgrade Oj to a version that resolves this vulnerability.

    Fixed in 3.17.3

Event History

Jun 19, 2026
Advisory Published
via GitHub·07:36 PM
Data Sourced
via GitHub·07:36 PM
DescriptionSeverityWeaknessAffected Software
Jun 30, 2026
CVE Published
via MITRE·11:16 PM
Data Sourced
via MITRE·11:16 PM
DescriptionSeverityWeakness
Jul 1, 2026
Data Sourced
via NVD·12:16 AM
DescriptionSeverityWeakness
Sep 8, 2026
Data Sourced
via IBM·12:00 AM
DescriptionAffected Software

Parent advisories

This vulnerability appears in the following advisories.

Frequently Asked Questions

1

What is the severity of CVE-2026-54592?

CVE-2026-54592 has a severity rating of high, with a score of 7.5.

2

How do I fix CVE-2026-54592?

To mitigate CVE-2026-54592, update the oj gem to the latest version that addresses this vulnerability.

3

What type of vulnerability is CVE-2026-54592?

CVE-2026-54592 is a denial of service vulnerability caused by a stack buffer overflow in the Oj library.

4

What impact does CVE-2026-54592 have on my application?

CVE-2026-54592 can cause your application to abort or crash when processing deeply nested JSON documents.

5

Is CVE-2026-54592 exploitable remotely?

Yes, CVE-2026-54592 can be exploited remotely through untrusted JSON input.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203