Skip to content

Security: SSRF via unvalidated webhook URLs #346

@OneStepAt4time

Description

@OneStepAt4time

Summary

Webhook URLs from AEGIS_WEBHOOKS env var or config are used directly in fetch() with zero validation. An attacker who can set the env var or modify config can trigger requests to internal services (AWS metadata, localhost Aegis API, etc.).

Details

  • File: src/channels/webhook.ts:52-63, 130-137
  • Severity: Critical
  • URLs are never checked for scheme, host, or IP range
  • fromEnv() only checks Array.isArray() but doesn't validate endpoint object structure (missing url field, non-string url)
  • Related: src/server.ts:867-909 screenshot URL validation is bypassable via DNS rebinding (hostname checked at parse time, but DNS resolves to a different IP at fetch time)
  • Related: IPv6-mapped IPv4 addresses (::ffff:127.0.0.1) bypass the IPv4 private-range checks in screenshot validation

Attack Vectors

  1. AEGIS_WEBHOOKS=[{"url":"http://169.254.169.254/latest/meta-data/"}] — cloud metadata
  2. AEGIS_WEBHOOKS=[{"url":"http://localhost:9100/v1/sessions"}] — internal Aegis API
  3. DNS rebinding for screenshot URLs: resolve to public IP at validation, private IP at fetch

Suggested Fix

  • Reject non-HTTPS schemes for webhooks
  • Resolve DNS and validate resulting IP against RFC 1918 + loopback + link-local + CGNAT ranges
  • Validate webhook endpoint objects with Zod schema
  • For screenshots: add post-navigation IP check or configure Chromium to block private IPs

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions