Description
The webhook dispatcher (lib/webhook/dispatcher.js) performs outbound HTTP requests to arbitrary URLs provided by admin users (line 16: const response = await fetch(url, {...})). There is no validation against:
- Internal/private IP addresses (127.0.0.1, 10.x.x.x, 172.16.x.x, 192.168.x.x)
- Cloud metadata endpoints (169.254.169.254 on AWS/GCP/Azure)
- Localhost or loopback addresses
- Internal service hostnames
- Non-standard ports
The webhook URL is set via POST /api/webhooks with only a basic new URL() validation, which accepts any valid URL including http://169.254.169.254/latest/meta-data/.
Impact
An attacker can:
- Steal AWS IAM credentials via cloud metadata endpoints
- Scan the internal network by targeting internal IPs
- Access internal services not exposed to the internet
- Exfiltrate environment variables and secrets from cloud metadata
- Trigger SSRF against any HTTP endpoint reachable from the server
Combined with the privilege escalation issue, any newly registered user can become admin and exploit this.
Location
lib/webhook/dispatcher.js, Lines 16-26
Suggested Fix
- Reject private/loopback IP ranges using a library like
ip-cidr or custom validation
- Block cloud metadata IP ranges (169.254.0.0/16)
- Restrict allowed ports (80, 443 only)
- Add DNS resolution validation to prevent DNS rebinding attacks
- Consider using an outbound proxy/firewall with an allowlist of permitted destinations
Description
The webhook dispatcher (
lib/webhook/dispatcher.js) performs outbound HTTP requests to arbitrary URLs provided by admin users (line 16:const response = await fetch(url, {...})). There is no validation against:The webhook URL is set via
POST /api/webhookswith only a basicnew URL()validation, which accepts any valid URL includinghttp://169.254.169.254/latest/meta-data/.Impact
An attacker can:
Combined with the privilege escalation issue, any newly registered user can become admin and exploit this.
Location
lib/webhook/dispatcher.js, Lines 16-26Suggested Fix
ip-cidror custom validation