Marten's full-text search APIs interpolated the user-supplied regConfig parameter directly into the generated SQL without parameterization or validation, making every code path that exposes regConfig to untrusted input a SQL injection sink.
IQuerySession.SearchAsync<T>(string searchTerm, string regConfig, ...)IQuerySession.PlainTextSearchAsync<T>(...)IQuerySession.PhraseSearchAsync<T>(...)IQuerySession.WebStyleSearchAsync<T>(...)IQuerySession.PrefixSearchAsync<T>(...)IQueryable<T>.Where(x => x.Search(term, regConfig)) and the matching PlainTextSearch / PhraseSearch / WebStyleSearch / PrefixSearch extension methodsIn the affected versions, FullTextWhereFragment renders the WHERE-clause SQL by string interpolation:
private string Sql =>
$"to_tsvector('{_regConfig}'::regconfig, {_dataConfig}) @@ {_searchFunction}('{_regConfig}'::regconfig, ?)";
_regConfig arrives unchanged from the public API surface above. Any value containing a single quote terminates the SQL literal and lets an attacker append arbitrary PostgreSQL.
regConfig set to attacker-controlled input)| Goal | Payload |
|---|---|
| Time-based blind | english'::text); SELECT pg_sleep(5); -- |
| Information disclosure | english'; SELECT version(); -- |
| DDL execution | english'; DROP TABLE mt_doc_article; -- |
All five overloads listed above produced SQL containing the verbatim payload.
SELECT statements and exfiltrate database contents through error channels, response timing, or — if the application surfaces query results — directly.UPDATE, DELETE, and pg_sleep-style denial-of-service payloads succeed under the same vector. Concrete impact depends on the database role used by the Marten connection string.regConfig parameter (e.g. a ?lang= query string mapped to regConfig). Applications that hard-code regConfig to a compile-time constant are not exploitable.Fixed in Marten 8.36.1 (and forward) by #4343.
FullTextWhereFragment now validates regConfig against ^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)?$ (a simple PostgreSQL identifier, optionally schema-qualified, capped at NAMEDATALEN-1 per side) and throws ArgumentException for anything else. The default value ("english"), schema-qualified configs ("pg_catalog.english"), and the standard PostgreSQL text-search configurations all continue to work.
If users cannot upgrade immediately, do one of the following at the application boundary:
regConfig to a compile-time constant ("english", "simple", …) and never accept it from request input.regConfig value before passing it to Marten — e.g. against the same regex as the patch (^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)?$) or against an allowlist of PostgreSQL configurations the application actually uses.regConfig argument from the call site so Marten falls back to the safe default.FullTextWhereFragment.csfull_text_regconfig_sql_injection.csReported privately to the JasperFx team with a working proof of concept covering all five affected overloads.
| Score | Percentile |
|---|---|
| 0.04% | 11.66% |
| Base score | Version | Severity | Vector |
|---|---|---|---|
| 9.8 | 3.1 | — |
|
| Type | Value |
|---|---|
| GHSA | GHSA-vmw2-qwm8-x84c ↗ |
| CVE | CVE-2026-45288 ↗ |
Vulnerable version ranges and first patched releases as published by GitHub.
| Ecosystem | Package | Vulnerable range | First patched | Vulnerable functions |
|---|---|---|---|---|
| nuget | Marten | <= 8.36 | 8.37.0 | — |