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.
{
"severity": "CRITICAL",
"cwe_ids": [
"CWE-74",
"CWE-89"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-14T20:46:26Z",
"nvd_published_at": null
}