Severity by source
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L
Network-reachable through the application; low complexity; PR:L because the attacker must reach a filter-accepting endpoint; C:H for blind exfiltration, I:L/A:L for bounded row deletion and pg_sleep DoS.
Primary rating from Vendor (https://github.com/langchain4j/langchain4j).
CVSS VectorVendor: https://github.com/langchain4j/langchain4j
Lifecycle Timeline
3Blast Radius
ecosystem impact- 1 maven packages depend on dev.langchain4j:langchain4j-pgvector (1 direct, 0 indirect)
Ecosystem-wide dependent count for version 1.3.0-beta9.
DescriptionCVE.org
Summary
The MariaDB and pgvector embedding stores build metadata-filter SQL by string-concatenating filter keys (and, in MariaDB, string values) directly into the query without adequate escaping. A crafted metadata key in EmbeddingSearchRequest.filter() can break out of its SQL context and inject arbitrary SQL into the statements executed by the stores' search and removeAll(Filter) operations.
Details
pgvector - JSON mode (default, COMBINED_JSON / COMBINED_JSONB). JSONFilterMapper places the key inside a single-quoted SQL literal (the JSON key of the ->> operator) with no escaping:
(metadata->>'<key>')::text
A key containing a single quote breaks out, e.g. metadataKey("')::text IS NOT NULL OR pg_sleep(1) IS NOT NULL --") injects a live pg_sleep(1) (observable as a delay; exploitable for blind data extraction).
pgvector - column mode (COLUMN_PER_KEY). ColumnFilterMapper used the key as a bare, unquoted, unvalidated SQL identifier (<key>::<type>), so a key such as 1=1 OR true -- injects directly.
MariaDB - JSON mode (default). JSONFilterMapper placed the key inside the JSON path literal '$.<key>' unescaped (same break-out mechanism). Additionally, MariaDbFilterMapper.formatValue() escaped ' but not \; because MariaDB treats backslash as an escape character by default, a string value ending in a backslash could also break out of its literal.
MariaDB - column mode (COLUMN_PER_KEY). ColumnFilterMapper fell back to the raw, unescaped key when the driver could not quote it as an identifier (e.g. a character).
The filter key is the runtime injection surface; both stores' search() (including pgvector's HYBRID mode) and removeAll(Filter) are affected. Add/upsert operations a parameterized and not affected.
Impact
Applications that allow attacker-influenced metadata filter keys (e.g. use LLM-generated filters) to reach these stores are exposed to SQL injection: blind data exfiltration, denial of service via sleep functions, and - through `remove deletion of arbitrary rows. Applications using only hard-coded, developer-defined filter keys are not reachable.
Patches
Fixed in langchain4j-mariadb and langchain4j-pgvector 1.16.3-beta26:
- JSON filter keys are escaped before being embedded in the SQL string lit
quotes doubled, correct for PostgreSQL standard_conforming_strings = on; MariaDB: backslash and single quote).
- MariaDB string values escape both
\and'. - Column-mode keys are validated/quoted as identifiers and rejected when u
concatenated as raw SQL.
Workarounds
- Do not pass untrusted input as metadata filter keys.
- Restrict filter keys to a known allow-list at the application layer.
References
- pgvector:
JSONFilterMapper,ColumnFilterMapper - MariaDB:
JSONFilterMapper,MariaDbFilterMapper,ColumnFilterMapper
AnalysisAI
SQL injection in LangChain4j's langchain4j-mariadb and langchain4j-pgvector embedding stores allows authenticated attackers who can influence metadata filter keys to execute arbitrary SQL via EmbeddingSearchRequest.filter(), enabling blind data exfiltration, denial of service through sleep functions, and deletion of arbitrary rows via removeAll(Filter). The flaw stems from string-concatenated filter keys (and MariaDB string values) being placed into SQL without escaping, and is particularly relevant where filter keys originate from LLM-generated output or untrusted user input. No public exploit identified at time of analysis, though the vendor advisory documents working proof-of-concept payloads such as pg_sleep(1) injection.
Technical ContextAI
LangChain4j is a Java framework for building LLM-powered applications, with optional embedding-store integrations for vector similarity search. The affected components are the Maven artifacts dev.langchain4j:langchain4j-mariadb and dev.langchain4j:langchain4j-pgvector, which provide MariaDB and PostgreSQL/pgvector backends. The root cause maps to CWE-89 (SQL Injection): JSONFilterMapper embeds filter keys into single-quoted JSON path literals such as (metadata->>'<key>') in pgvector and '$.<key>' in MariaDB without escaping single quotes, and ColumnFilterMapper in COLUMN_PER_KEY mode uses the key as a raw, unvalidated SQL identifier (<key>::<type>). Additionally, MariaDbFilterMapper.formatValue() escapes single quotes but not backslashes, and because MariaDB treats backslash as an escape character by default, string values ending in a backslash can also escape their literal. Both search() (including pgvector HYBRID mode) and removeAll(Filter) execute these unsafe statements, while add/upsert operations remain parameterized and safe.
RemediationAI
Vendor-released patch: upgrade langchain4j-mariadb and langchain4j-pgvector to 1.16.3-beta26 (or the matching branch fix: 1.2.1-beta8, 1.5.1-beta11, or 1.11.8-beta19 if pinned to an older line) per https://github.com/langchain4j/langchain4j/security/advisories/GHSA-2mfg-cc43-9pcj, which escapes JSON filter keys (doubled single quotes for PostgreSQL with standard_conforming_strings=on; backslash and single quote for MariaDB), escapes both backslash and single quote in MariaDB string values, and validates or quotes column-mode keys as identifiers rather than concatenating them as raw SQL. If immediate upgrade is not possible, the documented workarounds are to never pass untrusted input as metadata filter keys and to enforce a strict server-side allow-list of permitted filter keys at the application layer before invoking EmbeddingSearchRequest.filter() - the trade-off is that LLM-driven or user-driven dynamic filter schemas must be locked down, which may reduce query flexibility for agent workflows. As a defense-in-depth measure, restrict the database role used by the embedding store so that pg_sleep, sensitive table reads, and DELETE on unrelated tables are constrained, limiting the impact of any residual injection paths.
More in PostgreSQL
View allPostgreSQL libpq functions PQescapeLiteral(), PQescapeIdentifier(), PQescapeString(), and PQescapeStringConn() improperl
An issue was discovered in Appsmith before 1.52. Rated critical severity (CVSS 9.8), this vulnerability is remotely expl
Argument injection vulnerability in PostgreSQL 9.2.x before 9.2.4, 9.1.x before 9.1.9, and 9.0.x before 9.0.13 allows re
Unauthenticated arbitrary file write in Splunk Enterprise (below 10.2.4 and 10.0.7) and Splunk Cloud Platform (below 10.
Unauthenticated SQL injection in Sangoma Switchvox SMB Edition 8.3 (build 104997) lets remote attackers execute arbitrar
PostgreSQL versions before 9.2.22, 9.3.18, 9.4.13, 9.5.8 and 9.6.4 are vulnerable to incorrect authentication flaw allow
The build_tablename function in pgsql.c in the PostgreSQL (aka pgsql) extension in PHP through 5.6.7 does not validate t
A vulnerability in the h2oai/h2o-3 REST API versions 3.46.0.4 allows unauthenticated remote attackers to execute arbitra
In PostgreSQL 9.3 through 11.2, the "COPY TO/FROM PROGRAM" function allows superusers and users in the 'pg_execute_serve
Unauthenticated SQL injection in Vendure Shop API allows remote attackers to execute arbitrary SQL commands against the
Parse Server is an open source http web server backend. Rated critical severity (CVSS 10.0), this vulnerability is remot
Hard-coded default PostgreSQL credentials shipped in the docker-compose.yaml of langgenius Dify through version 1.5.1 al
Same weakness CWE-89 – SQL Injection
View allSame technique Denial Of Service
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-43027
GHSA-2mfg-cc43-9pcj