A leaked cloud credential is supposed to be a short-lived emergency. New research shows it is closer to a permanent one. Truffle Security spent four years cataloguing Amazon Web Services access keys exposed in public code, datasets, and container images, then quietly checked which ones still worked. As of August 10, 88 percent of the credentials it re-verified still authenticated. The median live key had been sitting exposed for more than five years. The leak is not the interesting part of this story. The fact that almost none of these keys were ever turned off is.
The metric that matters is time-to-invalidation, not keys found
Across four years of scanning, Truffle Security pulled 64,024 unique access keys out of more than 431,000 raw hits, spread over roughly 50,000 accounts and first exposed between 2022 and this month (its own writeup, with independent coverage by BleepingComputer). Of the keys it safely re-tested using only harmless read calls, 9,308 (88 percent) still logged in. Only 13.7 percent of the keys it could check had ever been rotated. The other 86 percent were never touched.
Most security teams measure secret exposure by the wrong number. Finding a committed key is close to a solved problem: scanners flag it within seconds of the push. The number that actually predicts your blast radius is how long a key keeps working after it leaks, and this data puts that at a five-year median. A credential that never expires and is never rotated has an effectively unbounded window of use. Rotation as a written policy has clearly failed as a practice, because nothing forces it and an AWS access key has no built-in expiry to fall back on.
The keys are not leaking where your scanner is looking
The single largest source was not a code host. Truffle found 8,482 live keys inside 3,394 public datasets on Hugging Face, where AWS keys ranked as the second most frequent secret exposed. The rest came from git history, container images, package registries, and continuous-integration logs.
That shift matters for detection scope. Most secret scanning is pointed at source repositories and pull-request diffs, the artifacts the security team already governs. The exposure has migrated to data and model artifacts: datasets, notebooks, and checkpoints that data-science teams publish to sharing hubs outside the pipeline anyone is watching. If your scanning stops at the code repo, you are guarding the door the keys stopped using. Point it at the datasets, container layers, and CI logs too, and treat any machine-learning publishing workflow as a credential path. Hunting for anomalous key use in your own logs is the backstop for everything the pre-commit scanners miss.
Root keys are the part with no defense
Of the 768 live keys that handed over an entire company account, 526 were root keys and 242 belonged to IAM users with the AdministratorAccess policy. A further 130 live root keys sat on organization management accounts, where the blast radius is not one account but every account in the organization.
Root and IAM admin are not the same problem. An IAM key can at least be constrained: you can scope its policies, apply a permission boundary, or fence it behind a service control policy. A root access key answers to none of that. It cannot be scoped, it ignores permission boundaries, and service control policies do not apply to it. There is no supported reason to have a root access key in 2026, which makes its mere existence the finding. The over-permissioning ran deep on the IAM side too: of 7,590 active leaked IAM users, 84 percent held AdministratorAccess directly or through a group. A leaked key is only as dangerous as what it can reach, and here most of them could reach everything.
AWS already flagged 929 of these, and they still work
The most telling number is one AWS generated itself. When AWS finds one of your access keys exposed in a public place, it automatically attaches a restrictive policy called AWSCompromisedKeyQuarantine to that IAM user. Truffle found 929 of the 7,590 active leaked IAM users (12 percent) still carrying that policy, and 112 of them carried the original version that AWS had flagged at least three years earlier. The keys still authenticated.
Read that as a gift. AWS attaching the quarantine policy is a free, high-fidelity breach signal: if it is there, a machine at AWS found your credential in the wild. Almost nobody alerts on it. Watch your CloudTrail logs for an AttachUserPolicy or AttachGroupPolicy event where the policy ARN contains AWSCompromisedKeyQuarantine, and route it to your on-call the way you would a confirmed intrusion, because that is what it is. We made a similar point in June about credentials committed into a public repo: the platform often knows you are exposed before you do.
Start with the keys AWS already flagged for you
Prioritize by how much a key can reach and how likely it already leaked.
- Delete every root access key. There is no supported use case in 2026. Operate through IAM roles or Identity Center instead, and confirm with an account summary that
AccountAccessKeysPresentis zero on every account. - Alert on quarantine-policy attachment. Treat an
AWSCompromisedKeyQuarantineattach event in CloudTrail as an active compromise, rotate the key, and investigate what it touched. - Pull an access-key-age report and set a hard ceiling. Anything past ninety days without rotation is a finding. A five-year-old key is not a policy exception, it is an incident waiting to be claimed.
- Extend scanning past source repos to datasets, notebooks, container images, and CI logs, since that is where these keys actually surfaced.
- Set a cheap budget alarm. Across the accounts Truffle could read, fewer than one in ten (262 of 2,754) had any budget alert set; a ten-dollar threshold is a trip-wire for a key being abused for crypto mining. Truffle observed the readable set spending 420,631 dollars in a single month.
The durable fix is architectural, not procedural. Rotation keeps failing because it depends on a human remembering. Short-lived credentials remove the thing that leaks: with IAM Roles Anywhere, OIDC federation from your CI provider, or plain STS role assumption, the credential your workload holds expires in minutes to hours. A key that is committed to a repo or baked into a dataset stops working on its own, long before anyone finds it. Treat every static access key you still issue as a credential you will eventually find in someone else's git history, and design so that finding it does not matter.