CVE-2026-76848 Overview
CVE-2026-76848 is a SQL injection vulnerability [CWE-89] in the TypeORM object-relational mapper for Node.js. The flaw resides in SelectQueryBuilder.distinctOn, which accepts an array of strings and interpolates them directly into a SELECT DISTINCT ON (...) clause for PostgreSQL-family drivers. The createSelectDistinctExpression function in src/query-builder/SelectQueryBuilder.ts performs no escaping, quoting, identifier validation, or allowlist enforcement. Applications that forward client-controlled values into distinctOn allow remote attackers to inject arbitrary SQL expressions, including correlated subqueries. This enables data extraction anywhere the application's database role can reach through boolean or time-based inference.
Critical Impact
Remote, unauthenticated attackers can exfiltrate database contents through injected SQL expressions independently of the entity being queried.
Affected Products
- TypeORM object-relational mapper for Node.js and TypeScript
- Applications using PostgreSQL-family drivers with SelectQueryBuilder.distinctOn
- Any deployment forwarding client-controlled values into the distinctOn API
Discovery Timeline
- 2026-08-24 - CVE-2026-76848 published to NVD
- 2026-08-24 - Last updated in NVD database
Technical Details for CVE-2026-76848
Vulnerability Analysis
The vulnerability originates in the TypeORM query builder's handling of distinctOn arguments. SelectQueryBuilder.distinctOn stores its string array on the expression map without validation. When the query is compiled for PostgreSQL, createSelectDistinctExpression joins the array and interpolates the result directly into the generated statement as SELECT DISTINCT ON (values). The values never pass through replacePropertyNames or the driver's escape helper.
Because the interpolation point is a parenthesized SQL expression list rather than an identifier-only position, supplied elements may carry arbitrary expressions. Attackers can embed correlated subqueries that read from unrelated tables. The allowlist check validateOrderByCondition, which guards the orderBy family in the same class, is not applied to this code path.
Root Cause
The root cause is missing input sanitization in a code path that developers may reasonably treat as identifier-only. The API surface accepts strings intended to represent column names, but the compiler interpolates those strings into a SQL expression context. This mismatch between the intended contract of the API and the actual interpolation site enables SQL injection. Comparable guard logic exists elsewhere in SelectQueryBuilder but was not extended to distinctOn.
Attack Vector
Exploitation requires an application that forwards a client-controlled value into distinctOn, for example a query endpoint that lets a caller choose a deduplication column. The attacker supplies a crafted string containing a subquery or boolean expression instead of a plain column identifier. The injected expression executes with the database privileges of the application role. Attackers use boolean-based or time-based inference to extract data from tables outside the queried entity. See the VulnCheck SQL Injection Advisory for technical details.
Detection Methods for CVE-2026-76848
Indicators of Compromise
- PostgreSQL query logs containing SELECT DISTINCT ON ( followed by subqueries, CASE expressions, pg_sleep, or comparison operators in place of a plain column identifier
- Repeated queries against the same endpoint that differ only in the distinctOn parameter, consistent with boolean-based blind extraction
- Anomalous query latency patterns tied to time-based inference using pg_sleep or similar functions
Detection Strategies
- Perform source code review to locate every call to SelectQueryBuilder.distinctOn and verify that arguments derive from a server-side allowlist, not from request input
- Enable PostgreSQL statement logging and alert on DISTINCT ON clauses containing parentheses, quotes, or SQL keywords beyond identifier characters
- Deploy web application firewall rules that flag request parameters mapped to deduplication or grouping options when they contain SQL metacharacters
Monitoring Recommendations
- Baseline the shape of legitimate DISTINCT ON queries produced by the application and alert on deviations
- Monitor database role activity for cross-table reads that do not match the application's expected access pattern
- Correlate application logs and database logs to attribute injected queries to specific user sessions and source addresses
How to Mitigate CVE-2026-76848
Immediate Actions Required
- Audit application code for calls to distinctOn and remove any path that accepts client-controlled input for this argument
- Replace direct user input with a server-side allowlist mapping request values to fixed, validated column identifiers
- Rotate database credentials if query logs show evidence of injected DISTINCT ON expressions
Patch Information
Monitor the TypeORM GitHub repository and the VulnCheck advisory for the fixed version. Upgrade to the patched TypeORM release once available and redeploy affected services. Review the vulnerable interpolation logic in SelectQueryBuilder.ts when validating the fix.
Workarounds
- Wrap distinctOn calls with an application-level allowlist that rejects any value not matching a known column name for the target entity
- Apply least-privilege principles to the database role used by the application to limit cross-table exposure during blind extraction
- Disable or remove API endpoints that expose deduplication column selection to untrusted clients until a patched version is deployed
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

