Skip to content

security: webhook SSRF filter bypassable (follow-up to #295, #202) #333

Closed

Description

@ajianaz

Problem (crates/trapfalld/src/alert.rs:156-200)

  • DNS rebinding/TOCTOU: the check resolves via to_socket_addrs, reqwest resolves again for the send.
  • addrs.iter().all(ip_is_private) (line ~181): a host with one public and one private record passes; should be any.
  • ip_is_private misses IPv4-mapped IPv6 (::ffff:169.254.169.254), ULA fc00::/7, fec0::/10, 64:ff9b::/96, 0.0.0.0/8, 192.0.0.0/24, 198.18.0.0/15, multicast/broadcast.
  • Rule creation (server.rs:628) does no URL validation.
  • Full webhook URL (often contains Slack/Discord token) is logged at alert.rs:122,144; log host only.

Fix

Canonicalize with to_canonical(), reject non-global addresses, resolve once and pin via ClientBuilder::resolve_to_addrs or a filtering dns::Resolve. Validate URL at rule creation. HTTPS-only and no redirects are already good.

Found in static audit of develop @ db3ca67.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions