CVE-2026-54903
Oj: Integer Overflow in Oj.load 2GB String Handling
Oj (Optimized JSON) is a JSON parser and Object marshaller packaged as a Ruby gem. In versions prior to 3.17.2, 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. The 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
What each source reports
CVE List Score used
6.3
Oj: Integer Overflow in Oj.load 2GB String Handling
Oj (Optimized JSON) is a JSON parser and Object marshaller packaged as a Ruby gem. In versions prior to 3.17.2, 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. The issue has been fixed in version 3.17.2.
- Record
CVE-2026-54903- CVSS 4.0
- 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 - Weakness
- CWE-190
- Updated
- 2026-11-02
EUVDEUVD-2026-40858
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.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. The issue has been fixed in version 3.17.2.
- Record
EUVD-2026-40858- CVSS 4.0
- 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 - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-475m-ph3x-64gp
8.7
Oj: Integer Overflow in Oj.load 2GB String Handling
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.handext/oj/parse.c - Latest tested: 3.17.1 (confirmed present)
Details
ext/oj/buf.h, line 61:
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:
// 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
require 'oj'
n = 1 << 31 # 2 GB
json = '"' + ('A' * n) + 'A"' # >2GB JSON string with a trailing escape
Oj.load(json)
- Record
GHSA-475m-ph3x-64gp- CVSS 4.0
- 8.7 High
CVSS: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-190
- 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.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. The issue has been fixed in version 3.17.2.
- Record
CVE-2026-54903- CVSS 4.0
- 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 - Weakness
- CWE-190
- Updated
- 2026-11-02
OSVDEBIAN-CVE-2026-54903
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.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. The issue has been fixed in version 3.17.2.
- Record
DEBIAN-CVE-2026-54903- CVSS 4.0
- 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 - Updated
- 2026-11-02
OSVGHSA-475m-ph3x-64gp
8.7
Oj: Integer Overflow in Oj.load 2GB String Handling
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.handext/oj/parse.c - Latest tested: 3.17.1 (confirmed present)
Details
ext/oj/buf.h, line 61:
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:
// 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
require 'oj'
n = 1 << 31 # 2 GB
json = '"' + ('A' * n) + 'A"' # >2GB JSON string with a trailing escape
Oj.load(json)
- Record
GHSA-475m-ph3x-64gp- CVSS 4.0
- 8.7 High
CVSS: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-190
- Updated
- 2026-11-02
OSVUBUNTU-CVE-2026-54903
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.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. The issue has been fixed in version 3.17.2.
- Record
UBUNTU-CVE-2026-54903- CVSS 4.0
- 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 - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
ojRubyGems |
before 3.17.2 | 3.17.2 |
ruby-ojDebian:12 |
before 3.14.2-1+deb12u1, plus listed versions 3.14.2-1 |
3.14.2-1+deb12u1 |
ruby-ojDebian:13 |
before 3.16.3-1+deb13u1, plus listed versions 3.16.3-1 |
3.16.3-1+deb13u1 |
ruby-ojDebian: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 |
ojRubyGems |
before 3.17.3, plus listed versions 0.50.5.10.5.20.6.00.7.0 Show 45 moreShow less0.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-ojUbuntu:14.04:LTS |
All versions, plus listed versions 2.0.10-12.1.4-12.4.0-12.5.3-1 |
None known |
ruby-ojUbuntu:16.04:LTS |
All versions, plus listed versions 2.12.10-32.12.10-3build12.12.10-42.12.10-4build1 |
None known |
ruby-ojUbuntu:18.04:LTS |
All versions, plus listed versions 2.17.4-13.4.0-13.4.0-1build1 |
None known |
ruby-ojUbuntu: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-ojUbuntu: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
| Package | Affected | Fixed |
|---|---|---|
ruby-ojUbuntu: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-ojUbuntu:25.10 |
All versions, plus listed versions 3.16.3-1build3 |
None known |
ruby-ojUbuntu: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-ojUbuntu:26.04:LTS |
All versions, plus listed versions 3.16.3-1build33.16.12-13.16.15-1 |
None known |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-54903 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
Left out here: 244 versions. The JSON record has them.