Back to all posts
Published on · by Renaud Deraison

The key never expired

Truffle Security spent four years pulling AWS keys out of git history, Hugging Face datasets, Docker images and CI logs. Of the ones they could re-verify, 88% still authenticate. The median live key is five years old, 2,505 users never rotated theirs, and 929 of them wear the quarantine policy AWS attaches when it spots a key in public. Nobody failed to detect anything. Bromure Agentic Coding keeps the half of the key that signs out of the VM, so what an agent leaks is dead the day it leaves.

Finding leaked credentials is a solved problem. Truffle Security has been at it for four years and has 431,875 AWS findings to show for it. The unsolved half is the step after, where someone has to log in and delete the key. That happens one time in seven.

Truffle Security published a census this week, and BleepingComputer picked it up on Thursday. Since August 2022 the company has collected AWS access keys from the places they surface in public: git history, Hugging Face datasets, Docker images, package registries, CI logs. Then it checked whether they still work.

The report counts 431,875 verified AWS findings, deduplicated to 64,024 unique access keys across 50,654 distinct accounts. Of those, 10,616 pairs carried enough material to re-test. Eighty-eight percent of them still authenticate. That is 9,308 keys, live today, that anybody could have picked up off a public surface at some point in the last four years.

They kept the verification narrow, using read-only metadata calls: sts:GetCallerIdentity, iam:ListAccessKeys, policy-name enumeration, a budget read, one Cost Explorer call per account. They read no data and changed nothing, and they told 10,260 of the 10,616 owners before publishing.

Then look at how old the keys are.

Five years, and counting

The median still-working key is 1,831 days old. The oldest is 17.4 years. Only 25 keys in the set, nine tenths of one percent, date from the last thirty days.

That distribution describes sediment rather than a stream of fresh accidents getting caught and cleaned. A key leaks and stays leaked, because an AWS static access key has no expiry: no clock, no renewal, no certificate going stale in eighteen months. It works until someone opens the console and deletes it. Truffle measured how often that someone shows up. Of the users whose keys the researchers could enumerate, 398 out of 2,903 have a newer key sitting alongside the leaked one, which is 13.7%. The remaining 2,505 never rotated it.

You cannot pin that on the discovery step either, because Amazon had already done the discovering. When AWS spots one of its own keys in public it attaches a policy called AWSCompromisedKeyQuarantine to the user, clamps down what the key can do, and emails the account. Nobody has to ask it to. Truffle found 929 IAM users, 12% of the 7,590 active ones, wearing that policy right now. A hundred and twelve of them wear the original version of it, so AWS flagged those at least three years ago and they still answer.

Detection worked, the email went out, and three years later the key is still good.

The life of a leaked AWS keyDAY 0the key reaches a publicsurface: a commit, a layer,a CI log, a datasetDETECTEDAWS attachesAWSCompromisedKeyQuarantineand emails the account ownernothing expires itno TTL, no renewal, no rotationunless a person deletes itDAY 1,831median age of a key thatstill authenticates today17.4 YEARSoldest live keyin the setDid anyone ever issue a replacement key?13.7% · 398 users86.3% · 2,505 users never rotated, superseded or cleaned up the leaked key
An AWS static access key has no expiry, so a leak has no end date. The only thing that closes it is a person deleting the key, and across 2,903 enumerable users that happened 13.7% of the time, including for the 929 users AWS had flagged and quarantined by itself.

The leak surface moved somewhere with no delete button

The single largest source in the whole census is Hugging Face: 8,482 unique live keys across 3,394 datasets, and a 17.9% root-key rate, well above the rest of the population.

Truffle had already measured the far end of that pipe. In June the team cloned every public dataset on Hugging Face: 186.9 million unique files, 7.6 petabytes, around 815,000 dataset repositories. They flattened Parquet, Arrow, JSONL and archives into scannable text and verified everything they found. The result was 221,303 live, unique credentials sitting in 6,003 datasets: 11,496 AI-provider keys, 8,557 Google Cloud service-account keys across 3,811 projects, 8,594 working database logins, 3,343 AWS keys that pass an STS identity check, 349 GitHub personal access tokens of which 223 can push code and 130 can rewrite CI workflows.

Two of their examples show how far one mistake travels. Somebody pasted a Brazilian fintech's AWS key into a chatbot, and it now turns up mirrored about eighteen times across different corpora. An Infura key captured the same way ended up in 1,131 datasets and 10,162 separate file locations. Forty-four percent of the unique live secrets Truffle found appear in more than one dataset.

Then people train on those datasets. StarCoder's documented training data contains 25,217 of these keys; Swallow, 22,484; OLMo 3, 21,278. The large proprietary models keep their corpora private, so nobody outside knows.

Truffle draws the blunt conclusion: rotation is still the only fix, because nobody can go back and clean training data. Treat any key that ever hit a public repo, a web page, or a chatbot as burned.

One credential, and no way backone live keypasted into a chatbot,or committed, or loggedpublished as a dataset6,003 datasets on HuggingFace hold live credentialsmirrored44% of live secrets appearin more than one corpustrained onStarCoder 25,217 keysSwallow 22,484 keysOLMo 3 21,278 keysOne Infura key, captured from a single conversation: 1,131 datasets, 10,162 file locations. Deleting the original file reaches none of them.The only step that closes this is deleting the key at the provider, and that step happens 13.7% of the time.
A credential that reaches a public dataset cannot be withdrawn. Truffle found 44% of live secrets duplicated across corpora, one Infura key in 1,131 datasets, and tens of thousands of working keys inside the documented training data of open models. Deleting the original file changes nothing downstream.

Every source on that list is something an agent writes

Look again at where Truffle went shopping: git history, Docker images, package registries, CI logs, dataset uploads. Those are build outputs, and they are the artifacts a coding agent now produces unattended, overnight, at a rate no team could review.

An agent that runs a backlog while you sleep writes commits, rewrites lockfiles, builds images, pushes branches, and fills logs. Every one of those is a publication surface, and the agent has your ~/.aws/credentials in reach the whole time, because that is how the SDK is designed to find it.

Coding agents now write those artifacts faster than any tool before them, and the 13.7% has not moved.

The half that signs stays on your Mac

Bromure Agentic Coding runs the agent in a disposable Ubuntu VM on Apple's Virtualization framework, with a host-side proxy as its only route out. AWS needs its own handling in that design. SigV4 never puts the secret on the wire, since the SDK consumes it in-process to compute an HMAC, so a proxy has nothing to swap in transit. Bromure moves the signing instead.

Inside the VM, ~/.aws/config names a credential_process helper. When the SDK asks for credentials, the helper returns the real access key ID paired with a forty-character fake secret, minted fresh per session. The access key ID is an identifier, not a secret, and it is the half that identifies which IAM user is calling. The secret access key is the half that signs, and it never enters the VM's address space at all. Bromure does not even export AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY into the guest environment, on the grounds that environment variables leak through /proc, ps -E and shell history. The VM gets a region string and nothing else.

The SDK signs a request whose signature cannot be right. On the way out, the host strips that signature and recomputes SigV4 with the real material. aws, boto3 and terraform all work as usual. Anything that routes around the proxy gets InvalidSignatureException back from Amazon, which is the failure you want.

Now run a Bromure workspace through Truffle's methodology. Their bar for counting a key is a signed sts:GetCallerIdentity that comes back valid. Suppose a compromised dependency harvests the credentials file out of that guest, or the agent gets talked into cat-ing it, or a build inlines it into a public bundle. What leaves is an identifier and forty characters that were never the secret. It fails on the day it leaks, so it never joins the sediment layer and there is no five-year tail behind it.

That also removes the rotation step that waits on a human. The real secret lives in one place, on your Mac, in the profile's Credentials pane. Change it there and the next session picks it up. Nobody has to work out which of ninety overnight runs wrote which artifact.

Agent on the laptop~/.aws/credentialsaws_access_key_id = AKIA…aws_secret_access_key = <real>the agent reads it, the SDK signs with it, andevery artifact it writes can carry it outa commit, a layer, a CI log, a datasetsts:GetCallerIdentity → validmedian five more years of thatAgent in a Bromure workspacein the VM · credential_process helperAccessKeyId = AKIA…SecretAccessKey = <40-char fake>on the Mac: the real secret, never in the VMthe proxy strips the doomed signature and re-signsthe same artifact, harvestedsts:GetCallerIdentity → InvalidSignatureException
AWS credentials in a Bromure workspace: the access key ID identifies the caller and reaches the VM, the secret access key signs and does not. The guest signs a request that is bound to fail, the host re-signs it with the real material, and anything harvested out of the VM fails the same STS check the census used to count live keys.

A signed request narrower than the key that signs it

The other headline in the census is reach. Of 817 keys tied to a business, 768 gave full control of the account: 526 root keys and 242 IAM users holding AdministratorAccess. One hundred and thirty of those root keys sit on organization management accounts, the account that governs every member account in the org. Across the users the researchers could enumerate, 976 of them held AdministratorAccess, or 84%.

Those are keys minted for convenience, years ago, for a task that needed three permissions.

Bromure's Guardrails setting narrows the credential at the point of use, so you never have to remember to narrow it at the source. It is a host-side policy engine in the proxy. For AWS it reads the action name out of the X-Amz-Target header for JSON-protocol services like DynamoDB and Lambda, or out of the Action= parameter for query-protocol services like EC2, IAM and SQS, and falls back to HTTP method for S3. Delete*, Terminate*, Remove*, Purge* and Destroy* classify as destructive; Get*, List* and Describe* classify as reads. Set the profile to Read-only and a mutation comes back as a hard 403 that the agent reads as an ordinary API failure. Set it to Block destructive and creates and updates go through while deletes do not.

Your Mac enforces this, not the VM, so an agent that has been talked into something cannot argue its way past it. The credential your host signs with ends up narrower than the credential itself, which is worth having in a population where 84% of the enumerable users carried admin.

The record shows up before the invoice

One more number from the report. Of the 2,754 accounts whose budgets the researchers could read, 262 have a budget alert configured at all, which is 9.5%, at a median limit of eight dollars. That same set spent $420,631 in July, with fifty accounts over $1,000 and nine over $10,000. Most of those owners will meet their intruder on an invoice.

Bromure writes the record while the work happens. Every request the host signs emits a credential.aws_sign row into Window → Security Timeline carrying the service, method, host, region and the masked access key ID, alongside the package fetches, the firewall verdicts and the credential swaps. Bromure keeps that log on the Mac, where nothing inside the VM can edit it. For the stricter version, AWS → Require approval to use turns each signing call into a consent prompt with a time-bounded grant, so an afternoon of real work asks once.

Bromure applies the same idea one step earlier, when you first bring a profile up. It runs your imported agent configuration through a redaction pass: structured JSON, TOML and YAML filtered by key name, matching token, secret, password, apikey, credential, authorization, private_key and access_key, and prose filtered by token shape, matching AKIA, ASIA, sk-ant-, ghp_, glpat-, AIza and npm_. Whatever real secrets sit in the dotfiles on your Mac, they do not ride into the VM with the rest of the setup.

What the census proves

Truffle Security ran this well: read-only calls, no data touched, 10,260 of 10,616 owners told before publication. AWS comes out of it better than the headline suggests, since the quarantine policy is Amazon finding its own leaked keys and warning the owner without being prompted. Both halves of the detection pipeline did their job.

The result was still 9,308 live keys with a median age of five years, and a rotation rate of 13.7%.

The failing control asks a person to complete a chore months or years after the mistake, on a system they may not own any more, for a key that gives no sign of being a problem. Controls shaped like that fail at scale, and they were failing before anything started writing commits overnight.

So stop asking the chore to carry the weight. Put a credential in the workspace that was never the credential, and the census has nothing to count, the corpus has nothing to mirror, and the five-year tail belongs to somebody else.


Sources: Truffle Security, "Leaked Corporate AWS Keys Held Full Admin Rights" (Aug 19, 2026) · Truffle Security, "Scanning 7.6 Petabytes of HuggingFace Training Data for Secrets" (Jun 1, 2026) · Truffle Security, "Introducing TruffleHog AWS Analyze" (Aug 20, 2026) · BleepingComputer, "Hundreds of leaked AWS keys give full control over corporate accounts" (Aug 21, 2026) · Cybernews, "Massive exposure: researchers test leaked AWS keys, 9 out of 10 still authenticate" (Aug 21, 2026)