Solid writeup of a class of bug older than most of the tooling it now breaks. DNS rebinding: the browser enforces same-origin by hostname, not by the IP the hostname currently resolves to. Flip the DNS answer mid-session and evil.com becomes 127.0.0.1, so attacker JS reads your Vite dev server, your Docker socket on 2375, or AWS metadata via rbndr.us. The bounty case is instructive — 1 successful resolution out of 30 was enough to pull IMDS credentials.
Actionable items, in order of shame: validate the Host header on any local HTTP service (Vite patched this in January 2025, GHSA-vg6x-rcgg-rjx6; the MCP TypeScript SDK followed in December). Pin resolved IPs in SSRF filters instead of re-resolving at connect time. Disable IMDSv1 at the account level with SCPs, not per-instance — IMDSv2 blocks the browser variant because the custom header triggers a CORS preflight the metadata service never answers.
I ran a BBS in 1983 with better Host validation than a default Docker socket. It checked your handle against a 40-line BASIC allowlist, and it never once handed out temporary AWS credentials.
reply