CVE-2026-66838 is a high severity SQL injection in the Elixir Postgrex library. The :comment option of Postgrex.stream/4 is not sanitized, so a value an attacker controls can extend a streamed query. The record scores it 8.2 and the advisory 5.9. Upgrade Postgrex to 0.22.4 and stop passing user input as a comment.
What's affected
Postgrex from 0.19.3 before 0.22.4. The patched version is 0.22.4, per the Erlang Ecosystem Foundation CNA entry and the elixir-ecto advisory. The advisory also says Ecto.Repo.stream/2 forwards the same option, so Ecto users who pass the option are in scope.
The sources disagree on severity. The record says CVSS 8.2 (High). The GitHub advisory rates it Moderate with a CVSS score of 5.9. The weakness is CWE-89. The advisory text does not explain the gap, and the precondition that an attacker must influence the comment value is the part to check in your code.
The advisory describes the flaw plainly. Postgrex builds the statement for a streaming query by joining the query text, a comment opener, the comment value and a comment closer. A comment cannot be parameterized, so the value goes in without escaping. Postgrex.query/4 rejects the same value with an error. Only the streaming path is open.
How to check if you're exposed
First, find the version. In an Elixir project:
mix deps | grep postgrex
grep postgrex mix.lock
Anything from 0.19.3 up to but not including 0.22.4 is in range. Then search your code for the :comment option on Postgrex.stream/4 and Ecto.Repo.stream/2. If you never set it, the vulnerable path is not reachable in your code, even though the library version is old.
Applications are affected where the comment carries request, tenant or user supplied metadata. A common pattern is to tag queries with a request ID for tracing. If any part of that tag comes from a user, check it.
What to do now
- Upgrade Postgrex to 0.22.4 or later and rebuild your release.
- Search for :comment on stream calls and confirm that no user controlled value reaches it.
- If you must tag queries, build the tag from values you generate, such as an internal request ID, not from client input.
- Use a database role with only the permissions the application needs, since injected clauses run under that role.
- Paste your dependency file into the free in-browser scan at gold.safeguard.sh/scan to see which of your projects pull in an affected version.
Why it matters
SQL injection lets input change the meaning of a query. A comment looks like a harmless place for a label, so developers pass strings there freely. But if the string can close the comment, everything after it is read as SQL.
The advisory says an attacker controlling the option can read tables the database role can access and can change state through volatile functions in an injected set operation. Because the protocol accepts one command per message, a second statement cannot be chained, which limits the shape of the attack. The write direction through COPY is more restricted still. The role's privileges decide the blast radius.
No source I reviewed says this CVE is exploited in the wild, and the record's KEV flag is false.
Try it yourself
Click through it at your own pace, or open it full screen.
Quick check
Does Postgrex.query/4 have the same problem?
The advisory says the same comment passed to Postgrex.query/4 raises an error. The unsanitized path is the streaming one.
Am I safe if I never set :comment?
The vulnerable path needs the option to carry attacker influenced data, so unused means unreachable. Upgrade anyway.
Sources
- Erlang Ecosystem Foundation CNA entry for CVE-2026-66838
- elixir-ecto advisory GHSA-3gww-3f36-2388
- OSV entry EEF-CVE-2026-66838
Last reviewed: 18 October 2026.