{"id":"CVE-2026-54903","aliases":["DEBIAN-CVE-2026-54903","EUVD-2026-40858","GHSA-475m-ph3x-64gp","UBUNTU-CVE-2026-54903"],"status":"published","title":"Oj: Integer Overflow in Oj.load 2GB String Handling","description":"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.","severity":{"version":"4.0","score":6.3,"vector":"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","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00407,"percentile":0.35259,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-190"],"published":"2026-06-19T20:47:31Z","modified":"2026-10-26T11:47:25Z","fixes":[{"ecosystem":"RubyGems","package":"oj","fixed_in":["3.17.2","3.17.3"],"sources":["ghsa","osv"]},{"ecosystem":"Debian:12","package":"ruby-oj","fixed_in":["3.14.2-1+deb12u1"],"sources":["osv"]},{"ecosystem":"Debian:13","package":"ruby-oj","fixed_in":["3.16.3-1+deb13u1"],"sources":["osv"]},{"ecosystem":"Debian:14","package":"ruby-oj","fixed_in":["3.17.3-1"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"RubyGems","package":"oj","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.17.2"}]}]},{"source":"osv","ecosystem":"Debian:12","package":"ruby-oj","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.14.2-1+deb12u1"}]}],"versions":["3.14.2-1"]},{"source":"osv","ecosystem":"Debian:13","package":"ruby-oj","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.16.3-1+deb13u1"}]}],"versions":["3.16.3-1"]},{"source":"osv","ecosystem":"Debian:14","package":"ruby-oj","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.17.3-1"}]}],"versions":["3.16.12-1","3.16.15-1","3.16.16-1","3.16.3-1","3.17.0-1","3.17.1-1"]},{"source":"osv","ecosystem":"RubyGems","package":"oj","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.17.3"}]}],"versions":["0.5","0.5.1","0.5.2","0.6.0","0.7.0","0.8.0","0.9.0","1.0.0","1.0.1","1.0.2","1.0.3","1.0.4","1.0.5","1.0.6","1.1.0","1.1.1","1.2.0","1.2.1","1.2.10","1.2.11","1.2.12","1.2.13","1.2.2","1.2.3","1.2.4","1.2.5","1.2.6","1.2.7","1.2.8","1.2.9","1.3.0","1.3.2","1.3.4","1.3.5","1.3.6","1.3.7","1.4.0","1.4.1","1.4.2","1.4.3","1.4.4","1.4.5","1.4.6","1.4.6a2","1.4.7","2.0.0","2.0.1","2.0.10","2.0.11","2.0.12","2.0.13","2.0.14","2.0.2","2.0.3","2.0.4","2.0.5","2.0.6","2.0.7","2.0.8","2.0.9","2.1.0","2.1.1","2.1.2","2.1.3","2.1.4","2.1.6","2.1.7","2.10.0","2.10.1","2.10.2","2.10.3","2.10.4","2.11.0","2.11.1","2.11.2","2.11.3","2.11.4","2.11.5","2.12.0","2.12.1","2.12.10","2.12.11","2.12.12","2.12.13","2.12.14","2.12.2","2.12.3","2.12.4","2.12.5","2.12.6","2.12.7","2.12.8","2.12.9","2.13.0","2.13.1","2.14.0","2.14.1","2.14.2","2.14.3","2.14.4","2.14.5","2.14.6","2.15.0","2.15.1","2.16.0","2.16.1","2.17.0","2.17.1","2.17.2","2.17.3","2.17.4","2.17.5","2.18.0","2.18.1","2.18.2","2.18.3","2.18.4","2.18.5","2.2.0","2.2.1","2.2.2","2.2.3","2.3.0","2.4.0","2.4.1","2.4.2","2.4.3","2.5.1","2.5.2","2.5.3","2.5.4","2.5.5","2.6.0","2.6.1","2.7.0","2.7.1","2.7.2","2.7.3","2.8.0","2.8.1","2.9.0","2.9.1","2.9.2","2.9.3","2.9.4","2.9.5","2.9.6","2.9.7","2.9.8","2.9.9","3.0.0","3.0.1","3.0.10","3.0.11","3.0.2","3.0.3","3.0.4","3.0.5","3.0.6","3.0.7","3.0.8","3.0.9","3.1.0","3.1.2","3.1.3","3.1.4","3.10.0","3.10.1","3.10.10","3.10.11","3.10.12","3.10.13","3.10.14","3.10.15","3.10.16","3.10.17","3.10.18","3.10.2","3.10.3","3.10.5","3.10.6","3.10.7","3.10.8","3.10.9","3.11.0","3.11.1","3.11.2","3.11.3","3.11.4","3.11.5","3.11.6","3.11.7","3.11.8","3.12.0","3.12.1","3.12.2","3.12.3","3.13.0","3.13.1","3.13.10","3.13.11","3.13.12","3.13.13","3.13.14","3.13.15","3.13.16","3.13.17","3.13.18","3.13.19","3.13.2","3.13.20","3.13.21","3.13.22","3.13.23","3.13.3","3.13.4","3.13.5","3.13.6","3.13.7","3.13.8","3.13.9","3.14.0","3.14.1","3.14.2","3.14.3","3.15.0","3.15.1","3.16.0","3.16.1","3.16.10","3.16.11","3.16.12","3.16.13","3.16.14","3.16.15","3.16.16","3.16.17","3.16.2","3.16.3","3.16.4","3.16.5","3.16.6","3.16.7","3.16.8","3.16.9","3.17.0","3.17.1","3.2.0","3.2.1","3.3.0","3.3.1","3.3.10","3.3.2","3.3.3","3.3.4","3.3.5","3.3.6","3.3.7","3.3.8","3.3.9","3.4.0","3.5.0","3.5.1","3.6.0","3.6.10","3.6.11","3.6.12","3.6.13","3.6.2","3.6.3","3.6.4","3.6.5","3.6.6","3.6.7","3.6.8","3.6.9","3.7.0","3.7.1","3.7.10","3.7.11","3.7.12","3.7.2","3.7.3","3.7.4","3.7.5","3.7.6","3.7.7","3.7.8","3.7.9","3.8.0","3.8.1","3.9.0","3.9.1","3.9.2"]},{"source":"osv","ecosystem":"Ubuntu:14.04:LTS","package":"ruby-oj","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.0.10-1","2.1.4-1","2.4.0-1","2.5.3-1"]},{"source":"osv","ecosystem":"Ubuntu:16.04:LTS","package":"ruby-oj","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.12.10-3","2.12.10-3build1","2.12.10-4","2.12.10-4build1"]},{"source":"osv","ecosystem":"Ubuntu:18.04:LTS","package":"ruby-oj","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.17.4-1","3.4.0-1","3.4.0-1build1"]},{"source":"osv","ecosystem":"Ubuntu:20.04:LTS","package":"ruby-oj","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.8.1-1","3.9.1-1","3.9.2-1","3.10.1-1","3.10.1-1build1"]},{"source":"osv","ecosystem":"Ubuntu:22.04:LTS","package":"ruby-oj","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.11.0-1","3.13.7-1","3.13.7-1build1","3.13.9-1","3.13.9-1build1"]},{"source":"osv","ecosystem":"Ubuntu:24.04:LTS","package":"ruby-oj","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.15.0-1","3.16.1-1","3.16.3-1","3.16.3-1build1","3.16.3-1build2"]},{"source":"osv","ecosystem":"Ubuntu:25.10","package":"ruby-oj","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.16.3-1build3"]},{"source":"osv","ecosystem":"Ubuntu:26.10","package":"ruby-oj","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.16.15-1","3.17.0-1","3.17.1-1","3.17.3-1","3.17.4-1"]},{"source":"osv","ecosystem":"Ubuntu:26.04:LTS","package":"ruby-oj","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.16.3-1build3","3.16.12-1","3.16.15-1"]}],"products":[{"vendor":"ohler55","product":"oj"}],"references":[{"url":"https://github.com/ohler55/oj/security/advisories/GHSA-475m-ph3x-64gp","tags":["x_refsource_CONFIRM","exploit","web","report"]},{"url":"https://github.com/advisories/GHSA-475m-ph3x-64gp"},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-54903","tags":["advisory"]},{"url":"https://github.com/ohler55/oj","tags":["package"]},{"url":"https://ubuntu.com/security/CVE-2026-54903","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-54903","tags":["report"]}],"sources":{"cve":[{"id":"CVE-2026-54903","title":"Oj: Integer Overflow in Oj.load 2GB String Handling","description":"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.","status":"published","published":"2026-06-30T23:42:06.777Z","modified":"2026-07-01T12:43:48.523Z","cvss":[{"version":"4.0","score":6.3,"vector":"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","level":"medium","assessor":"cna"}],"cwes":["CWE-190"],"updated_at":"2026-11-02T13:37:58.613221Z"}],"euvd":[{"id":"EUVD-2026-40858","description":"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.","status":"published","published":"2026-06-30T23:42:06Z","modified":"2026-07-01T12:43:48Z","cvss":[{"version":"4.0","score":6.3,"vector":"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","level":"medium"}],"updated_at":"2026-11-02T18:20:20.297775Z"}],"ghsa":[{"id":"GHSA-475m-ph3x-64gp","title":"Oj: Integer Overflow in Oj.load 2GB String Handling","description":"### Summary\n\n`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.\n\n### Version\n\n- **Software**: oj gem\n- **Affected**: all versions with `ext/oj/buf.h` and `ext/oj/parse.c`\n- **Latest tested**: 3.17.1 (confirmed present)\n\n### Details\n\n`ext/oj/buf.h`, line 61:\n\n```c\ninline static void buf_append_string(Buf buf, const char *s, size_t slen) {\n    // ...\n    memcpy(buf-\u003etail, s, slen);   // slen derived from 32-bit int that wrapped negative\n```\n\nIn `parse.c`, escape sequence handling computes the remaining string length as an `int`:\n\n```c\n// parse.c:402 (read_escaped_str)\nint  slen = (int)(s - str);   // ← wraps to negative when string \u003e 2 GB\nbuf_append_string(buf, str, (size_t)slen);  // ← (size_t)(-2147483648) = 0x80000000...\n```\n\nASAN report:\n```\n==399019==ERROR: AddressSanitizer: negative-size-param: (size=-2147483648)\n    #0 __asan_memcpy\n    #1 buf_append_string  /ext/oj/buf.h:61\n    #2 read_escaped_str   /ext/oj/parse.c:402\n    #3 read_str           /ext/oj/parse.c:542\n    #4 oj_parse2          /ext/oj/parse.c:882\n    #5 oj_pi_parse        /ext/oj/parse.c:1256\n    #6 oj_object_parse    /ext/oj/object.c:701\n    #7 load               /ext/oj/oj.c:1259\n0x7f5a26ff0801 is located 1 bytes inside of 2147483657-byte region [0x7f5a26ff0800, 0x7f5aa6ff0809)\n```\n\n### Reproduce\n\n```ruby\nrequire 'oj'\nn = 1 \u003c\u003c 31                         # 2 GB\njson = '\"' + ('A' * n) + 'A\"'  # \u003e2GB JSON string with a trailing escape\nOj.load(json)\n```","status":"published","published":"2026-06-19T20:47:31Z","modified":"2026-06-19T20:47:33Z","cvss":[{"version":"4.0","score":8.7,"vector":"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","level":"high"}],"cwes":["CWE-190"],"updated_at":"2026-11-02T14:40:31.656952Z"}],"nvd":[{"id":"CVE-2026-54903","description":"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.","status":"published","published":"2026-07-01T00:16:33.707Z","modified":"2026-10-25T17:10:00.197Z","cvss":[{"version":"4.0","score":6.3,"vector":"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","level":"medium","assessor":"secondary"}],"cwes":["CWE-190"],"updated_at":"2026-11-02T14:12:27.199837Z"}],"osv":[{"id":"DEBIAN-CVE-2026-54903","description":"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.","status":"published","published":"2026-07-01T00:16:33.707Z","modified":"2026-10-26T11:47:25.363092911Z","cvss":[{"version":"4.0","score":6.3,"vector":"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","level":"medium"}],"updated_at":"2026-11-02T15:45:57.236551Z"},{"id":"GHSA-475m-ph3x-64gp","title":"Oj: Integer Overflow in Oj.load 2GB String Handling","description":"### Summary\n\n`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.\n\n### Version\n\n- **Software**: oj gem\n- **Affected**: all versions with `ext/oj/buf.h` and `ext/oj/parse.c`\n- **Latest tested**: 3.17.1 (confirmed present)\n\n### Details\n\n`ext/oj/buf.h`, line 61:\n\n```c\ninline static void buf_append_string(Buf buf, const char *s, size_t slen) {\n    // ...\n    memcpy(buf-\u003etail, s, slen);   // slen derived from 32-bit int that wrapped negative\n```\n\nIn `parse.c`, escape sequence handling computes the remaining string length as an `int`:\n\n```c\n// parse.c:402 (read_escaped_str)\nint  slen = (int)(s - str);   // ← wraps to negative when string \u003e 2 GB\nbuf_append_string(buf, str, (size_t)slen);  // ← (size_t)(-2147483648) = 0x80000000...\n```\n\nASAN report:\n```\n==399019==ERROR: AddressSanitizer: negative-size-param: (size=-2147483648)\n    #0 __asan_memcpy\n    #1 buf_append_string  /ext/oj/buf.h:61\n    #2 read_escaped_str   /ext/oj/parse.c:402\n    #3 read_str           /ext/oj/parse.c:542\n    #4 oj_parse2          /ext/oj/parse.c:882\n    #5 oj_pi_parse        /ext/oj/parse.c:1256\n    #6 oj_object_parse    /ext/oj/object.c:701\n    #7 load               /ext/oj/oj.c:1259\n0x7f5a26ff0801 is located 1 bytes inside of 2147483657-byte region [0x7f5a26ff0800, 0x7f5aa6ff0809)\n```\n\n### Reproduce\n\n```ruby\nrequire 'oj'\nn = 1 \u003c\u003c 31                         # 2 GB\njson = '\"' + ('A' * n) + 'A\"'  # \u003e2GB JSON string with a trailing escape\nOj.load(json)\n```","status":"published","published":"2026-06-19T20:47:31Z","modified":"2026-09-10T03:51:07.824466317Z","cvss":[{"version":"4.0","score":8.7,"vector":"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","level":"high"}],"cwes":["CWE-190"],"updated_at":"2026-11-02T15:46:36.782754Z"},{"id":"UBUNTU-CVE-2026-54903","description":"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.","status":"published","published":"2026-07-01T00:16:00Z","modified":"2026-10-17T13:00:26.851131716Z","cvss":[{"version":"4.0","score":6.3,"vector":"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","level":"medium"}],"updated_at":"2026-11-02T16:56:41.382716Z"}]}}
