2 SEP 2026 — An attacker took an API key from a researcher's personal server and spent about US$600,000 of model inference credits over three weeks before anyone noticed, then came back in May. Nobody noticed because the credits had been donated. No invoice ever arrived, and the bill is the detection control most organisations are actually relying on.
How it happened
A researcher at METR, the non-profit that evaluates AI model capabilities, ran a personal EC2 instance intended to sit behind Google authentication. The application on it had a fail-open bug that disabled authentication instead of denying access when the check did not complete.
Attackers found the host through certificate transparency lists, prompted an agent running on it to reveal the API key, and added an SSH key for persistent access. The initial breach was in March 2026. Three weeks of undetected use followed. A second campaign began in May. The disclosure came on 1 September.
The stolen key consumed roughly US$600,000 of inference credits on public models. METR was not out of pocket, because the model developer had donated the credits to the non-profit.
Free credits removed the only alarm that was working
The reason this ran for three weeks is stated plainly in METR's own account: token usage spikes and rate-limit errors are normal during evaluations, and because the tokens were free, no billing alert fired.
That is worth sitting with, because almost every organisation using a metered cloud or model API is in the same position without having decided to be. Nobody writes a control document saying the monthly invoice is the primary detection mechanism for credential theft, and for a great many teams it is.
Once the invoice is gone, whether through donated credits, a committed-spend agreement, a prepaid pool or a bill sent to a finance team that does not read line items, so is the detection mechanism. What replaces it has to be a usage alert configured against a baseline, on the key rather than the account, and almost nobody configures one until after this happens.
Certificate transparency is a public index of your hostnames
The attackers did not scan for this host. They read it from certificate transparency logs, which are append-only public records of every TLS certificate a public authority issues.
The system exists for good reasons — it is how a mis-issued certificate for your domain gets caught — and it has a consequence people forget. Every hostname you obtain a certificate for is published, permanently, within minutes, to a log anyone can query. Naming a host internal-tools-staging and not linking to it from anywhere hides it from search engines and from nobody else.
Two ordinary defences follow. Wildcard certificates publish only the parent domain, hiding the specific hostname. An internal tool should also sit on a network path an outsider cannot reach, which makes the public hostname irrelevant. Monitoring your own certificate transparency entries is worth doing anyway, since it tells you what an attacker enumerating you already sees.
Fail-open is a decision, not a bug
An authentication layer that disables itself when a check fails has chosen availability over access control. That is sometimes the right choice, but never for the component standing between the internet and a credential.
The pattern usually arrives through convenience during development, when the alternative is being locked out of your own tool while debugging the auth path, and it survives because everything appears to work. Nothing about a fail-open check looks wrong in testing, because the tests exercise the path where the check succeeds.
The description in the report is a vibe-coded app, which is the version of this that is going to become common. Generated code produces working authentication far more often than it produces correct failure handling, because the prompt asks for a login and the failure branch is not what was specified.
They came back in May, which is the useful detail
A second campaign two months after the first implies the March intrusion was not fully closed, or that the original entry point still existed.
The SSH key is the likely mechanism. Rotating a stolen API key is the obvious remediation and it is the one that gets done, because the credential is what was abused. An SSH key added to an authorized_keys file is a separate artefact on a separate host, and it survives a credential rotation completely.
This is a general failure in credential incidents. The response addresses the credential that was used, not the footholds the attacker left behind. The checklist is short: authorized_keys files on every affected host, new cron jobs and scheduled tasks, unexpected IAM users and roles, OAuth grants, personal access tokens, and any new webhooks. None of those is found by rotating the key that raised the alarm.
The part that generalises
METR's response was to hire security leadership, separate public-facing applications into isolated production environments, and set spending limits on API keys. The last of those is the cheapest and the one most readers can do this week.
A spending or rate limit on an individual key converts an unbounded loss into a bounded one, and it turns a silent theft into an alert the moment the limit is hit. It costs nothing and it is not on by default anywhere.
Two other things are worth doing at the same time. Never put a production credential on a personal instance. And schedule a regular review of what each key can reach. We reported on accounts hijacked through stolen session tokens to consume paid API subscriptions, which is the same economic model at consumer scale. The pattern in both is that the victim's compute is the product being stolen, and compute does not go missing from an inventory the way a laptop does.