CVE-2026-18022 Overview
CVE-2026-18022 is an integer wraparound vulnerability [CWE-190] in the IVFFlat index build code of pgvector before version 0.8.6. The flaw allows an authenticated database user to trigger an out-of-bounds write during index construction. Successful exploitation can lead to arbitrary code execution within the PostgreSQL backend process. Only 32-bit systems are affected because the wraparound occurs in Size arithmetic that remains safe on 64-bit builds. pgvector is a widely deployed PostgreSQL extension for vector similarity search used in AI and retrieval-augmented generation workloads.
Critical Impact
An authenticated database user on a 32-bit PostgreSQL host running pgvector can trigger memory corruption during IVFFlat index build, resulting in arbitrary code execution in the database server process.
Affected Products
- pgvector versions prior to 0.8.6
- PostgreSQL deployments running pgvector on 32-bit systems
- Applications and AI/RAG pipelines relying on IVFFlat indexes in pgvector
Discovery Timeline
- 2026-07-29 - CVE-2026-18022 published to NVD
- 2026-07-29 - Last updated in NVD database
Technical Details for CVE-2026-18022
Vulnerability Analysis
The vulnerability resides in the IVFFlat k-means clustering routine in src/ivfkmeans.c. During index build, the extension computes allocation sizes for several working buffers using raw multiplication of numCenters, numSamples, and dimensions. On 32-bit systems, the Size type is 32 bits wide, so large but attacker-controllable index parameters cause the multiplications to wrap around to small values. Subsequent allocations are undersized while the code proceeds to write full-length arrays into them, producing an out-of-bounds heap write.
Root Cause
The root cause is unchecked integer arithmetic when computing buffer sizes. Expressions such as sizeof(float) * numSamples * numCenters overflow the 32-bit Size type before the allocator ever sees the intended value. The fix replaces the raw arithmetic with PostgreSQL's mul_size and add_size helpers, which detect overflow and raise an error instead of returning a wrapped result.
Attack Vector
Exploitation requires an authenticated database role with permission to create an IVFFlat index on a table with attacker-influenced vector dimensions or list counts. The attacker issues a CREATE INDEX ... USING ivfflat statement with parameters chosen so that the internal size calculations wrap. The resulting out-of-bounds write corrupts adjacent heap memory in the PostgreSQL backend process, giving a path to arbitrary code execution under the PostgreSQL service account.
// Source: https://github.com/pgvector/pgvector/commit/636a92a3395d2e036ffd40d07aeb400a708ae104
// Patch in src/ivfkmeans.c - replaces unchecked multiplication with overflow-safe helpers
/* Calculate allocation sizes */
Size newCentersSize = VECTOR_ARRAY_SIZE(numCenters, centers->itemsize);
- Size aggSize = sizeof(float) * (int64) numCenters * dimensions;
- Size centerCountsSize = sizeof(int) * numCenters;
- Size closestCentersSize = sizeof(int) * numSamples;
- Size lowerBoundSize = sizeof(float) * numSamples * numCenters;
- Size upperBoundSize = sizeof(float) * numSamples;
- Size sSize = sizeof(float) * numCenters;
- Size halfcdistSize = sizeof(float) * numCenters * numCenters;
- Size newcdistSize = sizeof(float) * numCenters;
+ Size aggSize = mul_size(sizeof(float), mul_size(numCenters, dimensions));
+ Size centerCountsSize = mul_size(sizeof(int), numCenters);
+ Size closestCentersSize = mul_size(sizeof(int), numSamples);
+ Size lowerBoundSize = mul_size(sizeof(float), mul_size(numSamples, numCenters));
+ Size upperBoundSize = mul_size(sizeof(float), numSamples);
+ Size sSize = mul_size(sizeof(float), numCenters);
+ Size halfcdistSize = mul_size(sizeof(float), mul_size(numCenters, numCenters));
+ Size newcdistSize = mul_size(sizeof(float), numCenters);
/* Calculate total size */
- Size totalSize = memoryUsed + newCentersSize + aggSize + centerCountsSize + closestCentersSize + lowerBoundSize + upperBoundSize + sSize + halfcdistSize + newcdistSize;
+ Size totalSize = memoryUsed;
+
+ totalSize = add_size(totalSize, newCentersSize);
+ totalSize = add_size(totalSize, aggSize);
+ totalSize = add_size(totalSize, centerCountsSize);
+ totalSize = add_size(totalSize, closestCentersSize);
+ totalSize = add_size(totalSize, lowerBoundSize);
+ totalSize = add_size(totalSize, upperBoundSize);
Source: pgvector commit 636a92a
Detection Methods for CVE-2026-18022
Indicators of Compromise
- Unexpected crashes or SIGSEGV entries in PostgreSQL logs correlated with CREATE INDEX ... USING ivfflat statements.
- PostgreSQL backend processes spawning shell or scripting interpreters such as sh, bash, or python.
- Outbound network connections initiated by the postgres process to unfamiliar destinations after index operations.
Detection Strategies
- Inventory PostgreSQL servers running pgvector and identify any deployed on 32-bit operating systems or 32-bit PostgreSQL builds.
- Query pg_extension for vector extension versions below 0.8.6 across managed database fleets.
- Audit database roles that hold CREATE privileges on schemas containing vector-typed columns.
Monitoring Recommendations
- Enable log_statement = 'ddl' in PostgreSQL to capture all CREATE INDEX operations for review.
- Alert on child processes spawned by postgres that are not part of standard database operation.
- Forward PostgreSQL and host telemetry to a centralized data lake and correlate index-build activity with process and network events.
How to Mitigate CVE-2026-18022
Immediate Actions Required
- Upgrade pgvector to version 0.8.6 or later on all PostgreSQL instances, prioritizing 32-bit hosts.
- Restrict CREATE privileges on schemas containing vector columns to trusted roles only.
- Migrate 32-bit PostgreSQL deployments to 64-bit builds where feasible, as the vulnerable arithmetic is safe on 64-bit Size.
Patch Information
The issue is fixed in pgvector 0.8.6. The upstream fix replaces unchecked size arithmetic in src/ivfkmeans.c with the overflow-safe mul_size and add_size helpers from PostgreSQL. Refer to the pgvector patch commit and the pgvector issue #1006 for context.
Workarounds
- Revoke IVFFlat index creation from untrusted database roles until the extension is upgraded.
- Block CREATE INDEX ... USING ivfflat at the application layer or via event triggers on 32-bit hosts.
- Move affected workloads to 64-bit PostgreSQL servers where the wraparound cannot occur.
# Upgrade pgvector and reload the extension
cd /path/to/pgvector
git fetch --tags
git checkout v0.8.6
make && sudo make install
# In psql, upgrade the installed extension in each affected database
psql -d your_database -c "ALTER EXTENSION vector UPDATE TO '0.8.6';"
# Optional: restrict index creation until patched
psql -d your_database -c "REVOKE CREATE ON SCHEMA public FROM PUBLIC;"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

