{"id":"CVE-2026-71847","aliases":["DEBIAN-CVE-2026-71847","EUVD-2026-54576","GHSA-9hj4-r449-hfvc","SUSE-SU-2026:24195-1","SUSE-SU-2026:24250-1","UBUNTU-CVE-2026-71847","openSUSE-SU-2026:12153-1","openSUSE-SU-2026:22068-1"],"status":"published","title":"Ruby JSON: JSON::ResumableParser#partial_value dereferences a freed input buffer and crashes on truncated duplicate-key streams","description":"Ruby JSON is a JSON implementation for Ruby. From 2.20.0 until 2.21.2, Ruby's JSON native C extension clears the consumed JSON::ResumableParser input buffer but leaves state.start, state.cursor, and state.end pointing into released storage. When partial_value reconstructs an incomplete object containing duplicate keys, the duplicate-key warning path calls cursor_position, which dereferences those stale pointers. This results in a heap-use-after-free and can terminate the Ruby process. An attacker who can supply JSON stream data to an application using JSON::ResumableParser may cause process termination when the application calls partial_value on incomplete attacker-controlled input containing duplicate object keys. This issue has been fixed in version 2.21.2.","severity":{"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","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00428,"percentile":0.3731,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-416"],"published":"2026-08-07T18:31:28Z","modified":"2026-10-28T02:31:00Z","fixes":[{"ecosystem":"RubyGems","package":"json","fixed_in":["2.21.2"],"sources":["ghsa","osv"]},{"ecosystem":"Debian:14","package":"ruby-json","fixed_in":["2.21.2+dfsg-1"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"RubyGems","package":"json","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.20.0"},{"last_affected":"2.21.1"},{"fixed":"2.21.2"}]}]},{"source":"osv","ecosystem":"Debian:13","package":"ruby-json","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.15.2+dfsg-1","2.18.1+dfsg-1","2.19.1+dfsg-1","2.19.2+dfsg-1","2.19.4+dfsg-1","2.19.9+dfsg-1","2.21.1+dfsg-1","2.21.2+dfsg-1","2.9.1+dfsg-1","3.0.2+dfsg-1"]},{"source":"osv","ecosystem":"Debian:14","package":"ruby-json","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.21.2+dfsg-1"}]}],"versions":["2.15.2+dfsg-1","2.18.1+dfsg-1","2.19.1+dfsg-1","2.19.2+dfsg-1","2.19.4+dfsg-1","2.19.9+dfsg-1","2.21.1+dfsg-1","2.9.1+dfsg-1"]},{"source":"osv","ecosystem":"RubyGems","package":"json","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.20.0"},{"fixed":"2.21.2"}]}],"versions":["2.20.0","2.21.0","2.21.1"]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Availability Extension 16.0","package":"hawk2","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.2+git.1788518533.7d4dadd6-160000.1.1"}]}],"bundled":7},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server for SAP applications 16.0","package":"hawk2","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.2+git.1788518533.7d4dadd6-160000.1.1"}]}],"bundled":7},{"source":"osv","ecosystem":"Ubuntu:14.04:LTS","package":"ruby-json","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.8.0-1","1.8.0-1build1"]},{"source":"osv","ecosystem":"Ubuntu:16.04:LTS","package":"ruby-json","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.8.3-1build1","1.8.3-1build2","1.8.3-1build4"]},{"source":"osv","ecosystem":"Ubuntu:18.04:LTS","package":"ruby-json","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.1.0+dfsg-1","2.1.0+dfsg-1ubuntu2","2.1.0+dfsg-1ubuntu3","2.1.0+dfsg-2"]},{"source":"osv","ecosystem":"Ubuntu:20.04:LTS","package":"ruby-json","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.1.0+dfsg-2","2.3.0+dfsg-1","2.3.0+dfsg-1build1"]},{"source":"osv","ecosystem":"Ubuntu:22.04:LTS","package":"ruby-json","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.3.0+dfsg-1build1","2.5.1+dfsg-2","2.5.1+dfsg-2build1"]},{"source":"osv","ecosystem":"Ubuntu:24.04:LTS","package":"ruby-json","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.6.3+dfsg-1build2","2.6.3+dfsg-1build3","2.6.3+dfsg-1build4"]},{"source":"osv","ecosystem":"Ubuntu:26.10","package":"ruby-json","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.18.1+dfsg-1","2.21.1+dfsg-1","2.21.2+dfsg-1"]},{"source":"osv","ecosystem":"Ubuntu:26.04:LTS","package":"ruby-json","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.9.1+dfsg-1","2.15.2+dfsg-1","2.18.1+dfsg-1"]},{"source":"osv","ecosystem":"openSUSE:Tumbleweed","package":"hawk2","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.2+git.1792148770.648dcddb-1.1"}]}],"bundled":7},{"source":"osv","ecosystem":"openSUSE:Leap 16.0","package":"hawk2","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.2+git.1788518533.7d4dadd6-160000.1.1"}]}],"bundled":7}],"products":[{"vendor":"ruby","product":"json"}],"references":[{"url":"https://github.com/ruby/json/security/advisories/GHSA-9hj4-r449-hfvc","tags":["x_refsource_CONFIRM","exploit","advisory","web","report"]},{"url":"https://github.com/advisories/GHSA-9hj4-r449-hfvc"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/71xxx/CVE-2026-71847.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-71847","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-71847","tags":["advisory"]},{"url":"https://github.com/ruby/json","tags":["package"]},{"url":"https://www.suse.com/support/update/announcement/2026/suse-su-202624195-1/","tags":["advisory"]},{"url":"https://bugzilla.suse.com/1268996","tags":["report"]},{"url":"https://bugzilla.suse.com/1273348","tags":["report"]},{"url":"https://bugzilla.suse.com/1274860","tags":["report"]},{"url":"https://bugzilla.suse.com/1275019","tags":["report"]},{"url":"https://bugzilla.suse.com/1275179","tags":["report"]},{"url":"https://bugzilla.suse.com/1275183","tags":["report"]},{"url":"https://bugzilla.suse.com/1275188","tags":["report"]},{"url":"https://bugzilla.suse.com/1275200","tags":["report"]},{"url":"https://bugzilla.suse.com/1275213","tags":["report"]},{"url":"https://www.suse.com/security/cve/CVE-2026-42246","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-66066","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-71847","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-73490","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-73491","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-73492","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-73648","tags":["web"]},{"url":"https://www.suse.com/support/update/announcement/2026/suse-su-202624250-1/","tags":["advisory"]},{"url":"https://ubuntu.com/security/CVE-2026-71847","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-71847","tags":["report"]},{"url":"","tags":["advisory"]}],"sources":{"cve":[{"id":"CVE-2026-71847","title":"Ruby JSON: JSON::ResumableParser#partial_value dereferences a freed input buffer and crashes on truncated duplicate-key streams","description":"Ruby JSON is a JSON implementation for Ruby. From 2.20.0 until 2.21.2, Ruby's JSON native C extension clears the consumed JSON::ResumableParser input buffer but leaves state.start, state.cursor, and state.end pointing into released storage. When partial_value reconstructs an incomplete object containing duplicate keys, the duplicate-key warning path calls cursor_position, which dereferences those stale pointers. This results in a heap-use-after-free and can terminate the Ruby process. An attacker who can supply JSON stream data to an application using JSON::ResumableParser may cause process termination when the application calls partial_value on incomplete attacker-controlled input containing duplicate object keys. This issue has been fixed in version 2.21.2.","status":"published","published":"2026-08-07T18:31:28.507Z","modified":"2026-08-07T21:02:06.463Z","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","assessor":"cna"}],"cwes":["CWE-416"],"updated_at":"2026-11-02T14:19:49.559463Z"}],"euvd":[{"id":"EUVD-2026-54576","description":"Ruby JSON is a JSON implementation for Ruby. From 2.20.0 until 2.21.2, Ruby's JSON native C extension clears the consumed JSON::ResumableParser input buffer but leaves state.start, state.cursor, and state.end pointing into released storage. When partial_value reconstructs an incomplete object containing duplicate keys, the duplicate-key warning path calls cursor_position, which dereferences those stale pointers. This results in a heap-use-after-free and can terminate the Ruby process. An attacker who can supply JSON stream data to an application using JSON::ResumableParser may cause process termination when the application calls partial_value on incomplete attacker-controlled input containing duplicate object keys. This issue has been fixed in version 2.21.2.","status":"published","published":"2026-08-07T18:31:28Z","modified":"2026-08-07T21:02:06Z","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"}],"updated_at":"2026-11-02T18:02:06.573967Z"}],"ghsa":[{"id":"GHSA-9hj4-r449-hfvc","title":"Ruby JSON: JSON::ResumableParser#partial_value dereferences a freed input buffer and crashes on truncated duplicate-key streams","description":"### Summary\n\nRuby's JSON native C extension clears the consumed `JSON::ResumableParser` input buffer but leaves `state.start`, `state.cursor`, and `state.end` pointing into released storage.\n\nWhen `partial_value` reconstructs an incomplete object containing duplicate keys, the duplicate-key warning path calls `cursor_position`, which dereferences those stale pointers. This results in a heap-use-after-free and can terminate the Ruby process.\n\nAn attacker who can supply JSON stream data to an application using `JSON::ResumableParser` may cause process termination when the application calls `partial_value` on incomplete attacker-controlled input containing duplicate object keys.\n\nThe issue was reproduced in the native C extension from the official RubyGems releases:\n\n* JSON 2.20.0\n* JSON 2.21.0\n* JSON 2.21.1\n\nThe attached evidence demonstrates:\n\n* an AddressSanitizer-confirmed heap-use-after-free;\n* a native `SIGSEGV` using the official JSON 2.21.1 RubyGem;\n* an end-to-end loopback TCP attacker/victim reproduction;\n* four differential controls;\n* successful execution after applying a tested patch control.\n\nThis was originally reported privately through Ruby's HackerOne program as report `#3867755`. A Ruby maintainer independently confirmed reproduction of the ASan failure and requested that further coordination continue through this private advisory.\n\nNo code execution or information disclosure is claimed.\n\n### Details\n\nThe affected source is:\n\n```text\next/json/ext/parser/parser.c\n```\n\nThe vulnerable sequence in JSON 2.21.1 is:\n\n1. `cResumableParser_parse` reaches the end of the current input buffer.\n2. It calls `json_str_clear(parser-\u003ebuffer)`.\n3. It sets `parser-\u003ebuffer = Qfalse`.\n4. The parser-state pointers into the released buffer are not reset.\n5. `partial_value` makes a shallow copy of the parser state.\n6. Reconstructing an incomplete object containing duplicate keys reaches the duplicate-key warning path.\n7. `cursor_position` walks through the stale input pointers and reads released memory.\n\nRelevant source locations:\n\n* Buffer release:\n  https://github.com/ruby/json/blob/fd61def38b9bb859fee7eec8e7d3143600e5b347/ext/json/ext/parser/parser.c#L2562-L2569\n\n* Parser-state copy:\n  https://github.com/ruby/json/blob/fd61def38b9bb859fee7eec8e7d3143600e5b347/ext/json/ext/parser/parser.c#L2647-L2654\n\n* Stale-pointer read in `cursor_position`:\n  https://github.com/ruby/json/blob/fd61def38b9bb859fee7eec8e7d3143600e5b347/ext/json/ext/parser/parser.c#L590-L628\n\n* Duplicate-key handling path:\n  https://github.com/ruby/json/blob/fd61def38b9bb859fee7eec8e7d3143600e5b347/ext/json/ext/parser/parser.c#L1196-L1255\n\nWhen input is supplied to the resumable parser, the parser state stores direct pointers into the backing Ruby string:\n\n```c\nRSTRING_GETMEM(parser-\u003ebuffer, start, len);\nparser-\u003estate.start = start;\nparser-\u003estate.end = start + len;\nparser-\u003estate.cursor = parser-\u003estate.start + offset;\n```\n\nAfter the current buffer has been consumed, `cResumableParser_parse` clears the string and removes the parser's reference to it:\n\n```c\nif (eos(\u0026parser-\u003estate)) {\n    json_str_clear(parser-\u003ebuffer);\n    parser-\u003ebuffer = Qfalse;\n}\n```\n\nThis path does not invalidate or replace:\n\n```text\nparser-\u003estate.start\nparser-\u003estate.cursor\nparser-\u003estate.end\n```\n\n`JSON::ResumableParser#partial_value` subsequently makes a shallow copy of the parser structure:\n\n```c\nJSON_ResumableParser *original_parser = cResumableParser_get(self);\nJSON_ResumableParser parser = *original_parser;\n```\n\nWhen the partial object contains duplicate keys, reconstruction follows this call path:\n\n```text\ncResumableParser_partial_value_body\n  -\u003e json_decode_object\n  -\u003e json_on_duplicate_key\n  -\u003e emit_duplicate_key_warning\n  -\u003e emit_parse_warning\n  -\u003e cursor_position\n```\n\n`cursor_position` then reads through pointers that may refer to released storage.\n\nAddressSanitizer reports:\n\n```text\nERROR: AddressSanitizer: heap-use-after-free\ncursor_position at parser.c:604\nfreed by cResumableParser_parse at parser.c:2567\n```\n\nThe reproducer follows the normal resumable-parser API sequence:\n\n```ruby\nparser \u003c\u003c chunk\nparser.parse\nparser \u003c\u003c next_chunk\nparser.parse\nparser.partial_value\n```\n\nThe issue does not require:\n\n* an application-defined callback;\n* explicit garbage collection;\n* parser reentrancy;\n* custom parser options;\n* an attacker-supplied Ruby object;\n* manual modification of native parser state.\n\nThe release-build crash reproduced on JSON 2.20.0, 2.21.0, and 2.21.1.\n\nThis report covers the native C-extension implementation. The separate Java-platform implementation was not tested and is not claimed to be affected.\n\n### PoC\n\nThe complete evidence bundle is attached as:\n\n```text\nruby-json-resumable-partial-value-uaf-evidence-20260716.zip\n```\n\nSHA-256:\n\n```text\n07bf8d47b115e45d6145d0447ab6c1c0255e4a7e9b2fb55c3c9a0e24406134ac\n```\n\n#### Requirements\n\n* Linux\n* Ruby with development headers\n* C compiler\n* `make`\n* RubyGems\n\n#### Release-build, network, and differential reproduction\n\nExtract the attachment:\n\n```sh\nunzip ruby-json-resumable-partial-value-uaf-evidence-20260716.zip\ncd ruby-json-resumable-partial-value-uaf-evidence-20260716\n```\n\nRun the official JSON 2.21.1 release-build proof, loopback network proof, and differential controls:\n\n```sh\n./run_exact_2211.sh\n```\n\nExpected primary results:\n\n```text\nrelease_exit=139\nnetwork_victim_exit=139\nnetwork_result=PASS\nresult=PASS\n```\n\nThe following four differential controls must also report `result=PASS`:\n\n```text\nunique_key\nduplicate_allowed\nno_partial\ncomplete_document\n```\n\nThe release-build crash stack includes:\n\n```text\ncursor_position\nemit_parse_warning\nemit_duplicate_key_warning\njson_decode_object\ncResumableParser_partial_value_body\n```\n\n#### AddressSanitizer reproduction\n\nRun:\n\n```sh\n./run_asan.sh\n```\n\nExpected vulnerable result:\n\n```text\nasan_vulnerable_exit=134\nERROR: AddressSanitizer: heap-use-after-free\ncursor_position at parser.c:604\nfreed by cResumableParser_parse at parser.c:2567\n```\n\nExpected patched-control result:\n\n```text\nasan_patched_exit=0\nasan_result=PASS\n```\n\n#### Affected-version matrix\n\nThe release-build crash was reproduced three times for each of the following official RubyGems releases:\n\n```text\njson 2.20.0\njson 2.21.0\njson 2.21.1\n```\n\nAdditional evidence is included in:\n\n```text\nartifacts/exact-2211-e2e.txt\nartifacts/asan-and-patched-control.txt\nartifacts/version-matrix.txt\nartifacts/source-and-release-verification.txt\nsource-slices.txt\nprior-art.md\npatch-control.diff\n```\n\n### Impact\n\nThis is a use-after-free that can result in native Ruby process termination.\n\nAn attacker must be able to supply JSON stream data to an application that:\n\n1. uses `JSON::ResumableParser`;\n2. processes attacker-controlled streaming input;\n3. calls `partial_value` after parsing an incomplete document containing duplicate object keys.\n\nIn network-facing deployments meeting these conditions, an attacker can cause process termination and denial of service.\n\nThe release-build crash was reproduced consistently in the tested Linux environment. The AddressSanitizer result confirms the underlying heap-use-after-free independently of normal allocator behavior.\n\nThe demonstrated impact is:\n\n```text\nDenial of service through native process termination\n```\n\nNo confidentiality impact, integrity impact, arbitrary code execution, or information disclosure is claimed.\n\n### Suggested remediation\n\nBefore clearing or releasing the resumable parser's input buffer, invalidate or replace every parser-state pointer that refers to the buffer's backing storage.\n\nDelayed code paths such as duplicate-key warning generation must not calculate cursor positions using pointers after the corresponding buffer has been released.\n\nThe attached `patch-control.diff` demonstrates one tested control and is provided for validation rather than as a required final implementation.","status":"published","published":"2026-08-07T18:33:12Z","modified":"2026-08-07T18:33:13Z","cwes":["CWE-416"],"updated_at":"2026-11-02T14:40:58.888637Z"}],"nvd":[{"id":"CVE-2026-71847","description":"Ruby JSON is a JSON implementation for Ruby. From 2.20.0 until 2.21.2, Ruby's JSON native C extension clears the consumed JSON::ResumableParser input buffer but leaves state.start, state.cursor, and state.end pointing into released storage. When partial_value reconstructs an incomplete object containing duplicate keys, the duplicate-key warning path calls cursor_position, which dereferences those stale pointers. This results in a heap-use-after-free and can terminate the Ruby process. An attacker who can supply JSON stream data to an application using JSON::ResumableParser may cause process termination when the application calls partial_value on incomplete attacker-controlled input containing duplicate object keys. This issue has been fixed in version 2.21.2.","status":"published","published":"2026-08-07T19:18:53.807Z","modified":"2026-10-24T15:10:00.19Z","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/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":"high","assessor":"secondary"}],"cwes":["CWE-416"],"updated_at":"2026-11-02T14:12:35.743275Z"}],"osv":[{"id":"CVE-2026-71847","title":"Ruby JSON: JSON::ResumableParser#partial_value dereferences a freed input buffer and crashes on truncated duplicate-key streams","description":"Ruby JSON is a JSON implementation for Ruby. From 2.20.0 until 2.21.2, Ruby's JSON native C extension clears the consumed JSON::ResumableParser input buffer but leaves state.start, state.cursor, and state.end pointing into released storage. When partial_value reconstructs an incomplete object containing duplicate keys, the duplicate-key warning path calls cursor_position, which dereferences those stale pointers. This results in a heap-use-after-free and can terminate the Ruby process. An attacker who can supply JSON stream data to an application using JSON::ResumableParser may cause process termination when the application calls partial_value on incomplete attacker-controlled input containing duplicate object keys. This issue has been fixed in version 2.21.2.","status":"published","published":"2026-08-07T18:31:28.507Z","modified":"2026-10-28T02:31:00.670432185Z","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-416"],"updated_at":"2026-11-02T15:45:15.511448Z"},{"id":"DEBIAN-CVE-2026-71847","description":"Ruby JSON is a JSON implementation for Ruby. From 2.20.0 until 2.21.2, Ruby's JSON native C extension clears the consumed JSON::ResumableParser input buffer but leaves state.start, state.cursor, and state.end pointing into released storage. When partial_value reconstructs an incomplete object containing duplicate keys, the duplicate-key warning path calls cursor_position, which dereferences those stale pointers. This results in a heap-use-after-free and can terminate the Ruby process. An attacker who can supply JSON stream data to an application using JSON::ResumableParser may cause process termination when the application calls partial_value on incomplete attacker-controlled input containing duplicate object keys. This issue has been fixed in version 2.21.2.","status":"published","published":"2026-08-07T19:18:53.807Z","modified":"2026-10-04T15:00:08.047237999Z","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/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":"high"}],"updated_at":"2026-11-02T15:46:02.094661Z"},{"id":"UBUNTU-CVE-2026-71847","description":"Ruby JSON is a JSON implementation for Ruby. From 2.20.0 until 2.21.2, Ruby's JSON native C extension clears the consumed JSON::ResumableParser input buffer but leaves state.start, state.cursor, and state.end pointing into released storage. When partial_value reconstructs an incomplete object containing duplicate keys, the duplicate-key warning path calls cursor_position, which dereferences those stale pointers. This results in a heap-use-after-free and can terminate the Ruby process. An attacker who can supply JSON stream data to an application using JSON::ResumableParser may cause process termination when the application calls partial_value on incomplete attacker-controlled input containing duplicate object keys. This issue has been fixed in version 2.21.2.","status":"published","published":"2026-08-07T19:18:00Z","modified":"2026-10-17T13:00:47.114991238Z","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"}],"updated_at":"2026-11-02T16:57:03.035847Z"},{"id":"GHSA-9hj4-r449-hfvc","title":"Ruby JSON: JSON::ResumableParser#partial_value dereferences a freed input buffer and crashes on truncated duplicate-key streams","description":"### Summary\n\nRuby's JSON native C extension clears the consumed `JSON::ResumableParser` input buffer but leaves `state.start`, `state.cursor`, and `state.end` pointing into released storage.\n\nWhen `partial_value` reconstructs an incomplete object containing duplicate keys, the duplicate-key warning path calls `cursor_position`, which dereferences those stale pointers. This results in a heap-use-after-free and can terminate the Ruby process.\n\nAn attacker who can supply JSON stream data to an application using `JSON::ResumableParser` may cause process termination when the application calls `partial_value` on incomplete attacker-controlled input containing duplicate object keys.\n\nThe issue was reproduced in the native C extension from the official RubyGems releases:\n\n* JSON 2.20.0\n* JSON 2.21.0\n* JSON 2.21.1\n\nThe attached evidence demonstrates:\n\n* an AddressSanitizer-confirmed heap-use-after-free;\n* a native `SIGSEGV` using the official JSON 2.21.1 RubyGem;\n* an end-to-end loopback TCP attacker/victim reproduction;\n* four differential controls;\n* successful execution after applying a tested patch control.\n\nThis was originally reported privately through Ruby's HackerOne program as report `#3867755`. A Ruby maintainer independently confirmed reproduction of the ASan failure and requested that further coordination continue through this private advisory.\n\nNo code execution or information disclosure is claimed.\n\n### Details\n\nThe affected source is:\n\n```text\next/json/ext/parser/parser.c\n```\n\nThe vulnerable sequence in JSON 2.21.1 is:\n\n1. `cResumableParser_parse` reaches the end of the current input buffer.\n2. It calls `json_str_clear(parser-\u003ebuffer)`.\n3. It sets `parser-\u003ebuffer = Qfalse`.\n4. The parser-state pointers into the released buffer are not reset.\n5. `partial_value` makes a shallow copy of the parser state.\n6. Reconstructing an incomplete object containing duplicate keys reaches the duplicate-key warning path.\n7. `cursor_position` walks through the stale input pointers and reads released memory.\n\nRelevant source locations:\n\n* Buffer release:\n  https://github.com/ruby/json/blob/fd61def38b9bb859fee7eec8e7d3143600e5b347/ext/json/ext/parser/parser.c#L2562-L2569\n\n* Parser-state copy:\n  https://github.com/ruby/json/blob/fd61def38b9bb859fee7eec8e7d3143600e5b347/ext/json/ext/parser/parser.c#L2647-L2654\n\n* Stale-pointer read in `cursor_position`:\n  https://github.com/ruby/json/blob/fd61def38b9bb859fee7eec8e7d3143600e5b347/ext/json/ext/parser/parser.c#L590-L628\n\n* Duplicate-key handling path:\n  https://github.com/ruby/json/blob/fd61def38b9bb859fee7eec8e7d3143600e5b347/ext/json/ext/parser/parser.c#L1196-L1255\n\nWhen input is supplied to the resumable parser, the parser state stores direct pointers into the backing Ruby string:\n\n```c\nRSTRING_GETMEM(parser-\u003ebuffer, start, len);\nparser-\u003estate.start = start;\nparser-\u003estate.end = start + len;\nparser-\u003estate.cursor = parser-\u003estate.start + offset;\n```\n\nAfter the current buffer has been consumed, `cResumableParser_parse` clears the string and removes the parser's reference to it:\n\n```c\nif (eos(\u0026parser-\u003estate)) {\n    json_str_clear(parser-\u003ebuffer);\n    parser-\u003ebuffer = Qfalse;\n}\n```\n\nThis path does not invalidate or replace:\n\n```text\nparser-\u003estate.start\nparser-\u003estate.cursor\nparser-\u003estate.end\n```\n\n`JSON::ResumableParser#partial_value` subsequently makes a shallow copy of the parser structure:\n\n```c\nJSON_ResumableParser *original_parser = cResumableParser_get(self);\nJSON_ResumableParser parser = *original_parser;\n```\n\nWhen the partial object contains duplicate keys, reconstruction follows this call path:\n\n```text\ncResumableParser_partial_value_body\n  -\u003e json_decode_object\n  -\u003e json_on_duplicate_key\n  -\u003e emit_duplicate_key_warning\n  -\u003e emit_parse_warning\n  -\u003e cursor_position\n```\n\n`cursor_position` then reads through pointers that may refer to released storage.\n\nAddressSanitizer reports:\n\n```text\nERROR: AddressSanitizer: heap-use-after-free\ncursor_position at parser.c:604\nfreed by cResumableParser_parse at parser.c:2567\n```\n\nThe reproducer follows the normal resumable-parser API sequence:\n\n```ruby\nparser \u003c\u003c chunk\nparser.parse\nparser \u003c\u003c next_chunk\nparser.parse\nparser.partial_value\n```\n\nThe issue does not require:\n\n* an application-defined callback;\n* explicit garbage collection;\n* parser reentrancy;\n* custom parser options;\n* an attacker-supplied Ruby object;\n* manual modification of native parser state.\n\nThe release-build crash reproduced on JSON 2.20.0, 2.21.0, and 2.21.1.\n\nThis report covers the native C-extension implementation. The separate Java-platform implementation was not tested and is not claimed to be affected.\n\n### PoC\n\nThe complete evidence bundle is attached as:\n\n```text\nruby-json-resumable-partial-value-uaf-evidence-20260716.zip\n```\n\nSHA-256:\n\n```text\n07bf8d47b115e45d6145d0447ab6c1c0255e4a7e9b2fb55c3c9a0e24406134ac\n```\n\n#### Requirements\n\n* Linux\n* Ruby with development headers\n* C compiler\n* `make`\n* RubyGems\n\n#### Release-build, network, and differential reproduction\n\nExtract the attachment:\n\n```sh\nunzip ruby-json-resumable-partial-value-uaf-evidence-20260716.zip\ncd ruby-json-resumable-partial-value-uaf-evidence-20260716\n```\n\nRun the official JSON 2.21.1 release-build proof, loopback network proof, and differential controls:\n\n```sh\n./run_exact_2211.sh\n```\n\nExpected primary results:\n\n```text\nrelease_exit=139\nnetwork_victim_exit=139\nnetwork_result=PASS\nresult=PASS\n```\n\nThe following four differential controls must also report `result=PASS`:\n\n```text\nunique_key\nduplicate_allowed\nno_partial\ncomplete_document\n```\n\nThe release-build crash stack includes:\n\n```text\ncursor_position\nemit_parse_warning\nemit_duplicate_key_warning\njson_decode_object\ncResumableParser_partial_value_body\n```\n\n#### AddressSanitizer reproduction\n\nRun:\n\n```sh\n./run_asan.sh\n```\n\nExpected vulnerable result:\n\n```text\nasan_vulnerable_exit=134\nERROR: AddressSanitizer: heap-use-after-free\ncursor_position at parser.c:604\nfreed by cResumableParser_parse at parser.c:2567\n```\n\nExpected patched-control result:\n\n```text\nasan_patched_exit=0\nasan_result=PASS\n```\n\n#### Affected-version matrix\n\nThe release-build crash was reproduced three times for each of the following official RubyGems releases:\n\n```text\njson 2.20.0\njson 2.21.0\njson 2.21.1\n```\n\nAdditional evidence is included in:\n\n```text\nartifacts/exact-2211-e2e.txt\nartifacts/asan-and-patched-control.txt\nartifacts/version-matrix.txt\nartifacts/source-and-release-verification.txt\nsource-slices.txt\nprior-art.md\npatch-control.diff\n```\n\n### Impact\n\nThis is a use-after-free that can result in native Ruby process termination.\n\nAn attacker must be able to supply JSON stream data to an application that:\n\n1. uses `JSON::ResumableParser`;\n2. processes attacker-controlled streaming input;\n3. calls `partial_value` after parsing an incomplete document containing duplicate object keys.\n\nIn network-facing deployments meeting these conditions, an attacker can cause process termination and denial of service.\n\nThe release-build crash was reproduced consistently in the tested Linux environment. The AddressSanitizer result confirms the underlying heap-use-after-free independently of normal allocator behavior.\n\nThe demonstrated impact is:\n\n```text\nDenial of service through native process termination\n```\n\nNo confidentiality impact, integrity impact, arbitrary code execution, or information disclosure is claimed.\n\n### Suggested remediation\n\nBefore clearing or releasing the resumable parser's input buffer, invalidate or replace every parser-state pointer that refers to the buffer's backing storage.\n\nDelayed code paths such as duplicate-key warning generation must not calculate cursor positions using pointers after the corresponding buffer has been released.\n\nThe attached `patch-control.diff` demonstrates one tested control and is provided for validation rather than as a required final implementation.","status":"published","published":"2026-08-07T18:33:12Z","modified":"2026-09-10T03:51:13.782635464Z","cwes":["CWE-416"],"updated_at":"2026-11-02T15:46:43.875515Z"},{"id":"openSUSE-SU-2026:12153-1","title":"hawk2-2.7.2+git.1792148770.648dcddb-1.1 on GA media","description":"These are all security issues fixed in the hawk2-2.7.2+git.1792148770.648dcddb-1.1 package on the GA media of openSUSE Tumbleweed.","status":"published","published":"2026-10-16T00:00:00Z","modified":"2026-10-17T10:00:04.120583882Z","updated_at":"2026-11-02T16:58:40.245664Z"},{"id":"openSUSE-SU-2026:22068-1","title":"Security update for hawk2","description":"This update for hawk2 fixes the following issues:\n\n- CVE-2026-42246: net-imap: MITM attacker can cause Net::IMAP#starttls to return successfully, without starting TLS\n  (bsc#1268996).\n- CVE-2026-66066: unsafe image processing operations on untrusted uploads can allow arbitrary file reading and remote\n  code execution (bsc#1273348).\n- CVE-2026-71847: json: heap use-after free in JSON::ResumableParser partial_value can lead to crash on truncated\n  duplicate-key streams (bsc#1275213).\n- CVE-2026-73490: loofah: improper handling of SVG attributes in the HTML5 sanitizer allows bypass of local-reference\n  restrictions (bsc#1275179).\n- CVE-2026-73491: loofah: improper handling of javascript: URIs can lead to XSS (bsc#1275183).\n- CVE-2026-73492: loofah: improper handling of javascript: and vbscript: URIs can lead to XSS (bsc#1275188).\n- CVE-2026-73648: rails-html-sanitizer: cross-site scripting is possible when the sanitizer is configured to allow\n  certain SVG reference elements (bsc#1275200).\n\nChanges for hawk2:\n\n- Update to version 2.7.2+git.1788518533.7d4dadd6 (bsc#1275019):\n * Test: give sle15 more time when choosing between sle15 and sle16\n * Dev: bump jQuery version to 4.0.0\n * Dev: bump jQuery version to 3.5.0\n * Dev: bump jQuery version to 2.2.4\n * Test: update the e2e test for the change allowing custom parameters\n * Dev: enable custom Parameters and Meta Attributes (bsc#1274860)\n * CI/CD: update hawk examiner entry point\n * Test: enable test_add_clone against hawk-apiserver verion 0.2.1\n * Test: fix SyntaxWarning: invalid escape sequence '\\|'\n * Test: make the tests compatible against hawk-apiserver ver0.2.0\n","status":"published","published":"2026-10-09T10:01:26Z","modified":"2026-10-19T17:23:11.651310245Z","updated_at":"2026-11-02T16:58:42.426393Z"},{"id":"SUSE-SU-2026:24195-1","title":"Security update for hawk2","description":"This update for hawk2 fixes the following issues:\n\n- CVE-2026-42246: net-imap: MITM attacker can cause Net::IMAP#starttls to return successfully, without starting TLS\n  (bsc#1268996).\n- CVE-2026-66066: unsafe image processing operations on untrusted uploads can allow arbitrary file reading and remote\n  code execution (bsc#1273348).\n- CVE-2026-71847: json: heap use-after free in JSON::ResumableParser partial_value can lead to crash on truncated\n  duplicate-key streams (bsc#1275213).\n- CVE-2026-73490: loofah: improper handling of SVG attributes in the HTML5 sanitizer allows bypass of local-reference\n  restrictions (bsc#1275179).\n- CVE-2026-73491: loofah: improper handling of javascript: URIs can lead to XSS (bsc#1275183).\n- CVE-2026-73492: loofah: improper handling of javascript: and vbscript: URIs can lead to XSS (bsc#1275188).\n- CVE-2026-73648: rails-html-sanitizer: cross-site scripting is possible when the sanitizer is configured to allow\n  certain SVG reference elements (bsc#1275200).\n\nChanges for hawk2:\n\n- Update to version 2.7.2+git.1788518533.7d4dadd6 (bsc#1275019):\n * Test: give sle15 more time when choosing between sle15 and sle16\n * Dev: bump jQuery version to 4.0.0\n * Dev: bump jQuery version to 3.5.0\n * Dev: bump jQuery version to 2.2.4\n * Test: update the e2e test for the change allowing custom parameters\n * Dev: enable custom Parameters and Meta Attributes (bsc#1274860)\n * CI/CD: update hawk examiner entry point\n * Test: enable test_add_clone against hawk-apiserver verion 0.2.1\n * Test: fix SyntaxWarning: invalid escape sequence '\\|'\n * Test: make the tests compatible against hawk-apiserver ver0.2.0\n","status":"published","published":"2026-10-09T10:11:39Z","modified":"2026-10-21T17:23:09.534601518Z","updated_at":"2026-11-02T15:54:04.519245Z"},{"id":"SUSE-SU-2026:24250-1","title":"Security update for hawk2","description":"This update for hawk2 fixes the following issues:\n\n- CVE-2026-42246: net-imap: MITM attacker can cause Net::IMAP#starttls to return successfully, without starting TLS\n  (bsc#1268996).\n- CVE-2026-66066: unsafe image processing operations on untrusted uploads can allow arbitrary file reading and remote\n  code execution (bsc#1273348).\n- CVE-2026-71847: json: heap use-after free in JSON::ResumableParser partial_value can lead to crash on truncated\n  duplicate-key streams (bsc#1275213).\n- CVE-2026-73490: loofah: improper handling of SVG attributes in the HTML5 sanitizer allows bypass of local-reference\n  restrictions (bsc#1275179).\n- CVE-2026-73491: loofah: improper handling of javascript: URIs can lead to XSS (bsc#1275183).\n- CVE-2026-73492: loofah: improper handling of javascript: and vbscript: URIs can lead to XSS (bsc#1275188).\n- CVE-2026-73648: rails-html-sanitizer: cross-site scripting is possible when the sanitizer is configured to allow\n  certain SVG reference elements (bsc#1275200).\n\nChanges for hawk2:\n\n- Update to version 2.7.2+git.1788518533.7d4dadd6 (bsc#1275019):\n * Test: give sle15 more time when choosing between sle15 and sle16\n * Dev: bump jQuery version to 4.0.0\n * Dev: bump jQuery version to 3.5.0\n * Dev: bump jQuery version to 2.2.4\n * Test: update the e2e test for the change allowing custom parameters\n * Dev: enable custom Parameters and Meta Attributes (bsc#1274860)\n * CI/CD: update hawk examiner entry point\n * Test: enable test_add_clone against hawk-apiserver verion 0.2.1\n * Test: fix SyntaxWarning: invalid escape sequence '\\|'\n * Test: make the tests compatible against hawk-apiserver ver0.2.0\n","status":"published","published":"2026-10-09T10:10:52Z","modified":"2026-10-21T17:23:12.551796041Z","updated_at":"2026-11-02T15:54:04.519245Z"}]}}
