Capital One — the 2019 breach
This is a real, named breach, and this page sticks to what Capital One's own disclosures, the U.S. Department of Justice's charging documents, and the Office of the Comptroller of the Currency's consent order say happened. In March 2019, a former Amazon Web Services engineer exploited a server-side request forgery (SSRF) flaw in a misconfigured web application firewall, used it to steal live credentials for an over-permissioned IAM role, and used that one role to pull data from more than 700 storage locations in Capital One's AWS environment — exposing roughly 106 million people's credit-application records. This is not a success story. It's a chain of ordinary, well-understood mistakes that lined up perfectly, and a walkthrough of exactly which control, at which link, would have broken it.
Imagine a guard dog trained to fetch anything you point at. Someone points it at the one drawer in the house where the spare keys to every room are kept, and the dog — doing exactly what it was trained to do — fetches the keys and hands them over. Now imagine that same drawer holds keys to every room in the building next door too, because nobody ever bothered to give the dog's owner a smaller set of keys. That's this breach: one trick (get the dog to fetch) plus one unrelated mistake (way too many keys in the drawer) equals the whole building.
The backdrop: a bank that bet early and hard on the cloud
☺ Like you're 10: This didn't happen to a company that was careless about computers — it happened to one of the banks that moved to the cloud earliest and loudest, which is exactly why the lesson matters.
Capital One is worth setting up correctly before anything else, because the easy, wrong reading of this story is "a bank got sloppy." The opposite is closer to true: starting around 2014–2015, Capital One committed publicly and aggressively to migrating off its own data centers and onto AWS, years ahead of most regulated financial institutions, and talked about it often at AWS's own conferences as a flagship customer story. By 2020 it had closed its last physical data center. This was, by the standards of 2019, a bank that took cloud engineering seriously and had real security investment behind it — which is exactly why this breach is worth studying closely: it wasn't the product of an organization that didn't care. It was the product of one internet-facing misconfiguration meeting one over-broad permission, in an environment that was otherwise sophisticated. See threat modeling for the discipline that's supposed to catch exactly this kind of interaction between two individually-plausible design decisions before either one ships.
Link one: an SSRF-able WAF facing the internet
☺ Like you're 10: The firewall's whole job was to fetch things on request — nobody had locked down which things it was allowed to fetch.
Capital One ran an open-source web application firewall (ModSecurity, configured as a reverse proxy) in front of a web application hosted on AWS. A server-side request forgery (SSRF) vulnerability in that WAF's configuration meant a specially crafted request could make the WAF itself issue an outbound HTTP request to a URL of the attacker's choosing, rather than only proxying traffic to the backend it was meant to protect. SSRF is not an exotic or novel attack class — it's been on the OWASP Top 10 for years precisely because "a server that will fetch a URL on your behalf" is an extremely common building block, and every instance of it needs to be scoped to a safe allowlist of destinations or it becomes an open proxy for anything reachable from that server's network position, including addresses no external caller should ever be able to reach.
That last part is what made this particular SSRF so damaging: every AWS EC2 instance can reach a special, non-routable address — 169.254.169.254 — the EC2 Instance Metadata Service (IMDS), which an instance uses to ask AWS about itself: its instance ID, its network config, and, critically, the temporary AWS credentials for whatever IAM role is attached to it. In 2019, the default version of this service (now called IMDSv1) answered a plain, unauthenticated GET request with no extra proof required — which meant an SSRF vulnerability that let an attacker point the WAF anywhere could point it at 169.254.169.254 just as easily as at any external URL.
Link two: a live credential, handed over by the metadata service
☺ Like you're 10: Once the dog would fetch anything, "fetch the drawer of keys" was just as easy an instruction as "fetch a website."
The pattern below is the general SSRF-to-stolen-credentials technique that this class of vulnerability enables — illustrative of the mechanism, not a reconstruction of the attacker's literal payload against Capital One's WAF, which was never made fully public:
# Step 1: use the SSRF-able endpoint to ask IMDSv1 which role is attached to the instance
curl -s "https://vulnerable-waf.example/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/"
# → returns the role name, e.g. "WAF-Role" — no authentication required under IMDSv1
# Step 2: fetch that role's live, temporary credentials
curl -s "https://vulnerable-waf.example/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/WAF-Role"
# → returns a working AccessKeyId, SecretAccessKey, and session Token
# Step 3: load the stolen credentials into the AWS CLI and use them like any legitimate caller would
aws configure set aws_access_key_id
aws configure set aws_secret_access_key
aws configure set aws_session_token
aws s3 ls # enumerate every bucket this role can see
aws s3 sync s3:// ./loot # pull a bucket's contents locally Nothing above required special tooling or a zero-day. Every step is a documented, ordinary use of publicly available AWS commands — the attacker's skill was in finding the SSRF entry point and recognizing what it was worth, not in any exotic exploit development. That's precisely why this case belongs in a DevSecOps course rather than a pure pentesting one: the fix isn't a smarter attacker-catching trick, it's removing the ordinary building blocks that made an ordinary technique this catastrophic.
Link three: one credential, 700+ locations, ~106 million records
☺ Like you're 10: The stolen key didn't open one door — it opened a wing of the building nobody had ever mapped.
The IAM role attached to the WAF's compute instance — publicly referred to in Capital One's own testimony to Congress as having "misconfigured permissions" — had far more reach than a web application firewall has any legitimate reason to need. It could list and read from a large share of Capital One's Amazon S3 storage. Public reporting and court filings vary slightly on whether to describe the scope as "more than 700 S3 buckets" or "more than 700 folders" within Capital One's AWS storage; they agree on the number, and, more importantly, they agree that a single stolen role could reach essentially all of it. That's the least-privilege failure in one sentence: a workload that only needed to proxy web traffic held a credential that could touch a meaningful fraction of a major bank's entire object storage estate.
| What Capital One disclosed (July 29, 2019) | Scale |
|---|---|
| Individuals affected in the United States | ~100 million |
| Individuals affected in Canada | ~6 million |
| U.S. Social Security numbers exposed | ~140,000 |
| Linked bank account numbers exposed | ~80,000 |
| Canadian Social Insurance Numbers exposed | ~1 million |
| Data category | Names, addresses, phone numbers, dates of birth, self-reported income, credit scores, credit limits, balances, and payment history from credit-card applications dating back to 2005 |
The data was mostly credit-card application information — exactly the kind of record a consumer bank accumulates by the tens of millions over fourteen years of taking applications — which is what made a single over-broad role so valuable a target once it was reachable at all.
The OCC's own August 2020 consent order didn't frame its finding as "an engineer misconfigured a WAF." It framed it as Capital One's failure to establish an effective risk-assessment process before migrating significant operations to the public cloud, and its failure to correct the resulting deficiencies in a timely manner — an organizational-process finding, not a personnel one. Blaming whoever wrote that one IAM policy misses the actual lesson: no single reviewer's judgment, on any given day, should be the only thing standing between an internet-facing proxy and 106 million records. That's exactly why this course pushes toward layered, automated controls instead of a single point of human review — see What is DevSecOps? for why "security as code" exists to catch the mistake any one person eventually makes.
The hidden link: a four-month gap between the theft and the discovery
☺ Like you're 10: Nobody at the bank noticed the door was open — someone had to spot the burglar bragging about it, days later, in a completely different building.
Capital One's own disclosure places the unauthorized access on March 22 and 23, 2019. Nothing in Capital One's own monitoring caught it. The breach came to light only because the person responsible for it, Paige A. Thompson — a former AWS software engineer who went by the online handle "erratic" — allegedly discussed the intrusion in a Slack channel, on Twitter, and in a public GitHub Gist, and someone who saw that activity emailed Capital One's responsible-disclosure inbox on July 17, 2019. Capital One, working with the incident-response firm Mandiant, confirmed the vulnerability and the scope of the breach within two days, disclosed it publicly on July 29, 2019, and the FBI arrested Thompson that same day.
That gap — roughly four months between the exfiltration and Capital One learning about its own breach, and from an external tip rather than internal telemetry — is a separate failure from the SSRF-and-IAM chain above, and this course treats it as its own lesson rather than a footnote. A role that normally does nothing but proxy web traffic suddenly running large-volume ListBucket and GetObject calls against buckets it had never touched before is exactly the kind of anomaly a monitoring pipeline exists to catch — if anyone is watching that role's baseline behavior in the first place. See Detection Engineering & Security Observability for what "someone is watching that role's baseline behavior" actually requires in practice, and incident response and forensics for how Capital One's response, once it started, moved from tip to public disclosure in twelve days — genuinely fast, once anyone knew to look.
Where the chain could have broken — mapped to this course
☺ Like you're 10: Five separate weak spots, five separate fixes — and any one of the five fixes, on its own, stops the whole story from happening.
The point of walking the chain this slowly is that it isn't one impossible-to-prevent failure — it's five ordinary, well-documented control gaps, each one covered by a specific page elsewhere on this site. Any single one of them, applied, breaks the chain.
| Link | What actually happened | The control that breaks it | Covered on this site |
|---|---|---|---|
| 1. An SSRF-able WAF facing the internet | A misconfigured, internet-facing reverse-proxy WAF could be tricked into fetching an arbitrary URL | Pre-production dynamic testing and red-teaming against every internet-facing proxy, not only the application behind it | Dynamic Analysis in Practice, Offensive Security for DevSecOps |
| 2. IMDSv1 hands over live credentials on request | A plain GET request to the metadata service returned a working access key, secret key, and session token, no extra proof required | Require IMDSv2 (session-oriented, hop-limited) so a basic SSRF that can't set custom headers can't complete the credential fetch | Workload Identity & Pipeline IAM |
| 3. The stolen role was over-permissioned | A role meant only to proxy web traffic could list and read a large share of the company's S3 storage | Least-privilege IAM: scope every role to exactly the actions and resources the workload needs, reviewed like code, not granted "to be safe" | Workload Identity & Pipeline IAM, Infrastructure as Code Hardening |
| 4. One credential reached 700+ locations | No compartmentalization existed between the WAF's blast radius and the rest of the data estate | Continuous cloud security posture management that flags a compute role with sweeping storage access as an anomaly, not background noise | Cloud Security Posture, Prowler, ScoutSuite |
| 5. Exfiltration ran four months undetected | No alert fired on an idle role suddenly making large-volume storage calls it had never made before | Baseline normal API-call behavior per identity and alert on deviation, paired with a rehearsed incident-response runbook | Detection Engineering & Security Observability, Incident Response & Forensics |
Five links, one chain — and this wasn't five independent failures that all had to go wrong together by bad luck. It was one underlying gap (nobody was treating the WAF's configuration, its IAM role, and its network reach as a single attack surface to review together) that showed up at every layer. A defense-in-depth pipeline doesn't need every layer to be perfect; it needs at least one layer to hold. Here, none of them did — but any single one holding would have been enough.
The aftermath: an arrest, a conviction, and two very different bills
☺ Like you're 10: The person responsible was caught fast; the company's own bill for the mistake took years to fully add up.
The FBI arrested Paige Thompson on July 29, 2019, the same day Capital One disclosed the breach publicly. Federal prosecutors charged her with computer fraud and abuse and wire fraud, and later court filings described a pattern of similar SSRF-based intrusions against dozens of other organizations using comparable misconfigurations — Capital One was, by scale, the largest of them, not an isolated incident for the attacker. In June 2022, a federal jury in Seattle convicted Thompson of wire fraud and multiple counts of unauthorized computer access, while acquitting her on separate charges tied to access-device fraud and identity theft. In June 2023, the presiding judge sentenced her to time already served plus five years of supervised release rather than additional prison time — a sentencing outcome that drew significant public debate, and one this page deliberately doesn't take a position on. What matters for a DevSecOps reader isn't the legal outcome; it's that every technical control that would have stopped her was already established, well-documented practice in 2019, not a lesson the industry learned for the first time from this case.
For Capital One, the regulatory and civil bill was substantial and arrived in stages. In August 2020, the Office of the Comptroller of the Currency imposed an $80 million civil money penalty — one of the largest of its kind against a bank for a cybersecurity failure at the time — citing Capital One's failure to establish effective risk-assessment processes before migrating significant IT operations to the public cloud, and its failure to correct known deficiencies quickly enough. Separately, Capital One reached a class-action settlement with affected customers, widely reported at approximately $190 million, covering credit monitoring and reimbursement for demonstrated losses; that settlement received final court approval in 2022. Readers using these figures for anything beyond a teaching example should verify current totals directly — further state-level or supplementary actions may have added to the tally since these were reported, and this page isn't tracking litigation in real time.
What doesn't transfer
☺ Like you're 10: A few things about this story are specific to 2019 and shouldn't be copied blindly into how you read it today.
- This wasn't negligence from a laggard. Capital One's early, public, and genuinely well-regarded cloud migration is the whole reason this case is worth teaching — a security-conscious, cloud-forward organization still shipped one over-scoped role and one misconfigured WAF. The transferable lesson is "even mature organizations need automated, continuously-enforced controls, because a manual review process — however good the reviewers are — will eventually miss one role," not "cloud migration is inherently risky."
- The industry's own defaults changed because of this exact pattern. AWS released IMDSv2 in November 2019, months after this breach, specifically to close the SSRF-to-credential-theft path used here: it requires a session token obtained via an authenticated PUT request before any metadata GET will succeed, and supports a response hop-limit that a basic SSRF proxy typically can't satisfy. AWS later moved toward making IMDSv2 the default for new instances and gave account owners the ability to require it fleet-wide. That's a rare, traceable case of one breach measurably changing a major cloud provider's secure-by-default posture — worth knowing, but also a reminder that this specific defense didn't exist yet in March 2019.
- The published financial figures are the two most consistently reported ones, not a final tally. The $80 million OCC penalty and the roughly $190 million class-action settlement are well documented, but state-level actions or supplementary litigation may have added to the total since. Treat these as the headline numbers for a teaching example, not an audited final figure.
- Thompson's technique wasn't cutting-edge. SSRF has been a known, catalogued vulnerability class for well over a decade, and least-privilege IAM was already standard security guidance in 2019. Nothing about this breach required a novel exploit — which is precisely why "we're not doing anything unusual" is not evidence that the same chain couldn't happen to any team running an internet-facing proxy on top of a broadly-permissioned role today.
Rocky the Raccoon: I didn't write any new exploit here — I just found a WAF that would fetch a URL for me, and asked it to fetch the one URL every EC2 instance already trusts.
Timmy the Turtle: That WAF should have been tested for exactly that before it ever faced the internet. SSRF against a proxy isn't exotic — it's on every serious DAST checklist.
Ellie the Elephant: And the second Rocky had that metadata response, she was holding a real, working AWS credential. I don't care that it came from a metadata endpoint instead of a committed file — a live credential is a live credential.
Sol the Sloth: The part that still bothers me is slower than that: why did a WAF's role have list-and-read access to 700-plus buckets in the first place? One careful pass, bucket by bucket, role by role, would have flagged that months before Rocky ever showed up.
Foxy: And nobody flagged four months of one idle identity suddenly pulling data out of buckets it had never touched before. That's not a scanning gap — that's a "nobody was even watching" gap.
Professor Owl: One weak link, repeated at every layer — no scan on the WAF, no ceiling on the role, no eye on the traffic. Break any single one of those and this whole case study doesn't exist.
Set this next to Equifax's unpatched dependency for a second mega-breach driven by one technical control gap left uncorrected, and against SolarWinds' supply-chain compromise for a very different failure shape — trusted software itself as the attack vector, rather than a misconfigured edge service. All three land in the same place this page keeps returning to: it's rarely one impossible mistake, it's one ordinary gap that nothing else in the pipeline caught.
1. Name the two technical failures that both had to be true for the SSRF against Capital One's WAF to turn into a 106-million-record breach. 2. What AWS feature, released a few months after this breach, was built specifically to defeat the SSRF-to-stolen-credentials pattern used here — and how does it work? 3. Why does this page treat the roughly four-month gap between the data being taken and Capital One learning about it as a separate failure from the SSRF/IAM chain itself? 4. What did the OCC's $80 million penalty actually cite as the underlying failure, and why does that framing matter more than "an engineer misconfigured a WAF"? 5. Pick any one link from the chain-of-failure table and name the specific DevSecOps control, from elsewhere in this course, that would have broken it.
Check your answers
- An SSRF vulnerability in the WAF's configuration that let it be tricked into fetching an arbitrary URL, and an IAM role attached to that WAF's instance that was far more permissive than a web application firewall needed — the SSRF alone would have been far less damaging against a tightly-scoped role, and the over-permissioned role alone was unreachable without the SSRF.
- IMDSv2 — it requires a session token obtained via an authenticated PUT request before any GET request to the metadata service will return credentials, and supports a response hop-limit; a basic SSRF proxy that can only relay simple GET-style requests typically can't satisfy either requirement, which closes the exact path used in this breach.
- Because it's a distinct control gap: even after the SSRF and the over-permissioned role both failed, a monitoring system that baselined normal behavior for that role and alerted on an idle identity suddenly making large-volume storage calls could still have caught the intrusion in progress, rather than Capital One learning about its own breach four months later from an external tip.
- It cited Capital One's failure to establish an effective risk-assessment process before migrating significant operations to the public cloud, and its failure to correct known deficiencies in a timely manner — an organizational-process finding. That framing matters because it points at the actual fix (layered, automated controls that don't depend on any single reviewer's judgment on any given day), not at blaming whichever individual configured one role.
- Any of: pre-production SSRF/DAST testing against the WAF (Dynamic Analysis in Practice, Offensive Security for DevSecOps); IMDSv2 enforcement or least-privilege IAM scoping (Workload Identity & Pipeline IAM); continuous cloud posture scanning flagging the over-broad role (Cloud Security Posture, Prowler, ScoutSuite); or anomaly detection on the role's API activity (Detection Engineering & Security Observability).