On July 17, 2019, an email landed in Capital One's responsible disclosure inbox from an outside security researcher. The message said, in effect: some of your data appears to be sitting in a public GitHub repository, and here is the link. Two days later the bank confirmed it was true. Ten days after that the FBI arrested a suspect, and the number everyone was repeating was 106 million - the credit card applicants and customers whose names, addresses, incomes and credit scores had walked out the door.

Here is the part I cannot get past. Nobody kicked the door in. No password was cracked, no employee clicked anything, no malware ran on a bank laptop. The way in was a web application firewall - a machine whose entire job is to stand in front of the doors and swat down bad requests. In this story, the security product was the door.

The server will dial anything

The bug class has an off-putting name, server-side request forgery, but the idea is ordinary. A lot of software is built to fetch URLs: link preview boxes, import buttons, image resizers, PDF generators, webhook testers. You type an address, the server fetches it for you, everyone saves time. The feature is friendly right up until a stranger types an address the server was never meant to fetch - and the server, which cannot tell a helpful fetch from a steered one, dials it anyway.

In March 2019 a former cloud engineer named Paige Thompson scanned the internet for machines that fetch. She found one of Capital One's - the firewall instance - and sent it a request that made it fetch an address that exists only inside a cloud machine: the metadata service. That service has one quiet job. It hands the machine its own temporary cloud credentials to any request that comes from the machine itself. The forged fetch came from the machine, so the service did its job, and the keys walked out.

They were fat keys. The firewall's role could list and read roughly 700 storage buckets, and what was inside added up to about 106 million people, including 140,000 Social Security numbers and 80,000 bank account numbers. The complaint put the access window between March 12 and July 17; the bank's own timeline puts the intrusion on March 22 and 23, 2019. Then nothing. For four months one of the largest banks in the country did not know it had been robbed, and the first person to figure it out was not on the payroll. In 2020 the Office of the Comptroller of the Currency fined the bank $80 million for failing "to establish effective risk assessment processes prior to migrating significant information technology operations to the public cloud environment." The class action settled at $190 million in December 2021.

Padlock as a data security symbol

What I take from all this is an opinion, and I hold it firmly. The scariest code in your application is not the login form or the admin panel - the doors you remember to lock. It is any line that makes a network request to an address it did not choose. Attackers stopped picking locks a long time ago. Now they ask your server, politely, to go fetch something on their behalf, and the server - built to be helpful, blind to intent - goes.

A URL field is a responsibility

I run a paid-rank leaderboard, and the intake form starts simple: your website's URL, your email, and a bid that starts at $5. To rank a site we have to read it server-side, which is exactly the shape of the story above - a user-chosen address, a fetch our infrastructure performs on request. So the fetch never runs bare. It goes through a guard that resolves where the address really points before anything leaves, and refuses anything that lands in a private, loopback or metadata range - the cloud's internal corners, the metadata service very much included. What comes back is treated as hostile until cleaned: the listing review runs on sanitized metadata, never raw page text.

The cloud vendor learned the same lesson on its side. By late 2019 AWS had rebuilt the metadata service so it answers only after a two-step handshake - a PUT request for a short-lived session token, then the real request with that token attached, kept close to the machine by a hop limit. A URL trick can steer a GET at an address. It cannot produce a PUT with a custom header and then reuse what comes back. One breach, and the shape of the request itself became the defense.

None of this makes fetch features optional. They are half the modern web; the leaderboard could not exist without its URL field, and neither could half the tools you use every day. The discipline is smaller and harder: enumerate every place your server dials out, ask what the most privileged address in your infrastructure is, and make sure no user-chosen string can ever point at it. Then check what the credentials on that fetch are allowed to read - because at Capital One the fetch was the burglary, but the 700-bucket role is what turned it into a heist.

If your site could use the spotlight, type its URL at bidspotlight.com/submit, set your bid, and let the guard worry about where the fetch goes.