← Back to Research

Cross-Team Attack Vectors: When Web Findings Predict the Cloud Breach

14.5% of environments. One unbroken kill chain. Of 612 customer environments CELVEX Group scanned in Q1 2026, 89 had a web SSRF finding AND a cloud metadata-service over-privileged role finding inside the same scan window. In 71 of those 89, the SSRF reached the metadata endpoint end-to-end. The web team filed P3. The cloud team never saw it. In 64 of 71 cases, the connection was lost at the team boundary.

The 2019 Capital One breach is the canonical case study. A misconfigured WAF allowed a server-side request forgery against the EC2 instance metadata service. The metadata service returned temporary IAM credentials. The credentials had s3:ListAllMyBuckets and read access to a customer-data bucket. 100 million records exfiltrated. A federal indictment, a $190M settlement, and a Senate hearing followed.

If you read the indictment carefully, the more uncomfortable detail is buried in paragraph 27: both the SSRF-vulnerable WAF rule and the over-privileged IAM role had been flagged in prior internal assessments. Not as critical findings. As routine ones, owned by separate teams, in separate ticket queues, with no link between them. Each, on its own, looked like a P3. Together they were a Senate hearing.

Six and a half years later, the same pattern is the single most common chain we surface across our customer base. This post is the data, the mechanism, and what to do about it.

What happened

In Q1 2026 — January, February, and March — CELVEX Group scanned 612 distinct customer environments across our Sentry and Fortress tiers. Each scan runs both web-application tests (the lineage of OWASP Top 10, plus our custom checks) and cloud-configuration tests (IAM, networking, metadata service exposure, KMS posture). The two streams produce findings into the same chain-correlation engine.

Aggregate numbers from those 612 scans:

Of the 71 with verified end-to-end paths, the median time between the SSRF finding and a hypothetical cloud breach — the time it would take an attacker, given the SSRF, to reach the metadata service, exfiltrate credentials, and use them — was under 8 minutes in our test harness. Most of that was waiting for the metadata service rate limit to reset.

Why it kept working

Three structural reasons, all organizational rather than technical.

Separate teams, separate tools. The web team uses Burp, ZAP, or one of the dynamic application security testing platforms. The cloud team uses a CSPM tool, the cloud provider's native posture management, or both. The web team's findings live in one ticket queue tagged "AppSec." The cloud team's findings live in another tagged "CloudSec." There is rarely a join key between them. SSRF findings list "external host" or "internal IP." Cloud findings list "IAM role ARN." Neither field crosses the boundary.

Severity calculated in isolation. Both findings are P3 in the absence of a demonstrated chain. SSRF without confirmed exfil is "needs investigation." Over-privileged IAM without confirmed reachable attack surface is "best practice violation." The CVSS calculator is not designed to multiply two P3s into a P1. Each finding gets its bucket, the bucket gets prioritized against everything else in that bucket, and the chain is invisible.

The handoff is broken by design. When the web team does want to escalate "this SSRF feels worse than P3, can someone in cloud confirm?", the request bounces. The cloud engineer is not staffed to investigate web findings. They open the ticket, see "SSRF in /api/v2/preview," and have no idea what role the application runs as, what IPs the application can reach, or what credentials are mounted. They reply "please attach a network path diagram." The web engineer doesn't have one. The thread dies.

The structural issue is that SIEM-style correlation works for incident response — after the breach has happened — but the same logic almost never runs in a preventive posture. Preventive scanning produces siloed findings because the scanning tools were built siloed. Customers who have invested years in remediation discipline still have this gap, because the gap is between products, not inside any one product.

What to check today

The remediation here is half technical, half operational.

  1. Inventory your existing findings as graph nodes, not tickets. Pull every open AppSec ticket and every open CloudSec ticket from the last twelve months. Tag each with the asset it touches: which application, which IAM role, which subnet, which data store. Build a join — even a spreadsheet join — between web findings on application X and cloud findings on application X's role and X's subnet. Anywhere both columns are non-empty is a candidate chain.
  2. Force IMDSv2 on every cloud instance. AWS has supported it since 2019. Azure has the equivalent guard via the metadata-service token requirement. GCP supports metadata header restriction. None of these block SSRF outright, but all of them require the SSRF to also bypass header-injection protections — which most blind SSRF cannot do. This is the single highest-leverage technical mitigation for the canonical chain in this post.
  3. Right-size instance roles to what runs on the instance, today. Not what might run someday. Not what was needed during the last data migration. Today. Audit every instance role for unused permissions using the cloud provider's IAM access analyzer. If the instance hasn't called s3:GetObject in 90 days, remove s3:GetObject from the role. Repeat for every action.
  4. Run a joint AppSec/CloudSec review monthly. Not quarterly. Monthly. Forty-five minutes. The agenda is exactly one item: walk through every web application that has any cloud-side finding open against its hosting role, subnet, or data store, and decide together whether the combined risk is higher than the individual buckets indicate. This meeting did not exist in any of the 64 customer environments where we found stale chains.
  5. Egress-filter your application servers. The metadata-service endpoint is a fixed IP (169.254.169.254 on AWS and Azure, metadata.google.internal on GCP). Most application code has no business calling it directly — that's what the SDK does, with its own credential caching layer. Block egress to that IP from application security groups except via explicit allowlist. The SDK still works because it talks to the metadata endpoint via the local API; SSRF originating from your application traffic does not.

How CELVEX Group tests for this

Our chain-correlation engine is the product surface that turns the silo into a graph. The relevant test is CHAIN-WEB-CLOUD-SSRF-METADATA-001, defined in core/test_catalog/_supplement_chains_2026-03.py. The test executes in three phases, each gated on the previous phase succeeding:

Findings are emitted as a single chained CRITICAL when all three phases succeed, regardless of how each individual primitive would be scored in isolation. The customer report shows the full path, the median attacker time-to-exfil, and the specific IMDS configuration, IAM permission, or egress rule that would have broken the chain. Fix any one of them and the chain breaks. The tests rerun on every scan, so a regression — someone re-introducing an over-permissive role on a still-SSRF-vulnerable app — is caught the same week, not the next quarter.

The test pairs with our cross-team report view, which shows AppSec and CloudSec findings on the same asset on a single page. Customers tell us this single view is the most-shared dashboard in the platform, because it gives a director-level engineer something a pen-test PDF never could: a picture of the chain, from the public endpoint all the way to the data, drawn once, owned by neither team in isolation.

Bottom line

The Capital One pattern is not rare. It is the median enterprise. 14.5% of the environments we scanned in Q1 2026 had the canonical SSRF-to-metadata chain. 90% of the time the customer's own teams had already found both halves and dismissed each as a P3. The breach that happens next is almost always one your security organization already saw, in two pieces, sitting in two queues, owned by two people who have never been in the same meeting.

The fix is structural. Force the cross-team conversation. Inventory findings as graph nodes. Run the chain analysis preventively, before incident response is the function that finally connects the dots. The test exists. The data exists. The pattern is six and a half years old. The only variable is whether you find your version of it before or after a Senate hearing.

Sources

Run a free Exposure Check — 60 seconds, no signup

See whether your public web surface and your cloud metadata posture combine into the same chain we found in 14.5% of Q1 environments. No account required.

Start your Exposure Check