Every CVE Search/ Get API key

CVE-2026-54901

Oj: Use-After-Free in Oj::Parser array_class/hash_class GC Marking

6.3 MediumFix available

Oj (Optimized JSON) is a JSON parser and Object marshaller packaged as a Ruby gem. In versions prior to 3.17.2, Oj::Parser in usual mode does not mark array_class and hash_class references during garbage collection, leading to Use-After-Free. 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. This issue has been fixed in version 3.17.2.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
None
Availability
Low

Exploit likelihood

0.41%Up 0.2 points since Jul 1, 2026
90%50%10%1%

What each source reports

CVE List Score used 6.3

Oj: Use-After-Free in Oj::Parser array_class/hash_class GC Marking

Oj (Optimized JSON) is a JSON parser and Object marshaller packaged as a Ruby gem. In versions prior to 3.17.2, Oj::Parser in usual mode does not mark array_class and hash_class references during garbage collection, leading to Use-After-Free. 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. This issue has been fixed in version 3.17.2.

Record
CVE-2026-54901
CVSS 4.0
6.3 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N
Weakness
CWE-416
Updated
2026-11-02
EUVDEUVD-2026-40856 6.3

Oj (Optimized JSON) is a JSON parser and Object marshaller packaged as a Ruby gem. In versions prior to 3.17.2, Oj::Parser in usual mode does not mark array_class and hash_class references during garbage collection, leading to Use-After-Free. 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. This issue has been fixed in version 3.17.2.

Record
EUVD-2026-40856
CVSS 4.0
6.3 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-vwm4-62gf-x745 8.7

Oj: Use-After-Free in Oj::Parser array_class/hash_class GC Marking

Summary

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.

Version

  • Software: oj gem
  • Affected: all versions with ext/oj/usual.c / ext/oj/parser.c
  • Latest tested: 3.17.1 (confirmed present)

Details

The 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

Reproduce

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
Record
GHSA-vwm4-62gf-x745
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-416
Updated
2026-11-02
NVD 6.3

Oj (Optimized JSON) is a JSON parser and Object marshaller packaged as a Ruby gem. In versions prior to 3.17.2, Oj::Parser in usual mode does not mark array_class and hash_class references during garbage collection, leading to Use-After-Free. 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. This issue has been fixed in version 3.17.2.

Record
CVE-2026-54901
CVSS 4.0
6.3 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Weakness
CWE-416
Updated
2026-11-02
OSVDEBIAN-CVE-2026-54901 6.3

Oj (Optimized JSON) is a JSON parser and Object marshaller packaged as a Ruby gem. In versions prior to 3.17.2, Oj::Parser in usual mode does not mark array_class and hash_class references during garbage collection, leading to Use-After-Free. 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. This issue has been fixed in version 3.17.2.

Record
DEBIAN-CVE-2026-54901
CVSS 4.0
6.3 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Updated
2026-11-02
OSVGHSA-vwm4-62gf-x745 8.7

Oj: Use-After-Free in Oj::Parser array_class/hash_class GC Marking

Summary

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.

Version

  • Software: oj gem
  • Affected: all versions with ext/oj/usual.c / ext/oj/parser.c
  • Latest tested: 3.17.1 (confirmed present)

Details

The 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

Reproduce

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
Record
GHSA-vwm4-62gf-x745
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-416
Updated
2026-11-02
OSVUBUNTU-CVE-2026-54901 6.3

Oj (Optimized JSON) is a JSON parser and Object marshaller packaged as a Ruby gem. In versions prior to 3.17.2, Oj::Parser in usual mode does not mark array_class and hash_class references during garbage collection, leading to Use-After-Free. 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. This issue has been fixed in version 3.17.2.

Record
UBUNTU-CVE-2026-54901
CVSS 4.0
6.3 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
oj
RubyGems
before 3.17.2
3.17.2
ruby-oj
Debian:12
before 3.14.2-1+deb12u1, plus listed versions
3.14.2-1
3.14.2-1+deb12u1
ruby-oj
Debian:13
before 3.16.3-1+deb13u1, plus listed versions
3.16.3-1
3.16.3-1+deb13u1
ruby-oj
Debian:14
before 3.17.3-1, plus listed versions
3.16.12-13.16.15-13.16.16-13.16.3-13.17.0-13.17.1-1
3.17.3-1
oj
RubyGems
before 3.17.3, plus listed versions
0.50.5.10.5.20.6.00.7.0
Show 45 moreShow less
0.8.00.9.01.0.01.0.11.0.21.0.31.0.41.0.51.0.61.1.01.1.11.2.01.2.11.2.101.2.111.2.121.2.131.2.21.2.31.2.41.2.51.2.61.2.71.2.81.2.91.3.01.3.21.3.41.3.51.3.61.3.71.4.01.4.11.4.21.4.31.4.41.4.51.4.61.4.6a21.4.72.0.02.0.12.0.102.0.112.0.12
3.17.3
ruby-oj
Ubuntu:14.04:LTS
All versions, plus listed versions
2.0.10-12.1.4-12.4.0-12.5.3-1
None known
ruby-oj
Ubuntu:16.04:LTS
All versions, plus listed versions
2.12.10-32.12.10-3build12.12.10-42.12.10-4build1
None known
ruby-oj
Ubuntu:18.04:LTS
All versions, plus listed versions
2.17.4-13.4.0-13.4.0-1build1
None known
ruby-oj
Ubuntu:20.04:LTS
All versions, plus listed versions
3.8.1-13.9.1-13.9.2-13.10.1-13.10.1-1build1
None known
ruby-oj
Ubuntu:22.04:LTS
All versions, plus listed versions
3.11.0-13.13.7-13.13.7-1build13.13.9-13.13.9-1build1
None known
Show 4 moreShow less
Affected packages
PackageAffectedFixed
ruby-oj
Ubuntu:24.04:LTS
All versions, plus listed versions
3.15.0-13.16.1-13.16.3-13.16.3-1build13.16.3-1build2
None known
ruby-oj
Ubuntu:25.10
All versions, plus listed versions
3.16.3-1build3
None known
ruby-oj
Ubuntu:26.10
All versions, plus listed versions
3.16.15-13.17.0-13.17.1-13.17.3-13.17.4-1
None known
ruby-oj
Ubuntu:26.04:LTS
All versions, plus listed versions
3.16.3-1build33.16.12-13.16.15-1
None known

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-54901 is a medium vulnerability (CVSS 6.3) in Ohler55 Oj, published June 19, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.41%, the 35th percentile. Fixed in oj 3.17.2.

References

This page doesn't list everything

Left out here: 244 versions. The JSON record has them.

MoveEnter Open