Severity by source
CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
AV:L because attacker must control an application-internal argument; AC:H for the dual precondition of streaming API use and externally influenced comment; C:H for full data access within connection role scope.
Primary rating from Vendor (EEF).
CVSS VectorVendor: EEF
Lifecycle Timeline
2DescriptionCVE.org
Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') vulnerability in elixir-ecto postgrex allows SQL Injection via the :comment option of Postgrex.stream/4. An attacker who can influence that value can close the comment delimiter with */ and extend the streamed statement with their own clauses, which execute under the connection's role. Ecto exposes the same option through Ecto.Repo.stream/2.
Postgrex appends the comment by concatenating it into the statement text sent in the Parse message, without escaping or rejecting */. The option is validated by comment_not_present!/1 at every other execution point; stream/4 never calls it. Because Parse accepts a single command, the injection is confined to the streamed statement and further statements cannot be chained.
This issue affects postgrex: from 0.19.3 before 0.22.4.
AnalysisAI
SQL injection in Postgrex (elixir-ecto's PostgreSQL driver) versions 0.19.3 through 0.22.3 allows an attacker who controls the :comment option passed to Postgrex.stream/4 or Ecto.Repo.stream/2 to close the SQL comment delimiter with */ and inject arbitrary SQL clauses into the streamed statement, executing them under the existing database connection's role. The root cause is a missing call to the comment_not_present!/1 guard in stream/4, an oversight absent from every other execution path in the library. No public exploit code has been identified and no active exploitation appears in the CISA KEV catalog; the CVSS 4.0 vector (AV:L, AT:P) signals that exploitation requires specific, non-default application architecture.
Technical ContextAI
Postgrex is the primary PostgreSQL driver for the Elixir ecosystem, used directly and as the backing adapter for Ecto (the widely-used Elixir data mapping and query layer). The :comment option exists to embed tracing or diagnostic metadata into the SQL comment prepended to each statement. Postgrex implements this by string-concatenating the caller-supplied comment into the statement text sent in the PostgreSQL wire-protocol Parse message. Every other execution entry point (query, execute, prepare, etc.) calls the internal comment_not_present!/1 validator, which raises an error if the comment string contains the */ delimiter-closing sequence or null bytes. The stream/4 function - and by extension Ecto.Repo.stream/2 - never invoked this guard, leaving the code path unprotected. CWE-89 (Improper Neutralization of Special Elements in SQL Commands) applies directly: user-supplied data reaches the SQL layer without sanitization. Critically, PostgreSQL's Parse message accepts exactly one command, so the injected clauses are constrained to modifying the single streamed statement (e.g., appending UNION, WHERE, or RETURNING clauses) - multi-statement chaining is architecturally prevented. Affected CPE: cpe:2.3:a:elixir-ecto:postgrex:*:*:*:*:*:*:*:* from 0.19.3 to 0.22.3.
RemediationAI
Upgrade Postgrex to version 0.22.4 or later, which adds the missing comment_not_present!/1 call to the stream/4 code path; the fix is confirmed in upstream commits https://github.com/elixir-ecto/postgrex/commit/e1ecba618ddea4cee2556bd6ad9b6285e05f9d3c and https://github.com/elixir-ecto/postgrex/commit/4011be852c99dc61ddb98cb01aa41e8775a0e3dd. If an immediate upgrade is not feasible, audit all call sites of Postgrex.stream/4 and Ecto.Repo.stream/2 and ensure the :comment option value is always a hard-coded developer string - never derived from user-supplied input, request parameters, tenant identifiers, or any other external source; this eliminates the injection surface without patching. As a secondary application-layer control, strip or reject any occurrence of */ in comment values before they reach the API, though this is less reliable than the upstream fix since new call sites may be added without following the convention.
Same weakness CWE-89 – SQL Injection
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-54476