GitHub Advisoryadvisory · NuGet

GHSA-rfx3-98h7-v3xp Marten's LINQ provider has SQL injection via unescaped string literals

CRITICAL Published 2026-09-17 Modified 2026-09-17 Official page ↗
Aliases
CVE-2026-75513
Ecosystem
NuGet
Packages
Marten
Severity
Critical
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:L
Weaknesses
CWE-89
Reviewed
2026-09-17

Affected packages

• NuGet Marten: >= 7.0.0, < 9.13.0 → fixed in 9.13.0

Description

Several code paths in Marten's LINQ provider and tenant-management internals interpolated a runtime, potentially attacker-influenced value into generated SQL as a single-quoted string literal without escaping or parameterization. A value containing a single quote (`'`) could break out of the literal and inject arbitrary SQL. The primary vector is a `Dictionary` indexer key used in a `Where` filter — `Where(x => x.Attributes[key] == v)` — a common "filter by attribute name" / EAV pattern. It is confirmed with an executed proof-of-concept and yields filter / multi-tenant authorization bypass (returning other tenants' rows) and blind data exfiltration. Where the application permits `;`-batched statements (Npgsql default), data modification is also possible. Affected sinks • `Linq/Members/Dictionaries/DictionaryItemMember.cs` — dictionary indexer key (primary, confirmed PoC) • `Linq/Members/Dictionaries/DictionaryContainsKeyFilter.cs` — `Dictionary.ContainsKey(key)` (Newtonsoft serializer only; System.Text.Json escapes the quote) • `Linq/Parsing/SelectParser.cs` — a constant string projected through `Select(x => new { L = runtimeString })` • `Internal/Operations/DeleteAllForTenant.cs` — tenant id reaching per-tenant projection teardown via `IEventStore.DeleteProjectionProgressAsync` (an in-code comment wrongly claimed the value was validated) • `Schema/DatabaseScopedTenantPartitions.cs` — tenant id inlined into `FOR VALUES IN ('...')` partition DDL • `Events/Daemon/Internals/EventLoader.cs` (defense-in-depth) — per-tenant partition-pruning literal Proof of concept (primary vector) Benign: `x.Attributes["nonexistent-key"] == "v"` returns 0 rows. Attack: `x.Attributes["nonexistent' = '' or 1=1 --"] == "v"` returns all rows. Generated SQL: ``` select d.data from public.mt_doc_doc as d where d.data -> 'Attributes' ->> 'x' or 1=1 --' = :p0; ``` Fix Each sink now escapes embedded single quotes (`.Replace("'", "''")`, mirroring the existing `Ordering.BuildNgramRankExpression`) or binds the value as a parameter (`DeleteAllForTenant`). Where a literal is retained for partition pruning, escaping preserves plan-time pruning while closing the injection. Regression tests lock down each vector. Workarounds Until upgrading: do not pass untrusted input as a dictionary indexer key / `ContainsKey` argument / `Select` constant, nor as a tenant id into projection teardown or provisioning; and disable multi-statement command batching to limit blast radius. Credit Reported privately and responsibly by an external security researcher with an executed PoC. Additional sinks found during the follow-up LINQ-wide audit.

Related

Alias · CVE (1)

  • CVE-2026-75513 Marten is a .NET Transactional Document DB and Event Store on PostgreSQL. vulnerability

Weakness · CWE (1)

  • CWE-89 Improper Neutralization of Special Elements used in an SQL Command weakness

References