CVE-2026-54901High▾ TwilightOj: Use-After-Free in Oj::Parser array_class/hash_class GC Marking
▾ Twilight zone — High severity, or a signal on a lesser flaw
impact 41.3 · likelihood 0.1 · exploitation 0
Need a working PoC? Pro members can cast a request and our team develops one — it lands right here.
Exploit-prediction probability, daily snapshots since Jul 4.
Disclosure to exploitation, from the record and what we observed since indexing it.
Disclosed via GHSA
0.3%
0.3% → 0.4%
Oj::Parser in usual mode does not mark array_class and hash_class references during garbage collection. If GC runs after the class is assigned but before a parse, the class object is reclaimed, leaving the parser holding a dangling VALUE. The subsequent parse call dereferences the freed object, producing a segfault.
ext/oj/usual.c / ext/oj/parser.cThe parser_mark function in ext/oj/parser.c is registered as the GC mark callback for the parser's TypedData. If array_class (stored as d->array_class in the Usual struct) is not passed to rb_gc_mark, the GC does not know it is referenced and may collect it.
When close_array_class (usual.c:405) later calls rb_funcallv on the collected class VALUE, it accesses freed memory, crashing at RIP: 0x7f... / 0x0000000000000000.
Crash output:
array_class finalized
about to parse
[BUG] Segmentation fault at 0x0000000000000000
close_array_class+0x194 /ext/oj/usual.c:405
parse+0x17b3 /ext/oj/parser.c:715
parser_parse+0x10b /ext/oj/parser.c:1408
RIP: 0x7fd1b46d68b7 RBP: 0x0000000000000000
require 'oj'
p = Oj::Parser.new(:usual,
array_class: (ac = Class.new { def <<(_x); end }))
ObjectSpace.define_finalizer(ac, proc { warn 'array_class finalized' })
ac = nil
GC.start(full_mark: true, immediate_sweep: true) # collect the class
p.parse('[1]') # segfault
oj < 3.17.2Upgrade to a patched release:
oj 3.17.3Connected by shared product, vendor, weakness, or advisory.
CVE-2026-54899HighOj: Use-After-Free in Oj::Parser Symbol Key Cache Toggle
CVE-2026-54897HighOj: Use-After-Free in Oj::Doc Iterators via Reentrant Close
CVE-2026-54898HighOj: Use-After-Free in Oj::Parser SAJ Callback via Input Mutation
CVE-2026-54900HighOj: Negative-Size memcpy in Oj::Parser create_id Attribute Handling
CVE-2026-54902HighOj: Use-After-Free in Oj::Parser SAJ Long Key Callback
CVE-2026-54502HighOj: Stack Buffer Overflow in Oj.dump via Large Indent