CWE-416
AllowedUse After Free
Abstraction: Variant · Status: Stable
The product reuses or references memory after it has been freed. At some point afterward, the memory may be allocated again and saved in another pointer, while the original pointer references a location somewhere within the new allocation. Any operations using the original pointer are no longer valid because the memory "belongs" to the code that operates on the new pointer.
9821 vulnerabilities reference this CWE, most recent first.
GHSA-Q262-3HFR-F5Q4
Vulnerability from github – Published: 2024-05-08 03:30 – Updated: 2025-04-12 00:30A race condition leading to a stack use-after-free flaw was found in libvirt. Due to a bad assumption in the virNetClientIOEventLoop() method, the data pointer to a stack-allocated virNetClientIOEventData structure ended up being used in the virNetClientIOEventFD callback while the data pointer's stack frame was concurrently being "freed" when returning from virNetClientIOEventLoop(). The 'virtproxyd' daemon can be used to trigger requests. If libvirt is configured with fine-grained access control, this issue, in theory, allows a user to escape their otherwise limited access. This flaw allows a local, unprivileged user to access virtproxyd without authenticating. Remote users would need to authenticate before they could access it.
{
"affected": [],
"aliases": [
"CVE-2024-4418"
],
"database_specific": {
"cwe_ids": [
"CWE-416",
"CWE-562"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-05-08T03:15:07Z",
"severity": "MODERATE"
},
"details": "A race condition leading to a stack use-after-free flaw was found in libvirt. Due to a bad assumption in the virNetClientIOEventLoop() method, the `data` pointer to a stack-allocated virNetClientIOEventData structure ended up being used in the virNetClientIOEventFD callback while the data pointer\u0027s stack frame was concurrently being \"freed\" when returning from virNetClientIOEventLoop(). The \u0027virtproxyd\u0027 daemon can be used to trigger requests. If libvirt is configured with fine-grained access control, this issue, in theory, allows a user to escape their otherwise limited access. This flaw allows a local, unprivileged user to access virtproxyd without authenticating. Remote users would need to authenticate before they could access it.",
"id": "GHSA-q262-3hfr-f5q4",
"modified": "2025-04-12T00:30:26Z",
"published": "2024-05-08T03:30:37Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-4418"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2024:4351"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2024:4432"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2024:4757"
},
{
"type": "WEB",
"url": "https://access.redhat.com/security/cve/CVE-2024-4418"
},
{
"type": "WEB",
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2278616"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/4IE44UIIC3QWBFRB4EUSFNLJBU6JLNSD"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/Q4ZQBAJVHIZMCZNTRPUW3ZKXRKLXRQZU"
},
{
"type": "WEB",
"url": "https://security.netapp.com/advisory/ntap-20250411-0002"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-Q263-XMXV-64C3
Vulnerability from github – Published: 2026-06-09 18:30 – Updated: 2026-06-09 18:30Heap-based buffer overflow in Remote Desktop Client allows an unauthorized attacker to execute code over a network.
{
"affected": [],
"aliases": [
"CVE-2026-47653"
],
"database_specific": {
"cwe_ids": [
"CWE-416",
"CWE-787"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-06-09T17:17:36Z",
"severity": "HIGH"
},
"details": "Heap-based buffer overflow in Remote Desktop Client allows an unauthorized attacker to execute code over a network.",
"id": "GHSA-q263-xmxv-64c3",
"modified": "2026-06-09T18:30:55Z",
"published": "2026-06-09T18:30:55Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-47653"
},
{
"type": "WEB",
"url": "https://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-47653"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-Q2C8-H5P8-R22V
Vulnerability from github – Published: 2025-07-08 18:31 – Updated: 2025-07-08 18:31Use after free in Windows Notification allows an authorized attacker to elevate privileges locally.
{
"affected": [],
"aliases": [
"CVE-2025-49726"
],
"database_specific": {
"cwe_ids": [
"CWE-416"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-07-08T17:16:00Z",
"severity": "HIGH"
},
"details": "Use after free in Windows Notification allows an authorized attacker to elevate privileges locally.",
"id": "GHSA-q2c8-h5p8-r22v",
"modified": "2025-07-08T18:31:50Z",
"published": "2025-07-08T18:31:50Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-49726"
},
{
"type": "WEB",
"url": "https://msrc.microsoft.com/update-guide/vulnerability/CVE-2025-49726"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-Q2CP-MH84-P47V
Vulnerability from github – Published: 2024-05-20 12:30 – Updated: 2025-01-14 18:31In the Linux kernel, the following vulnerability has been resolved:
raid1: fix use-after-free for original bio in raid1_write_request()
r1_bio->bios[] is used to record new bios that will be issued to underlying disks, however, in raid1_write_request(), r1_bio->bios[] will set to the original bio temporarily. Meanwhile, if blocked rdev is set, free_r1bio() will be called causing that all r1_bio->bios[] to be freed:
raid1_write_request() r1_bio = alloc_r1bio(mddev, bio); -> r1_bio->bios[] is NULL for (i = 0; i < disks; i++) -> for each rdev in conf // first rdev is normal r1_bio->bios[0] = bio; -> set to original bio // second rdev is blocked if (test_bit(Blocked, &rdev->flags)) break
if (blocked_rdev) free_r1bio() put_all_bios() bio_put(r1_bio->bios[0]) -> original bio is freed
Test scripts:
mdadm -CR /dev/md0 -l1 -n4 /dev/sd[abcd] --assume-clean fio -filename=/dev/md0 -ioengine=libaio -rw=write -bs=4k -numjobs=1 \ -iodepth=128 -name=test -direct=1 echo blocked > /sys/block/md0/md/rd2/state
Test result:
BUG bio-264 (Not tainted): Object already free
Allocated in mempool_alloc_slab+0x24/0x50 age=1 cpu=1 pid=869 kmem_cache_alloc+0x324/0x480 mempool_alloc_slab+0x24/0x50 mempool_alloc+0x6e/0x220 bio_alloc_bioset+0x1af/0x4d0 blkdev_direct_IO+0x164/0x8a0 blkdev_write_iter+0x309/0x440 aio_write+0x139/0x2f0 io_submit_one+0x5ca/0xb70 __do_sys_io_submit+0x86/0x270 __x64_sys_io_submit+0x22/0x30 do_syscall_64+0xb1/0x210 entry_SYSCALL_64_after_hwframe+0x6c/0x74 Freed in mempool_free_slab+0x1f/0x30 age=1 cpu=1 pid=869 kmem_cache_free+0x28c/0x550 mempool_free_slab+0x1f/0x30 mempool_free+0x40/0x100 bio_free+0x59/0x80 bio_put+0xf0/0x220 free_r1bio+0x74/0xb0 raid1_make_request+0xadf/0x1150 md_handle_request+0xc7/0x3b0 md_submit_bio+0x76/0x130 __submit_bio+0xd8/0x1d0 submit_bio_noacct_nocheck+0x1eb/0x5c0 submit_bio_noacct+0x169/0xd40 submit_bio+0xee/0x1d0 blkdev_direct_IO+0x322/0x8a0 blkdev_write_iter+0x309/0x440 aio_write+0x139/0x2f0
Since that bios for underlying disks are not allocated yet, fix this problem by using mempool_free() directly to free the r1_bio.
{
"affected": [],
"aliases": [
"CVE-2024-35979"
],
"database_specific": {
"cwe_ids": [
"CWE-416"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-05-20T10:15:12Z",
"severity": "HIGH"
},
"details": "In the Linux kernel, the following vulnerability has been resolved:\n\nraid1: fix use-after-free for original bio in raid1_write_request()\n\nr1_bio-\u003ebios[] is used to record new bios that will be issued to\nunderlying disks, however, in raid1_write_request(), r1_bio-\u003ebios[]\nwill set to the original bio temporarily. Meanwhile, if blocked rdev\nis set, free_r1bio() will be called causing that all r1_bio-\u003ebios[]\nto be freed:\n\nraid1_write_request()\n r1_bio = alloc_r1bio(mddev, bio); -\u003e r1_bio-\u003ebios[] is NULL\n for (i = 0; i \u003c disks; i++) -\u003e for each rdev in conf\n // first rdev is normal\n r1_bio-\u003ebios[0] = bio; -\u003e set to original bio\n // second rdev is blocked\n if (test_bit(Blocked, \u0026rdev-\u003eflags))\n break\n\n if (blocked_rdev)\n free_r1bio()\n put_all_bios()\n bio_put(r1_bio-\u003ebios[0]) -\u003e original bio is freed\n\nTest scripts:\n\nmdadm -CR /dev/md0 -l1 -n4 /dev/sd[abcd] --assume-clean\nfio -filename=/dev/md0 -ioengine=libaio -rw=write -bs=4k -numjobs=1 \\\n -iodepth=128 -name=test -direct=1\necho blocked \u003e /sys/block/md0/md/rd2/state\n\nTest result:\n\nBUG bio-264 (Not tainted): Object already free\n-----------------------------------------------------------------------------\n\nAllocated in mempool_alloc_slab+0x24/0x50 age=1 cpu=1 pid=869\n kmem_cache_alloc+0x324/0x480\n mempool_alloc_slab+0x24/0x50\n mempool_alloc+0x6e/0x220\n bio_alloc_bioset+0x1af/0x4d0\n blkdev_direct_IO+0x164/0x8a0\n blkdev_write_iter+0x309/0x440\n aio_write+0x139/0x2f0\n io_submit_one+0x5ca/0xb70\n __do_sys_io_submit+0x86/0x270\n __x64_sys_io_submit+0x22/0x30\n do_syscall_64+0xb1/0x210\n entry_SYSCALL_64_after_hwframe+0x6c/0x74\nFreed in mempool_free_slab+0x1f/0x30 age=1 cpu=1 pid=869\n kmem_cache_free+0x28c/0x550\n mempool_free_slab+0x1f/0x30\n mempool_free+0x40/0x100\n bio_free+0x59/0x80\n bio_put+0xf0/0x220\n free_r1bio+0x74/0xb0\n raid1_make_request+0xadf/0x1150\n md_handle_request+0xc7/0x3b0\n md_submit_bio+0x76/0x130\n __submit_bio+0xd8/0x1d0\n submit_bio_noacct_nocheck+0x1eb/0x5c0\n submit_bio_noacct+0x169/0xd40\n submit_bio+0xee/0x1d0\n blkdev_direct_IO+0x322/0x8a0\n blkdev_write_iter+0x309/0x440\n aio_write+0x139/0x2f0\n\nSince that bios for underlying disks are not allocated yet, fix this\nproblem by using mempool_free() directly to free the r1_bio.",
"id": "GHSA-q2cp-mh84-p47v",
"modified": "2025-01-14T18:31:49Z",
"published": "2024-05-20T12:30:29Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-35979"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/3f28d49a328fe20926995d5fbdc92da665596268"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/f423f41b7679c09abb26d2bd54be5cbef23c9446"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/fcf3f7e2fc8a53a6140beee46ec782a4c88e4744"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-Q2CV-8M5W-P6F2
Vulnerability from github – Published: 2022-05-24 16:47 – Updated: 2024-04-04 00:53There is a use after free vulnerability on certain driver component in Huawei Mate10 smartphones versions earlier than ALP-AL00B 9.0.0.167(C00E85R2P20T8). An attacker tricks the user into installing a malicious application, which make the software to reference memory after it has been freed. Successful exploit could cause a denial of service condition.
{
"affected": [],
"aliases": [
"CVE-2019-5214"
],
"database_specific": {
"cwe_ids": [
"CWE-416"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2019-06-06T15:29:00Z",
"severity": "HIGH"
},
"details": "There is a use after free vulnerability on certain driver component in Huawei Mate10 smartphones versions earlier than ALP-AL00B 9.0.0.167(C00E85R2P20T8). An attacker tricks the user into installing a malicious application, which make the software to reference memory after it has been freed. Successful exploit could cause a denial of service condition.",
"id": "GHSA-q2cv-8m5w-p6f2",
"modified": "2024-04-04T00:53:34Z",
"published": "2022-05-24T16:47:31Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2019-5214"
},
{
"type": "WEB",
"url": "http://www.huawei.com/en/psirt/security-advisories/huawei-sa-20190109-01-smartphone-en"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-Q2F8-7M8G-86C8
Vulnerability from github – Published: 2022-07-27 00:00 – Updated: 2022-07-30 00:00Use after free in SwiftShader in Google Chrome prior to 101.0.4951.41 allowed a remote attacker to potentially exploit heap corruption via a crafted HTML page.
{
"affected": [],
"aliases": [
"CVE-2022-1478"
],
"database_specific": {
"cwe_ids": [
"CWE-416"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2022-07-26T22:15:00Z",
"severity": "HIGH"
},
"details": "Use after free in SwiftShader in Google Chrome prior to 101.0.4951.41 allowed a remote attacker to potentially exploit heap corruption via a crafted HTML page.",
"id": "GHSA-q2f8-7m8g-86c8",
"modified": "2022-07-30T00:00:19Z",
"published": "2022-07-27T00:00:33Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-1478"
},
{
"type": "WEB",
"url": "https://chromereleases.googleblog.com/2022/04/stable-channel-update-for-desktop_26.html"
},
{
"type": "WEB",
"url": "https://crbug.com/1299261"
},
{
"type": "WEB",
"url": "https://security.gentoo.org/glsa/202208-25"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-Q2FF-FFV4-75Q7
Vulnerability from github – Published: 2022-05-24 17:43 – Updated: 2022-05-24 17:43Use after free in Blink in Google Chrome prior to 89.0.4389.72 allowed a remote attacker to potentially exploit heap corruption via a crafted HTML page.
{
"affected": [],
"aliases": [
"CVE-2021-21188"
],
"database_specific": {
"cwe_ids": [
"CWE-416"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-03-09T18:15:00Z",
"severity": "HIGH"
},
"details": "Use after free in Blink in Google Chrome prior to 89.0.4389.72 allowed a remote attacker to potentially exploit heap corruption via a crafted HTML page.",
"id": "GHSA-q2ff-ffv4-75q7",
"modified": "2022-05-24T17:43:59Z",
"published": "2022-05-24T17:43:59Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-21188"
},
{
"type": "WEB",
"url": "https://chromereleases.googleblog.com/2021/03/stable-channel-update-for-desktop.html"
},
{
"type": "WEB",
"url": "https://crbug.com/1161739"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/BBT54RKAE5XLMWSHLVUKJ7T2XHHYMXLH"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/FE5SIKEVYTMDCC5OSXGOM2KRPYLHYMQX"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/LCIDZ77XUDMB2EBPPWCQXPEIJERDNSNT"
},
{
"type": "WEB",
"url": "https://security.gentoo.org/glsa/202104-08"
},
{
"type": "WEB",
"url": "https://www.debian.org/security/2021/dsa-4886"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-Q2FW-M52X-W593
Vulnerability from github – Published: 2025-07-22 15:32 – Updated: 2026-05-19 15:31A vulnerability was found in libssh, where an uninitialized variable exists under certain conditions in the privatekey_from_file() function. This flaw can be triggered if the file specified by the filename doesn't exist and may lead to possible signing failures or heap corruption.
{
"affected": [],
"aliases": [
"CVE-2025-4878"
],
"database_specific": {
"cwe_ids": [
"CWE-416"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-07-22T15:15:36Z",
"severity": "LOW"
},
"details": "A vulnerability was found in libssh, where an uninitialized variable exists under certain conditions in the privatekey_from_file() function. This flaw can be triggered if the file specified by the filename doesn\u0027t exist and may lead to possible signing failures or heap corruption.",
"id": "GHSA-q2fw-m52x-w593",
"modified": "2026-05-19T15:31:18Z",
"published": "2025-07-22T15:32:52Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-4878"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:18683"
},
{
"type": "WEB",
"url": "https://access.redhat.com/security/cve/CVE-2025-4878"
},
{
"type": "WEB",
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2376184"
},
{
"type": "WEB",
"url": "https://git.libssh.org/projects/libssh.git/commit/?id=697650caa97eaf7623924c75f9fcfec6dd423cd1"
},
{
"type": "WEB",
"url": "https://git.libssh.org/projects/libssh.git/commit/?id=b35ee876adc92a208d47194772e99f9c71e0bedb"
},
{
"type": "WEB",
"url": "https://www.libssh.org/security/advisories/CVE-2025-4878.txt"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-Q2G3-7222-F2P8
Vulnerability from github – Published: 2025-05-13 21:30 – Updated: 2025-05-13 21:30Use after free for some Intel(R) PROSet/Wireless WiFi Software for Windows before version 23.100 may allow an unauthenticated user to potentially enable denial of service via adjacent access.
{
"affected": [],
"aliases": [
"CVE-2025-20006"
],
"database_specific": {
"cwe_ids": [
"CWE-416"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-05-13T21:16:02Z",
"severity": "HIGH"
},
"details": "Use after free for some Intel(R) PROSet/Wireless WiFi Software for Windows before version 23.100 may allow an unauthenticated user to potentially enable denial of service via adjacent access.",
"id": "GHSA-q2g3-7222-f2p8",
"modified": "2025-05-13T21:30:55Z",
"published": "2025-05-13T21:30:55Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-20006"
},
{
"type": "WEB",
"url": "https://intel.com/content/www/us/en/security-center/advisory/intel-sa-01270.html"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:A/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:H/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",
"type": "CVSS_V4"
}
]
}
GHSA-Q2GM-54R6-8FWM
Vulnerability from github – Published: 2026-06-19 19:36 – Updated: 2026-06-19 19:36Summary
Oj::Parser#parse is vulnerable to a heap use-after-free when a SAJ/SAJ2 callback mutates the input JSON string during parsing. The C engine holds a raw const byte * pointer into the Ruby string's internal buffer. If a callback (e.g. hash_start) resizes the string — for example by calling String#replace with a longer value — Ruby reallocates the string buffer and frees the old one. The C parser's pointer is left dangling; the next character read at parser.c:607 is a use-after-free.
Version
- Software: oj gem
- Affected: all versions with
ext/oj/parser.c - Latest tested: 3.17.1 (confirmed present)
Details
ext/oj/parser.c, parser_parse → parse:
static VALUE parser_parse(VALUE self, VALUE json) {
const byte *ptr = (const byte *)StringValuePtr(json); // raw pointer into Ruby string
// ...
parse(p, ptr); // ptr used throughout; any realloc frees the backing buffer
}
// parser.c:607
static void parse(ojParser p, const byte *json) {
const byte *b = json;
// ...
for (; '\0' != *b; b++) { // ← UAF: reads freed memory after callback resizes json
Ruby's String#replace (or <<, gsub!, etc.) can trigger a reallocation of the string's internal buffer if the new content is larger than the embedded capacity, freeing the old buffer that ptr still points to.
ASAN report:
==372273==ERROR: AddressSanitizer: heap-use-after-free on address 0x51900008ed81
READ of size 1 at 0x51900008ed81 thread T0
#0 parse /ext/oj/parser.c:607
#1 parser_parse /ext/oj/parser.c:1408
0x51900008ed81 is located 1 bytes inside of 1023-byte region [0x51900008ed80, 0x51900008f17f)
freed by thread T0 here:
#0 free
#1 ruby_sized_xfree (libruby-3.3.so.3.3)
Shadow bytes: [fd]fd fd fd fd fd ... (entire region freed)
Reproduce
require 'oj'
class Mutator
def initialize(json) = (@json = json; @done = false)
def hash_start(key)
return if @done; @done = true
@json.replace('x' * 1_000_000) # triggers String realloc, frees original buffer
end
def hash_end(key); end
def array_start(key); end
def array_end(key); end
def add_value(value, key); end
end
json = '{"a":1,"pad":"' + ('A' * 1000) + '","z":2}'
parser = Oj::Parser.new(:saj)
parser.handler = Mutator.new(json)
parser.parse(json)
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c 3.17.2"
},
"package": {
"ecosystem": "RubyGems",
"name": "oj"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.17.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-54898"
],
"database_specific": {
"cwe_ids": [
"CWE-416"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-19T19:36:54Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "### Summary\n\n`Oj::Parser#parse` is vulnerable to a heap use-after-free when a SAJ/SAJ2 callback mutates the input JSON string during parsing. The C engine holds a raw `const byte *` pointer into the Ruby string\u0027s internal buffer. If a callback (e.g. `hash_start`) resizes the string \u2014 for example by calling `String#replace` with a longer value \u2014 Ruby reallocates the string buffer and frees the old one. The C parser\u0027s pointer is left dangling; the next character read at `parser.c:607` is a use-after-free.\n\n### Version\n\n- **Software**: oj gem\n- **Affected**: all versions with `ext/oj/parser.c`\n- **Latest tested**: 3.17.1 (confirmed present)\n\n### Details\n\n`ext/oj/parser.c`, `parser_parse` \u2192 `parse`:\n\n```c\nstatic VALUE parser_parse(VALUE self, VALUE json) {\n const byte *ptr = (const byte *)StringValuePtr(json); // raw pointer into Ruby string\n // ...\n parse(p, ptr); // ptr used throughout; any realloc frees the backing buffer\n}\n```\n\n```c\n// parser.c:607\nstatic void parse(ojParser p, const byte *json) {\n const byte *b = json;\n // ...\n for (; \u0027\\0\u0027 != *b; b++) { // \u2190 UAF: reads freed memory after callback resizes json\n```\n\nRuby\u0027s `String#replace` (or `\u003c\u003c`, `gsub!`, etc.) can trigger a reallocation of the string\u0027s internal buffer if the new content is larger than the embedded capacity, freeing the old buffer that `ptr` still points to.\n\nASAN report:\n```\n==372273==ERROR: AddressSanitizer: heap-use-after-free on address 0x51900008ed81\nREAD of size 1 at 0x51900008ed81 thread T0\n #0 parse /ext/oj/parser.c:607\n #1 parser_parse /ext/oj/parser.c:1408\n0x51900008ed81 is located 1 bytes inside of 1023-byte region [0x51900008ed80, 0x51900008f17f)\nfreed by thread T0 here:\n #0 free\n #1 ruby_sized_xfree (libruby-3.3.so.3.3)\nShadow bytes: [fd]fd fd fd fd fd ... (entire region freed)\n```\n\n### Reproduce\n\n```ruby\nrequire \u0027oj\u0027\n\nclass Mutator\n def initialize(json) = (@json = json; @done = false)\n\n def hash_start(key)\n return if @done; @done = true\n @json.replace(\u0027x\u0027 * 1_000_000) # triggers String realloc, frees original buffer\n end\n\n def hash_end(key); end\n def array_start(key); end\n def array_end(key); end\n def add_value(value, key); end\nend\n\njson = \u0027{\"a\":1,\"pad\":\"\u0027 + (\u0027A\u0027 * 1000) + \u0027\",\"z\":2}\u0027\nparser = Oj::Parser.new(:saj)\nparser.handler = Mutator.new(json)\nparser.parse(json)\n```",
"id": "GHSA-q2gm-54r6-8fwm",
"modified": "2026-06-19T19:36:54Z",
"published": "2026-06-19T19:36:54Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/ohler55/oj/security/advisories/GHSA-q2gm-54r6-8fwm"
},
{
"type": "PACKAGE",
"url": "https://github.com/ohler55/oj"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "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",
"type": "CVSS_V4"
}
],
"summary": "Oj: Use-After-Free in Oj::Parser SAJ Callback via Input Mutation"
}
Mitigation
Strategy: Language Selection
Choose a language that provides automatic memory management.
Mitigation
Strategy: Attack Surface Reduction
When freeing pointers, be sure to set them to NULL once they are freed. However, the utilization of multiple or complex data structures may lower the usefulness of this strategy.
No CAPEC attack patterns related to this CWE.