domain: webmention source is fetched without a resolved-address SSRF check #52
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
rosa/vernier#52
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found during a code review of the
domaincrate.Location:
crates/domain/src/services.rs:1054(receive_webmention)Severity: Security — SSRF
Problem
receive_webmentionpasses the raw source URL to the verify job with no global-address check beyondWebmentionTarget::parse, which only rejects the literal localhost and non-global IP literals and never resolves the hostname. There is no connect-level resolved-IP guard in the hardened client, so a source whose DNS resolves to a private address is fetched.Failure scenario
An attacker POSTs a webmention with
source=http://attacker.example/whose A record points at169.254.169.254, plus a valid public target. The verify job GETs the source and reaches an internal address.Suggested fix
Validate the resolved IP at connect time (reject non-global addresses after DNS resolution) in the outbound client, not just the URL literal.
Triage: confirmed against current
main.hardened_clientincrates/infra/src/jobs/webmention.rsre-validates each redirect hop withWebmentionTarget::parse, which checks the URL literal only — nothing guards the resolved IP, so a hostname whose A record points at a private address is fetched. Routing to a human because the fix needs care: resolve-then-check has a DNS-rebinding TOCTOU, so the validated IP must be pinned for the actual connection (e.g. a custom resolver that filters non-global addresses at connect time).