Every CVE Search/ Get API key

CVE-2026-54902

Oj: Use-After-Free in Oj::Parser SAJ Long Key Callback

6.3 MediumFix available

Oj (Optimized JSON) is a JSON parser and Object marshaller packaged as a Ruby gem. Prior to version 3.17.2, is vulnerable to Use-After-Free when in SAJ mode. The Oj::Parser does not protect cached object keys (≥ 35 bytes) from garbage collection, and a Ruby callback that triggers GC inside hash_end can cause the key string to be reclaimed while the C parser still holds a pointer to it. The subsequent access to the freed string VALUE results in a segfault, confirmed by an RIP pointing to address 0x4242 (a canary-style pattern suggesting control over the freed memory's content). 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.50%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 SAJ Long Key Callback

Oj (Optimized JSON) is a JSON parser and Object marshaller packaged as a Ruby gem. Prior to version 3.17.2, is vulnerable to Use-After-Free when in SAJ mode. The Oj::Parser does not protect cached object keys (≥ 35 bytes) from garbage collection, and a Ruby callback that triggers GC inside hash_end can cause the key string to be reclaimed while the C parser still holds a pointer to it. The subsequent access to the freed string VALUE results in a segfault, confirmed by an RIP pointing to address 0x4242 (a canary-style pattern suggesting control over the freed memory's content). This issue has been fixed in version 3.17.2.

Record
CVE-2026-54902
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-40857 6.3

Oj (Optimized JSON) is a JSON parser and Object marshaller packaged as a Ruby gem. Prior to version 3.17.2, is vulnerable to Use-After-Free when in SAJ mode. The Oj::Parser does not protect cached object keys (≥ 35 bytes) from garbage collection, and a Ruby callback that triggers GC inside hash_end can cause the key string to be reclaimed while the C parser still holds a pointer to it. The subsequent access to the freed string VALUE results in a segfault, confirmed by an RIP pointing to address 0x4242 (a canary-style pattern suggesting control over the freed memory's content). This issue has been fixed in version 3.17.2.

Record
EUVD-2026-40857
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-m578-w5vf-rfcm 8.7

Oj: Use-After-Free in Oj::Parser SAJ Long Key Callback

Summary

Oj::Parser in SAJ mode does not protect cached object keys (≥ 35 bytes) from garbage collection. A Ruby callback that triggers GC inside hash_end can cause the key string to be reclaimed while the C parser still holds a pointer to it. The subsequent access to the freed string VALUE results in a segfault, confirmed by an RIP pointing to address 0x4242 (a canary-style pattern suggesting control over the freed memory's content).

Version

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

Details

Short keys (≤ 34 bytes) are stored inline on the C stack and are safe. Long keys (≥ 35 bytes) are stored as heap-allocated Ruby String objects passed to rb_funcall as the key argument. Between the key being resolved and the callback completing, a GC triggered inside the callback (e.g. GC.start) can collect the key String, leaving a dangling VALUE.

Crash output:

long_key_trigger
[BUG] Segmentation fault at 0x0000000000004242
    close_object+0x260    /ext/oj/usual.c:405  (calls rb_funcall with freed key)
    parse+0x11ff          /ext/oj/parser.c:693
    parser_parse+0x145    /ext/oj/parser.c:1408

RIP: 0x7fd1b46d68b7  RDI: 0x0000000000004242  (freed key VALUE)
R12: 0x0000000000004242

The freed VALUE 0x4242 shows the attacker-controlled content of the key string was loaded as a pointer — a classic use-after-free indicator.

Reproduce

require 'oj'

class H < Oj::Saj
  def add_value(value, key)
    GC.start(full_mark: true, immediate_sweep: true) if key == 'x'
  end
  def hash_start(key); end
  def hash_end(key); end
end

p = Oj::Parser.new(:saj)
p.handler = H.new
p.parse('{"' + 'A' * 35 + '":{"x":1}}')  # long outer key, GC fires on inner key
Record
GHSA-m578-w5vf-rfcm
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. Prior to version 3.17.2, is vulnerable to Use-After-Free when in SAJ mode. The Oj::Parser does not protect cached object keys (≥ 35 bytes) from garbage collection, and a Ruby callback that triggers GC inside hash_end can cause the key string to be reclaimed while the C parser still holds a pointer to it. The subsequent access to the freed string VALUE results in a segfault, confirmed by an RIP pointing to address 0x4242 (a canary-style pattern suggesting control over the freed memory's content). This issue has been fixed in version 3.17.2.

Record
CVE-2026-54902
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-54902 6.3

Oj (Optimized JSON) is a JSON parser and Object marshaller packaged as a Ruby gem. Prior to version 3.17.2, is vulnerable to Use-After-Free when in SAJ mode. The Oj::Parser does not protect cached object keys (≥ 35 bytes) from garbage collection, and a Ruby callback that triggers GC inside hash_end can cause the key string to be reclaimed while the C parser still holds a pointer to it. The subsequent access to the freed string VALUE results in a segfault, confirmed by an RIP pointing to address 0x4242 (a canary-style pattern suggesting control over the freed memory's content). This issue has been fixed in version 3.17.2.

Record
DEBIAN-CVE-2026-54902
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-m578-w5vf-rfcm 8.7

Oj: Use-After-Free in Oj::Parser SAJ Long Key Callback

Summary

Oj::Parser in SAJ mode does not protect cached object keys (≥ 35 bytes) from garbage collection. A Ruby callback that triggers GC inside hash_end can cause the key string to be reclaimed while the C parser still holds a pointer to it. The subsequent access to the freed string VALUE results in a segfault, confirmed by an RIP pointing to address 0x4242 (a canary-style pattern suggesting control over the freed memory's content).

Version

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

Details

Short keys (≤ 34 bytes) are stored inline on the C stack and are safe. Long keys (≥ 35 bytes) are stored as heap-allocated Ruby String objects passed to rb_funcall as the key argument. Between the key being resolved and the callback completing, a GC triggered inside the callback (e.g. GC.start) can collect the key String, leaving a dangling VALUE.

Crash output:

long_key_trigger
[BUG] Segmentation fault at 0x0000000000004242
    close_object+0x260    /ext/oj/usual.c:405  (calls rb_funcall with freed key)
    parse+0x11ff          /ext/oj/parser.c:693
    parser_parse+0x145    /ext/oj/parser.c:1408

RIP: 0x7fd1b46d68b7  RDI: 0x0000000000004242  (freed key VALUE)
R12: 0x0000000000004242

The freed VALUE 0x4242 shows the attacker-controlled content of the key string was loaded as a pointer — a classic use-after-free indicator.

Reproduce

require 'oj'

class H < Oj::Saj
  def add_value(value, key)
    GC.start(full_mark: true, immediate_sweep: true) if key == 'x'
  end
  def hash_start(key); end
  def hash_end(key); end
end

p = Oj::Parser.new(:saj)
p.handler = H.new
p.parse('{"' + 'A' * 35 + '":{"x":1}}')  # long outer key, GC fires on inner key
Record
GHSA-m578-w5vf-rfcm
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-54902 6.3

Oj (Optimized JSON) is a JSON parser and Object marshaller packaged as a Ruby gem. Prior to version 3.17.2, is vulnerable to Use-After-Free when in SAJ mode. The Oj::Parser does not protect cached object keys (≥ 35 bytes) from garbage collection, and a Ruby callback that triggers GC inside hash_end can cause the key string to be reclaimed while the C parser still holds a pointer to it. The subsequent access to the freed string VALUE results in a segfault, confirmed by an RIP pointing to address 0x4242 (a canary-style pattern suggesting control over the freed memory's content). This issue has been fixed in version 3.17.2.

Record
UBUNTU-CVE-2026-54902
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
OSVROOT-APP-RUBY-CVE-2026-54902 No score

CVE-2026-54902 in oj - Patched by Root

Root has patched CVE-2026-54902 in the oj package for Root:Ruby. Multiple fixed versions available.

Record
ROOT-APP-RUBY-CVE-2026-54902
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.6-2, plus listed versions
3.16.12-13.16.15-13.16.16-13.16.3-13.17.0-1
Show 4 moreShow less
3.17.1-13.17.3-13.17.4-13.17.6-1
3.17.6-2
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
oj
Root:Ruby
before 3.16.17.41610.4
3.16.17.41610.43.16.17.41610.5
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
Show 5 moreShow less
Affected packages
PackageAffectedFixed
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
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-54902 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.50%, the 42nd 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