CVE-2026-75513 Overview
CVE-2026-75513 is a SQL injection vulnerability [CWE-89] in Marten, a .NET transactional document database and event store built on PostgreSQL. Affected versions from 7.0.0 through 9.12.x interpolate runtime, attacker-controllable strings into single-quoted SQL literals across several LINQ and tenant-management code paths. The primary confirmed vector is a dictionary indexer key used by Where filters in DictionaryItemMember.cs. A crafted single quote breaks out of the generated literal, enabling filter bypass, multi-tenant authorization bypass, and blind data exfiltration. Deployments that permit semicolon-batched Npgsql statements may also allow data modification. The issue is fixed in version 9.13.0.
Critical Impact
Attackers with low-privilege access can bypass tenant isolation, exfiltrate cross-tenant data, and — where multi-statement batching is enabled — modify PostgreSQL data.
Affected Products
- Marten versions 7.0.0 through 9.12.x (JasperFx/marten)
- Applications using Marten LINQ dictionary indexer filters (DictionaryItemMember)
- Multi-tenant deployments invoking IEventStore.DeleteProjectionProgressAsync or using Newtonsoft-based DictionaryContainsKeyFilter
Discovery Timeline
- 2026-09-16 - CVE-2026-75513 published to NVD
- 2026-09-16 - Last updated in NVD database
Technical Details for CVE-2026-75513
Vulnerability Analysis
Marten generates PostgreSQL statements dynamically from LINQ expressions and tenant metadata. In several code paths, string values sourced from runtime input are concatenated directly into single-quoted SQL literals without escaping or parameterization. Because PostgreSQL treats '' as an escaped single quote inside a literal, an attacker supplying a value containing ' terminates the intended literal early and appends arbitrary SQL fragments.
Exploitation yields three concrete outcomes. Filter predicates can be neutralized or rewritten, returning rows the caller should not access. Tenant discriminators can be replaced, defeating multi-tenant isolation. When the Npgsql connection permits semicolon-separated batches, injected statements can perform INSERT, UPDATE, or DELETE operations. Blind data exfiltration is feasible even when responses are not directly reflected, using boolean or timing side channels.
Root Cause
The root cause is unsafe string concatenation into SQL literals across multiple sinks: src/Marten/Linq/Members/Dictionaries/DictionaryItemMember.cs, SelectParser.cs, DatabaseScopedTenantPartitions.cs, DeleteAllForTenant.cs, DictionaryContainsKeyFilter.cs (Newtonsoft serializer path only; System.Text.Json is not affected), and Events/Daemon/Internals/EventLoader.cs. Several sinks previously relied on an implicit assumption that tenant identifiers were pre-validated by AdvancedOperations.AssertValidPostgresqlIdentifiers. That assertion only runs at partition registration, not on every reachable code path.
Attack Vector
An attacker with authenticated, low-privilege application access submits input that reaches a Marten LINQ dictionary indexer, a ContainsKey filter, or a tenant-scoped delete or partition operation. The payload includes a single quote to escape the generated literal, followed by attacker-chosen SQL. No user interaction is required beyond normal API usage.
// Vulnerable pattern (pre-patch) in EventLoader.cs
builder.Append(" and d.tenant_id = '");
builder.Append(TenantFilterValue); // unescaped concatenation
builder.Append("'");
// Patched pattern (9.13.0)
builder.Append(" and d.tenant_id = '");
builder.Append(TenantFilterValue.Replace("'", "''"));
builder.Append("'");
Source: GitHub Commit 61882d0
Detection Methods for CVE-2026-75513
Indicators of Compromise
- PostgreSQL query logs containing dictionary indexer or tenant filter literals with embedded single quotes, --, /*, or ; sequences
- Unexpected cross-tenant row reads or writes appearing in Marten-generated statements against mt_events or projection tables
- IEventStore.DeleteProjectionProgressAsync calls with unusual tenant identifier strings
- Application errors from Npgsql citing malformed SQL near tenant or dictionary-key literals
Detection Strategies
- Enable PostgreSQL log_statement = 'all' in staging and parse for single-quote breakouts inside Marten-generated literals
- Static review of any caller path that supplies user-controlled strings to Marten Where clauses using dictionary indexers or ContainsKey
- Alert on Npgsql commands containing multiple statements (;) when the application does not intentionally use batched SQL
Monitoring Recommendations
- Baseline expected tenant identifiers and alert on values outside [A-Za-z0-9_]
- Forward PostgreSQL and application logs to a centralized analytics platform and correlate anomalous query shapes with authenticated user identity
- Track query volume and row-count anomalies on multi-tenant projection tables
How to Mitigate CVE-2026-75513
Immediate Actions Required
- Upgrade Marten to version 9.13.0 or later across all services and background workers
- Audit application code for callers that pass user-controlled strings into LINQ dictionary indexers or tenant-scoped APIs
- Disable multi-statement batching on Npgsql connection strings unless explicitly required
- Rotate any credentials or secrets that may have been exposed through cross-tenant reads
Patch Information
The fix is included in Marten Release 9.13.0. Details on the affected sinks and remediation are documented in GitHub Security Advisory GHSA-rfx3-98h7-v3xp and Pull Request #4911. The patch escapes embedded single quotes in defense-in-depth sinks and converts tenant identifiers to bound parameters in DeleteAllForTenant.
Workarounds
- Validate and reject any user-controlled string containing ', ;, --, or /* before it reaches Marten query construction
- Restrict tenant identifiers to [A-Za-z0-9_] at the application boundary and reject non-conforming values
- Remove or replace usage of the Newtonsoft-based DictionaryContainsKeyFilter with the System.Text.Json path where feasible
# Example Npgsql connection string with multi-statement batching disabled
# (removing Multiplexing/CommandText concatenation reduces post-exploitation impact)
Host=db.internal;Database=app;Username=app;Password=***;\
Include Error Detail=true;No Reset On Close=false
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.