Skip to content

SSRF in Webhook Dispatcher — No URL Restrictions Enables Internal Network Access #3957

Description

@atul-upadhyay-7

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

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions