Jul 2, 2026·6 min read·149 visits
Integer truncation in SQLite's aggregate query compiler allows remote code execution or denial of service through out-of-bounds heap reads and writes when processing queries with over 32,767 unique columns.
An integer truncation vulnerability (CWE-197) exists in SQLite before version 3.50.2 during the processing of aggregate queries with more than 32,767 distinct column references. This causes an internal 32-bit counter to truncate to a signed 16-bit integer, producing negative values that cause out-of-bounds heap operations in release builds.
SQLite is an embedded relational database engine utilized inside almost every major operating system, web browser, and enterprise application framework. The attack surface of SQLite expands when applications allow untrusted inputs to compile into executable database instructions. This specific vulnerability is an integer truncation flaw within the database engine's parsing and compilation pipeline.
The flaw exposes the system to heap-based buffer overflows during the compilation of complex aggregate queries. An attacker who is able to supply raw SQL queries to the compiler can exploit this truncation to corrupt memory. In systems with high-privilege SQL execution environments, this behavior can escalate to remote code execution.
Because SQLite runs inside the context of the calling process, memory corruption in the database engine translates directly to compromise of the parent application. The threat model is particularly critical for mobile platforms, native applications, and database management systems that perform client-side SQL execution. Securing these architectures requires a thorough understanding of compile-time logic.
The root cause of CVE-2025-6965 lies in the findOrCreateAggInfoColumn function within SQLite's query compilation subsystem. When parsing SQL statements containing aggregate functions like SUM(), COUNT(), or AVG(), SQLite maintains an internal count of distinct column references. This counter tracks where aggregate results are temporarily stored during execution.
If the number of unique column references within the aggregate expressions exceeds 32,767, the tracking index exceeds the storage capacity of a signed 16-bit integer. When the 32-bit compilation counter assigns its value to the 16-bit signed index variable, numeric truncation occurs. A value of 32,768 (0x8000) wraps to -32,768 due to the sign-bit interpretation.
In debug builds, assertion statements immediately halt program execution upon detecting invalid negative index states. In production (non-debug) release builds, these diagnostic assertions are compiled out to optimize performance. The negative index value then flows unchecked into subsequent memory calculation routines, resulting in out-of-bounds pointer arithmetic.
The vulnerability involves how the compiler manages the AggInfo structure and its nested arrays. Prior to the patch, the parser did not enforce a low-level limit on the number of aggregate terms. This omission allowed the internal counter to increment past the boundary of a signed 16-bit short.
Let's construct the visual state transition using a Mermaid diagram to show the flow of compilation index truncation:
The patch in trunk commit 5508b56fd24016c13981ec280ecdd833007c9d8dd595edb295b984c2b487b5c8 prevents this scenario by inserting validation checks directly inside src/expr.c. Below is a conceptual representation of the vulnerable pattern versus the patched logic:
// Vulnerable Code Path
struct AggInfo_col {
short iCol; // Signed 16-bit integer used for indexing
// ... other fields
};
int findOrCreateAggInfoColumn(Parse *pParse, AggInfo *pAggInfo, Expr *pExpr) {
// No validation on the aggregate column count before assignment
pAggInfo->aCol[pAggInfo->nColumn].iCol = (short)nColIndex; // Truncation happens here
pAggInfo->nColumn++;
}The patched version restricts the compilation count before any assignment is made:
// Patched Code Path (Trunk Fix)
int findOrCreateAggInfoColumn(Parse *pParse, AggInfo *pAggInfo, Expr *pExpr) {
if( pAggInfo->nColumn >= 32768 ){
sqlite3ErrorMsg(pParse, "too many terms in aggregate query");
return -1;
}
// The assignment is now guaranteed to remain within the range of a signed 16-bit integer
pAggInfo->aCol[pAggInfo->nColumn].iCol = (short)nColIndex;
pAggInfo->nColumn++;
}Exploitation of CVE-2025-6965 requires two primary prerequisites: the ability to execute arbitrary SQL commands on the target, and the absence of query length restrictions. The attacker constructs a SQL string consisting of more than 32,767 distinct columns referenced within aggregate statements. This query can reach several megabytes in size due to the verbose nature of naming tens of thousands of columns.
When the application processes this payload, the parser processes the columns and triggers the integer truncation in the compiler. Because the generated VDBE instructions contain negative indexes, the execution phase performs out-of-bounds lookups on the heap. Specifically, the base address of the aggregate column array is offset by a negative memory multiplier.
This calculation points to heap areas preceding the allocated buffer, where other critical database engine allocations reside. The application reads arbitrary data from these offsets and writes mutated values back to the same out-of-bounds locations during processing. Under precise heap layout manipulation, these out-of-bounds writes overwrite internal structure function pointers, allowing control flow hijack.
The security impact of CVE-2025-6965 is high, posing severe risks to applications integrating SQLite. The CVSS v3.1 base score of 7.7 represents a scenario where the attacker must have some privilege level to execute arbitrary SQL or must chain this with a SQL injection flaw. In situations where raw SQL injection exists, the impact elevates to remote code execution.
The EPSS score of 0.73495 demonstrates high vulnerability research interest and a high likelihood of target analysis. Although CISA has not yet added this vulnerability to the Known Exploited Vulnerabilities catalog, the technical availability of public details makes it a viable candidate for weaponization. Impacted operating systems include Apple macOS, iOS, iPadOS, and industrial systems like Siemens Ruggedcom Crossbow.
If successfully exploited, the vulnerability compromises the integrity of the host process, leading to a denial-of-service crash or complete execution control. Host configurations must treat this as a high-severity threat, especially in multi-tenant environments where users execute custom analytical database queries.
The definitive remediation is upgrading to SQLite version 3.50.2 or higher, which includes the hard limit checks on aggregate query sizes. For legacy systems where a full system upgrade is unfeasible, backported security updates are available on branches 3.32 and 3.42. These legacy patches include runtime bounds-checking to prevent negative offsets from being resolved during execution.
When binary updates are delayed, temporary mitigation strategies can reduce the attack surface. Applications should implement validation filters on inbound queries, dropping any requests exceeding 100 KB in size or containing more than 1,000 column declarations. Restricting database execution environments to read-only configurations does not prevent this heap corruption, as the compilation phase itself triggers the vulnerability.
Software developers must compile SQLite with strict compiler warning elevations to catch type conversions. Using flags like -Wconversion or -Wshorten-64-to-32 exposes truncation risks during the compilation of custom extensions. Regular static and dynamic analysis of native dependencies remains a critical practice to prevent native memory safety flaws from affecting higher-level applications.
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:L/I:H/A:L| Attribute | Detail |
|---|---|
| CWE ID | CWE-197 |
| Attack Vector | Network (AV:N) |
| CVSS Score | 7.7 (High) |
| EPSS Score | 0.73495 (99.40th percentile) |
| Impact | Memory Corruption / Remote Code Execution |
| Exploit Status | PoC Available |
| KEV Status | Not listed |
Truncation of a primitive type to a smaller type, leading to data loss and unexpected sign-extension or wrap-around.
Grav CMS prior to version 1.7.53 and 2.0.0-rc.8 is vulnerable to an unauthenticated remote denial of service (DoS) vulnerability. By supplying crafted query parameters with extremely large dimensions to image assets, remote unauthenticated attackers can force the server to allocate massive amounts of system memory, leading to kernel Out-Of-Memory (OOM) termination of web worker processes.
CVE-2026-53657 is a local privilege escalation vulnerability in Lima (lima-vm/lima) affecting versions prior to 2.1.3 when configured with the QEMU driver. The guest agent daemon, running as root, creates its communication socket `/run/lima-guestagent.sock` with world-writable permissions (0777). This allows unprivileged local users to command the agent to establish arbitrary tunnels, including to privileged local UNIX sockets (like D-Bus). Because the target daemon authenticates the incoming connection using the credentials of the root-owned guest agent (via SO_PEERCRED), unprivileged users can perform root operations, resulting in complete guest VM compromise.
An unauthenticated Denial of Service vulnerability exists in the s2n-quic library's CryptoStream reassembler due to a lack of buffer limits on out-of-order cryptographic frames. An attacker can transmit a crafted CRYPTO frame with an extremely high offset and nominal payload, forcing the receiver to execute unbounded memory allocations and causing service crashes.
A JNDI Injection and Deserialization Gadget vulnerability exists in mchange-commons-java prior to version 0.6.0. The com.mchange.v2.naming.JavaBeanObjectFactory component permits arbitrary class instantiation and setter invocation, allowing attackers to perform Server-Side Request Forgery (SSRF) and remote class loading.
SurrealDB versions supporting element-level SELECT permissions on arrays are vulnerable to a logical authorization bypass. Due to an index-shifting error during array filtration, restricted elements can skip permission checks and leak to unauthorized record users.
CVE-2026-12243 is a path traversal vulnerability in the Natural Language Toolkit (NLTK) version 3.9.4. The flaw exists because the input validation routine fails to account for percent-encoded directory traversal sequences like '..%2f' before passing them to urllib.request.url2pathname(), which decodes them into active traversal sequences.