Federation runs with allowPrivateAddress:true (own host svemagie.net resolves to
a LAN RFC-1918 address, required for own-site federation), which disables
Fedify's blanket SSRF guard. Attacker-sourced URLs (quoteUrl, author URLs, etc.)
flowing through lookupWithSecurity could reach internal services.
- new lib/ssrf-guard.js: assertLookupAllowed(url, ownHost) resolves DNS and
blocks private/reserved resolved IPs UNLESS the hostname string-equals the
trusted publication host (allowlist by hostname, NOT resolved IP — the LAN
private IP is shared). Covers 10/8, 172.16/12, 192.168/16, 127/8, 169.254/16,
0/8, 100.64/10, IPv6 ULA/link-local/::1/IPv4-mapped. Fails closed on DNS error.
- lookupWithSecurity: optional options.ownHost (no call-site signature change);
guards http(s) URL inputs, returns null on block (existing contract).
- og-unfurl fetchAndStoreQuote: passes ownHost so remote quotes of our own posts
still resolve.
- profile.remote.js: followController string-prefix check replaced with the
DNS-resolving guard; unfollowController gains validation (had none).
- test/ssrf-guard.test.js: 8 cases incl. own-host-private ALLOWED and
different-internal BLOCKED-with-ownHost (no IP-allowlist leak).
KNOWN RESIDUAL (documented in ssrf-guard.js): DNS rebinding — guard resolves,
Fedify re-resolves at connect. Fedify-internal getX() fetches (reply-chain,
boost) also bypass this path. Both need a connection-time document-loader,
tracked as follow-up.