Skip to main content

Oj gem CVE-2026-54899

MEDIUM
Use After Free (CWE-416)
2026-06-19 https://github.com/ohler55/oj GHSA-2cw7-v8ff-p88r
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:L/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
7.0 HIGH

Attacker-supplied JSON reaches the bug remotely (AV:N) but only when the app reuses a parser and toggles symbol_keys (AC:H); no auth or UI needed; UAF most reliably crashes the worker (A:H) with possible limited memory disclosure/corruption (C:L/I:L).

3.1 AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:H
4.0 AV:N/AC:H/AT:P/PR:N/UI:N/VC:L/VI:L/VA:H/SC:N/SI:N/SA:N
Red Hat
6.5 MEDIUM
qualitative

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

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

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:21 vuln.today
Analysis Generated
Jun 19, 2026 - 21:21 vuln.today

DescriptionCVE.org

Summary

Disabling symbol_keys on a reused Oj::Parser instance triggers a heap use-after-free. When symbol_keys is toggled from true to false, opt_symbol_keys_set frees the internal key cache (cache_free) but does not clear the pointer. The next parse call reads from the freed cache via cache_intern, producing a use-after-free.

Version

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

Details

ext/oj/usual.c, opt_symbol_keys_set:

c
// usual.c:1043-1051
if (symbol_keys) {
    d->key_cache = cache_create(...);   // allocate
} else {
    cache_free(d->key_cache);           // free - but d->key_cache pointer not NULLed
}

On the next parse call, cache_keycache_intern reads from d->key_cache which now points to freed memory.

ASAN report:

==145265==ERROR: AddressSanitizer: heap-use-after-free on address 0x50b00001a318
READ of size 8 at 0x50b00001a318 thread T0
    #0 cache_intern            /ext/oj/cache.c:328
    #1 cache_key               /ext/oj/usual.c:161
    #2 close_object            /ext/oj/usual.c:285
    #3 parse                   /ext/oj/parser.c:693
    #4 parser_parse            /ext/oj/parser.c:1408
freed by thread T0 here:
    #0 free
    #1 cache_free              /ext/oj/cache.c:277
    #2 opt_symbol_keys_set     /ext/oj/usual.c:1051
    #3 option                  /ext/oj/usual.c:1111
    #4 parser_missing          /ext/oj/parser.c:1362
0x50b00001a318 is 40 bytes inside freed 112-byte region [fd]fd fd fd fd fd fd fd

Reproduce

ruby
require 'oj'
p = Oj::Parser.new(:usual, symbol_keys: true)
p.symbol_keys = false
# frees cache without nulling pointer
p.parse('{"attacker":1}')
# UAF: reads freed cache

AnalysisAI

Heap use-after-free in the Oj Ruby JSON parser (versions prior to 3.17.3) is triggered when an application toggles the symbol_keys option from true to false on a reused Oj::Parser instance. The opt_symbol_keys_set function frees the internal key cache via cache_free but fails to NULL the d->key_cache pointer, so the next parse call dereferences freed memory through cache_intern, potentially leading to memory disclosure, crashes, or controlled corruption. No public exploit identified at time of analysis, and the issue is documented in GitHub Security Advisory GHSA-2cw7-v8ff-p88r.

Technical ContextAI

Oj (Optimized JSON) is a high-performance C-extension JSON parser/serializer for Ruby, widely used as a drop-in replacement for the standard JSON library and by Rails applications via multi_json. The flaw lives in the optimized 'usual' parser implementation (ext/oj/usual.c) which maintains a key_cache structure used by cache_intern to deduplicate and intern hash keys (as Symbol or String) during object parsing. The root cause is CWE-416 (Use After Free): opt_symbol_keys_set at ext/oj/usual.c:1043-1051 calls cache_free(d->key_cache) when disabling symbol keys but does not assign d->key_cache = NULL, leaving a dangling pointer that close_object → cache_key → cache_intern (cache.c:328) subsequently reads on the next parse, as confirmed by the AddressSanitizer trace provided in the advisory.

RemediationAI

Vendor-released patch: oj 3.17.3 - upgrade by pinning gem 'oj', '>= 3.17.3' in the Gemfile and running bundle update oj, then redeploy so the C extension is recompiled against the fixed source (see https://github.com/ohler55/oj/security/advisories/GHSA-2cw7-v8ff-p88r). If immediate upgrade is not possible, the targeted workaround is to avoid mutating symbol_keys on an existing Oj::Parser instance: construct a fresh Oj::Parser for each desired configuration, or set symbol_keys only once at construction; alternatively, route untrusted JSON through Oj.load / Oj.safe_load rather than a reused Oj::Parser, accepting the throughput cost of not reusing the parser object. Auditing application code and dependencies for any assignment like parser.symbol_keys = false on a long-lived parser is a quick way to confirm exposure.

Vendor StatusVendor

Share

CVE-2026-54899 vulnerability details – vuln.today

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