Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-18022

CVE-2026-18022: pgvector IVFFlat Index RCE Vulnerability

CVE-2026-18022 is an integer wraparound vulnerability in pgvector's IVFFlat index build that enables remote code execution on 32-bit systems. This article covers technical details, affected versions, and mitigation strategies.

Published:

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.

c
// 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.
bash
# 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.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.