Skip to main content

Oj gem CVE-2026-54901

MEDIUM
Use After Free (CWE-416)
2026-06-19 https://github.com/ohler55/oj GHSA-vwm4-62gf-x745
6.3
CVSS 4.0 · Vendor: https://github.com/ohler55/oj
Share

Severity by source

Vendor (https://github.com/ohler55/oj) PRIMARY
6.3 MEDIUM
CVSS: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
vuln.today AI
1.9 LOW

Trigger requires in-process configuration of Oj::Parser with array_class/hash_class and a GC race, so AV:L/AC:H/PR:H; impact is a crash only, hence C:N/I:N/A:L.

3.1 AV:L/AC:H/PR:H/UI:N/S:U/C:N/I:N/A:L
4.0 AV:L/AC:H/AT:N/PR:H/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N

Primary rating from Vendor (https://github.com/ohler55/oj).

CVSS VectorVendor: https://github.com/ohler55/oj

CVSS: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
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
X

Lifecycle Timeline

3
CVSS changed
Jul 01, 2026 - 00:22 NVD
6.3 (MEDIUM)
Source Code Evidence Fetched
Jun 19, 2026 - 21:34 vuln.today
Analysis Generated
Jun 19, 2026 - 21:34 vuln.today

DescriptionCVE.org

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

ruby
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

AnalysisAI

Use-after-free in the Oj Ruby JSON gem (≤ 3.17.1) crashes the host process when Oj::Parser is configured in :usual mode with a custom array_class or hash_class. Because parser_mark fails to register those VALUEs with the Ruby GC, the class object can be reclaimed and the next parse() dereferences freed memory, producing a segfault. …

Unlock full vulnerability intelligence

  • Risk assessment & exploitation conditions
  • Attack chain visualization
  • Remediation with exact patch versions
  • Threat intelligence from 22 sources
  • Personal watchlist & email alerts

Free forever · No credit card required

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata

Access
Access Ruby process using Oj::Parser :usual mode
Delivery
Reach code path that sets array_class/hash_class without strong reference
Exploit
Induce GC pressure to sweep the class VALUE
Execution
Trigger parse() on JSON input
Persist
rb_funcallv dereferences freed class
Impact
Worker segfaults causing denial of service

Vulnerability AssessmentAI

Exploitation Requires the target Ruby application to instantiate Oj::Parser in :usual mode (Oj::Parser.new(:usual, …)) with the array_class: or hash_class: option set to a class VALUE that has no other live references, and for Ruby's GC to run a marking/sweep cycle between that assignment and the parse() call. … Additional conditions and limiting factors are described in the full assessment.
Risk Assessment No CVSS or EPSS values are supplied and the CVE is not in CISA KEV, so this should be treated as a stability/availability bug rather than a high-severity security issue. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in.
Exploit Scenario An attacker who can influence when Ruby triggers garbage collection between Oj::Parser configuration and a parse call - for example by submitting allocation-heavy input to a long-running web worker that uses Oj::Parser with a custom array_class - can race the GC to free the class VALUE before parse() dereferences it, crashing the worker process and causing repeated denial of service. The GHSA advisory includes a deterministic Ruby reproducer that forces GC with GC.start(full_mark: true, immediate_sweep: true) and reliably segfaults on 3.17.1, so publicly available exploit code exists for the local crash, though no remote weaponization is published.
Remediation Vendor-released patch: upgrade the oj gem to 3.17.3 (or any later release), which is the fixed version per GHSA-vwm4-62gf-x745 (https://github.com/ohler55/oj/security/advisories/GHSA-vwm4-62gf-x745); update Gemfile.lock and rebuild native extensions. … Detailed patch versions, workarounds, and compensating controls in full report.

Recommended ActionAI

Within 24 hours: Identify all Ruby applications using Oj gem via dependency scanning and code review; prioritize those with custom array_class or hash_class parser configurations. …

Sign in for detailed remediation steps and compensating controls.

Threat intelligence, references, and detailed analysis are available after sign-in.

Share

CVE-2026-54901 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy