Spring AI’s April 27 batch1 patches five CVEs across the 1.0.x and 1.1.x lines. Two score HIGH: CVE-2026-409782 (CVSS 8.8) interpolates document IDs directly into a Cosmos DB SQL string, and CVE-2026-409673 (CVSS 8.6) leaves filter-expression keys unescaped across more than a dozen vector stores. The combined effect breaks the assumption that vector-store retrieval sits safely above the database layer.
The April 27 Batch: What Shipped
Spring AI 1.0.6 and 1.1.51 landed on April 27, 2026 with fixes for five CVEs. The two HIGH-severity issues trace directly to unparameterized query construction: one in a single backend, one spanning the entire filter-expression abstraction that Spring AI shares across backends. The remaining three are MEDIUM, covering chat-memory isolation, document parsing, and a cache directory permission issue.
All five affect the 1.0.0–1.0.5 and 1.1.0–1.1.4 ranges.
CVE-2026-40978: SQL Injection in CosmosDBVectorStore.doDelete()
CVE-2026-409784 scores CVSS 8.8 with low privileges required (PR
). That means an authenticated user with basic access can trigger it. This is not an unauthenticated scenario, but the bar is still low for any multi-tenant application where users supply document identifiers.The pre-patch code5 constructed the delete query as:
String.format("SELECT * FROM c WHERE c.id = '%s'", id)A caller controlling id gets arbitrary Cosmos DB SQL execution. The fix replaced this with a parameterized SqlQuerySpec using SqlParameter("@id", id).
CVE-2026-40967: Filter Expression Injection Across 14+ Stores
CVE-2026-409676 scores CVSS 8.6 and is the broader architectural concern. Spring AI’s filter-expression layer translates a common FilterExpression DSL into backend-specific queries for each supported store. Before the eb763fd fix7, keys and values were not properly escaped before query generation, allowing an attacker to alter the resulting query.
The fix added doKey() escaping across MariaDB, Oracle, PgVector, Pinecone, Chroma, Milvus, MongoDB, Neo4j, OpenSearch, Elasticsearch, GemFire, Couchbase, Weaviate, Infinispan, Redis, and Typesense. That list covers the near-complete set of Spring AI’s supported vector store backends.
Framing this as a CosmosDB companion issue would be wrong. CVE-2026-40967 hits the abstraction layer itself: any application using FilterExpression on any of those backends is affected, regardless of whether it runs Cosmos DB at all.
The Three Medium-Severity Companions
CVE-2026-409668 (CVSS 5.9) is the most operationally significant of the three. VectorStoreChatMemoryAdvisor constructed its conversationId filter via string concatenation:
DOCUMENT_METADATA_CONVERSATION_ID + "=='" + conversationId + "'"A single injected quote breaks the filter predicate and retrieves another tenant’s chat history. The 1e8135a commit9 replaced this with FilterExpressionBuilder.eq(), which handles escaping correctly.
The two remaining medium-severity issues are narrower in scope. One addresses an out-of-memory condition in ForkPDFLayoutTextStripper, where a crafted PDF can exhaust heap during document ingestion. The other secures the ONNX model cache in /tmp, which was created world-writable. Both are fixed in 1.0.6 and 1.1.5.
Why RAG Stacks Are the New Injection Surface
The standard SQL injection story involves a web form and a database. In a RAG stack the injection surface looks different: user input flows into a retrieval query through an abstraction layer that teams commonly treat as a sanitized primitive.
Spring AI’s FilterExpression is exactly that kind of abstraction. It presents a clean DSL for metadata filtering, translates to backend-specific query syntax, and sits between the LLM prompt layer and the underlying store. The assumption baked into most RAG architectures is that by the time input reaches FilterExpression, it has been validated at the application boundary. These CVEs break that assumption: the abstraction itself was not sanitizing inputs, and whatever validation happened upstream had no effect on what reached the backend.
The VectorStoreChatMemoryAdvisor case makes the failure mode concrete. A conversationId is the kind of identifier that applications routinely accept from a session token or a URL parameter. If that value flows into the advisor without further sanitization, CVE-2026-40966 turns a memory-isolation boundary into a cross-tenant read.
The trust boundary has shifted. Validating at the LLM prompt is no longer sufficient; inputs that feed the retrieval layer need the same treatment as inputs feeding an ORM.
Patched Versions and Upgrade Paths
Spring AI 1.0.61 and 1.1.5 contain fixes for all five CVEs. The affected range is 1.0.0–1.0.5 and 1.1.0–1.1.4 across both lines.
Upgrading is the complete remediation for CVE-2026-40978 and CVE-2026-40967. For CVE-2026-40966, if upgrading is not immediately possible, audit every code path where a conversationId or similar session-bound identifier is passed to VectorStoreChatMemoryAdvisor and treat it as unsanitized input until the patch is in place.
Teams using ONNX models with a custom cache directory should verify directory permissions after upgrading, since the patch only applies to the default path.
Frequently Asked Questions
I only use PgVector. Is CVE-2026-40967 still relevant to me?
Yes. CVE-2026-40967 affects PgVector and every other built-in backend because the bug lives in the shared FilterExpression abstraction, not in Cosmos DB-specific code. Security teams should resist deprioritizing the patch based on vendor summaries that foreground CosmosDB; the cross-store scope means your vector backend choice offers no isolation.
Why is CVE-2026-40967 structurally different from a typical SQL injection?
Standard SQL injections are backend-specific—a fix for PostgreSQL doesn’t protect Oracle. CVE-2026-40967 lives in the shared FilterExpression abstraction, so a single malformed expression can alter queries across SQL, NoSQL, and Lucene-based backends simultaneously. Switching from, say, Cosmos DB to Elasticsearch would not have isolated a team from this bug.
Do the patches change the Spring AI API, or are they drop-in replacements?
They are drop-in replacements. The fixes are internal to the query-construction layer and do not alter public APIs, so upgrading from 1.0.5 to 1.0.6 requires no code changes. The only visible difference is stricter escaping in filter expressions, which means applications that were inadvertently relying on unescaped special characters in metadata keys may see subtly different query results rather than errors.
Should teams rotate conversation identifiers after patching?
Yes. The fix prevents future injection, but any chat memory already persisted with a malformed conversationId remains retrievable if an attacker can supply that same identifier through another code path. Rotating active conversation identifiers and purging affected vector entries closes this residual exposure.
Are other RAG frameworks likely to face the same vulnerability class?
Yes. LangChain, LlamaIndex, and Haystack all rely on similar metadata-filter abstractions over diverse backends, and the broader security press has not yet treated vector-store filtering as a systemic RAG-stack risk. The underlying pattern—treating retrieval filters as implicitly sanitized—is framework-agnostic and likely to resurface in future disclosures.