domain,infra: Guard webmention fetches with a connect-time resolved-IP check #90
No reviewers
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
rosa/vernier!90
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/52-webmention-source-ssrf-guard"
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?
Closes #52.
Problem
The outbound webmention client validated only the URL literal
(
WebmentionTarget::parse), never the resolved IP. Asource, redirect hop, ordiscovered endpoint whose DNS pointed at a private, loopback, or link-local
address (e.g.
169.254.169.254cloud metadata) was connected to — an SSRF.Fix
is_global_ip(IpAddr) -> boolpolicy (handling IPv4-mappedIPv6), reused by both the literal
WebmentionTarget::parsecheck and the newconnect-time resolver.
names via
tokio::net::lookup_hostand drops non-global addresses. reqwestconnects only to the returned addresses, so the checked IP is the connected
IP — no DNS-rebinding TOCTOU. This covers discovery, delivery, verification,
and every redirect hop.
GlobalGuardBlockedsentinel, preserved on the reqwest connect error'ssource()chain. The verify job recognises it and aborts terminally ratherthan retrying a source that will never be permitted.
Scope notes
job distinguishes the block and aborts terminally.
Tests
is_global_ipreject/accept cases (incl. IPv4-mapped private andmetadata IPs) and
WebmentionTarget::parsecases.resolve_global_onlykeep/block cases andchain_contains_blockrecovering the sentinel through a wrapping error's
source().mise run ciandmise run clippypass.Plan and research:
thoughts/shared/plans/007_…andthoughts/shared/research/008_….