Skip to main content

Oj gem CVE-2026-54903

MEDIUM
Integer Overflow or Wraparound (CWE-190)
2026-06-19 https://github.com/ohler55/oj GHSA-475m-ph3x-64gp
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
5.9 MEDIUM

Network-reachable via any endpoint calling Oj.load; AC:H because exploitation requires delivering a >2GB payload past typical body limits; PR:N/UI:N; impact is process crash, so only A:H.

3.1 AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H
4.0 AV:N/AC:H/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Red Hat
7.5 HIGH
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:36 vuln.today
Analysis Generated
Jun 19, 2026 - 21:36 vuln.today

DescriptionCVE.org

Summary

Oj.load is vulnerable to heap corruption when parsing a JSON string longer than 2 GB. An integer overflow in buf_append_string (buf.h:61) converts the string length to a large negative size_t, causing memcpy to copy an astronomically large amount of data out of bounds. This crashes the process and can corrupt adjacent heap memory.

Version

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

Details

ext/oj/buf.h, line 61:

c
inline static void buf_append_string(Buf buf, const char *s, size_t slen) {
    // ...
    memcpy(buf->tail, s, slen);   // slen derived from 32-bit int that wrapped negative

In parse.c, escape sequence handling computes the remaining string length as an int:

c
// parse.c:402 (read_escaped_str)
int  slen = (int)(s - str);   // ← wraps to negative when string > 2 GB
buf_append_string(buf, str, (size_t)slen);  // ← (size_t)(-2147483648) = 0x80000000...

ASAN report:

==399019==ERROR: AddressSanitizer: negative-size-param: (size=-2147483648)
    #0 __asan_memcpy
    #1 buf_append_string  /ext/oj/buf.h:61
    #2 read_escaped_str   /ext/oj/parse.c:402
    #3 read_str           /ext/oj/parse.c:542
    #4 oj_parse2          /ext/oj/parse.c:882
    #5 oj_pi_parse        /ext/oj/parse.c:1256
    #6 oj_object_parse    /ext/oj/object.c:701
    #7 load               /ext/oj/oj.c:1259
0x7f5a26ff0801 is located 1 bytes inside of 2147483657-byte region [0x7f5a26ff0800, 0x7f5aa6ff0809)

Reproduce

ruby
require 'oj'
n = 1 << 31
# 2 GB
json = '"' + ('A' * n) + 'A"'
# >2GB JSON string with a trailing escape
Oj.load(json)

AnalysisAI

Heap corruption in the Ruby Oj JSON parser (Oj.load) is triggered when applications process attacker-controlled JSON strings larger than 2 GB containing an escape sequence, due to an integer overflow in read_escaped_str that wraps a 32-bit length to a negative value and is then cast to size_t, causing memcpy to copy ~2 GB out of bounds. Versions of the oj gem prior to 3.17.3 are affected, and no public exploit identified at time of analysis; CVSS and EPSS are not provided.

Technical ContextAI

Oj is a widely used C-extension JSON parser for Ruby (CPE pkg:rubygems/oj), commonly used as a faster drop-in for Ruby's stdlib JSON. The root cause is CWE-190 (Integer Overflow or Wraparound): in ext/oj/parse.c:402 (read_escaped_str), the remaining string length is computed as int slen = (int)(s - str), which wraps to a negative value when the input exceeds 2^31 bytes. That value is cast to size_t and passed to buf_append_string in ext/oj/buf.h:61, where memcpy(buf->tail, s, slen) then reads ~2 GB out of bounds, corrupting adjacent heap memory and typically crashing the Ruby process, as evidenced by the AddressSanitizer negative-size-param report in the GHSA advisory.

RemediationAI

Vendor-released patch: upgrade the oj gem to version 3.17.3 or later (advisory GHSA-475m-ph3x-64gp at https://github.com/ohler55/oj/security/advisories/GHSA-475m-ph3x-64gp), e.g. by pinning gem 'oj', '>= 3.17.3' in the Gemfile and running bundle update oj. As a compensating control until patched, enforce a hard input-size limit well below 2 GB on any code path that feeds untrusted data into Oj.load - for HTTP services this typically means setting Rack/Nginx client_max_body_size (e.g. 10-100 MB) and validating JSON payload length before parsing, which has minimal side effects for normal traffic but will reject legitimate very large uploads; alternatively, route untrusted JSON through Ruby's stdlib JSON.parse until the upgrade is deployed, accepting a performance penalty.

Vendor StatusVendor

Share

CVE-2026-54903 vulnerability details – vuln.today

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