Oj - Stack Buffer Overflow in Oj::Doc#each_child via Deeply Nested Input
Published: June 19, 2026
SECURITY IDENTIFIERS
- CVE: CVE-2026-54592 (NVD)
- GHSA: GHSA-3m6q-jj5j-38c9
GEM
SEVERITY
CVSS v3.x: 7.5 (High)
PATCHED VERSIONS
>= 3.17.3
DESCRIPTION
Summary
Oj::Doc#each_child, 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.
Impact
Reliable denial of service: any endpoint that calls
Oj::Doc.open(untrusted) { |d| d.each_child ... } 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: doc_each_child now bounds-checks before incrementing
doc->where (raising Oj::DepthError) and restores doc->where after the
loop, matching the existing each_leaf pattern. Verified on the fixed build:
depth >= 101 raises a clean Oj::DepthError instead of aborting.
Credit
Reported by Zac Wang (@7a6163).
RELATED
- https://www.cve.org/CVERecord/SearchResults?query=CVE-2026-54592
- https://rubygems.org/gems/oj/versions/3.17.3
- https://github.com/ohler55/oj/blob/master/CHANGELOG.md#3173---2026-06-04
- https://github.com/ohler55/oj/pull/1015
- https://github.com/ohler55/oj/security/advisories/GHSA-3m6q-jj5j-38c9
- https://github.com/advisories/GHSA-3m6q-jj5j-38c9
