# OneUptime ClickHouse vulnerable to SQL Injection via unvalidated column identifiers in sort, select, and groupBy parameters

OneUptime's StatementGenerator interpolated unvalidated sort/select/groupBy keys as ClickHouse Identifiers, letting authenticated users inject SQL into analytics queries.

- Payout: Research
- Severity: high
- Program: OneUptime
- Found by: vnykmshr
- Disclosed: 2026-03-18
- CVE: CVE-2026-33142
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-gcg3-c5p2-cqgg
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-gcg3-c5p2-cqgg
- Tags: area:web3 domain:api impact:data-leak impact:integrity kind:research platform:ghsa sev:high tech:nodejs technique:incomplete-fix technique:source-review vuln:sqli

**Target:** ClickHouse analytics query builder (StatementGenerator) via BaseAnalyticsAPI list/aggregate endpoints
**Root cause:** toSortStatement, toSelectStatement, and toGroupByStatement iterate user-controlled object keys and pass them as ClickHouse Identifier parameters, which are substituted unescaped, without calling model.getTableColumn() validation.
**Steps:**
1. Authenticate and reach any analytics endpoint backed by BaseAnalyticsAPI.getList() or getAggregate() (logs, metrics, spans, exceptions).
2. Send a request body with `sort`, `select`, or `groupBy` containing a crafted object key instead of a real column name.
3. The key is deserialized in BaseAnalyticsAPI.ts and passed to StatementGenerator, where it becomes a ClickHouse Identifier substituted directly into the query.
4. Injected SQL executes against ClickHouse, allowing read/modify/delete of analytics data.
**How found:** Noticed the prior fix for GHSA-p5g2-jm85-8g35 added column validation only to _aggregateBy, then audited sibling query-construction methods in StatementGenerator and found toSortStatement, toSelectStatement, and toGroupByStatement lacked the same getTableColumn() check that toWhereStatement already had.
**Exploitation:** An authenticated user crafts malicious object keys in sort/select/groupBy of an analytics list or aggregate request; these flow unvalidated into ClickHouse Identifier substitution, yielding arbitrary SQL execution over the analytics datastore.
**Insight:** When a patch adds validation to one query builder method, enumerate every sibling method that iterates user-controlled keys into the same sink; ClickHouse Identifier params are unescaped by design, so any unvalidated key is direct SQLi.

