Two kinds of bad week#

This week looked like everything got hacked at once. Theo’s useful move in his latest video is to split the pile in two.

On one side are vulnerabilities: bugs found, often by AI, in software everyone runs. PHP2Shell is the headline, and I covered it and Microsoft’s Storm-0940 report in today’s Digest. Node.js shipped security fixes the same day. These are serious, but they follow the old script: a patch exists, and your job is to apply it before someone else exploits the gap.

On the other side are actual attacks on companies developers trust with their secrets. OpenCode, the open-source coding agent, and Railway, the hosting platform, both had customer credentials taken. Theo argues this second column is the scarier one, even though it got less attention. I agree, and the reason is what the attackers wanted.

What actually happened#

OpenCode. On the night of October 16, an intruder got into a legacy system behind OpenCode Console, the optional hosted service where teams can paste their own OpenAI, Anthropic or Google keys so members can use models without seeing the key. OpenCode says 1.4% of Console users were affected, all of them people with an outside provider linked, and that it emailed every one of them on October 17. The email puts the earliest possible exposure at 00:30 UTC on October 17. The CLI and desktop app were not involved. Keys you add there stay on your machine, or as co-founder Dax Raad put it, those keys “never come to us.”

The bills came fast. Users posted spend alerts firing overnight. BleepingComputer collected reports from several hundred dollars up to $1,700, and Google suspended some users’ projects for “hijacked resources.” Anthropic and Google blocked keys they believed were exposed. OpenAI said it worked with OpenCode on refunds, and OpenCode says refunds for unauthorized charges are underway.

Railway. On October 21, Railway disclosed that a third party “may have accessed encrypted environment variables and, for some of them, obtained the decrypted contents.” Environment variables are where apps keep API keys and database passwords. Railway told every user to roll every variable, invalidated all its own API tokens, and reset storage bucket and GitHub credentials itself. Builds were paused across the platform while it investigated, so customers could rotate keys but not deploy the new ones. Enterprise waited most of a day, cheaper plans longer. Builds came back by plan tier, with Enterprise first and Free and Trial last, late on October 22 UTC. As of this morning Railway is still emailing customers with a high likelihood of impact, and its preliminary incident report is due around midday Eastern time today.

Theo is a Railway customer and he is furious about the outage. That part is a reliability complaint, not a security one, and I’ll leave it to him.

Why your keys are suddenly worth stealing#

Here is the part I think most coverage missed. Railway said it believes the breach is “part of a series of attacks recently targeting platform companies with the aim of compromising AI inference providers.” OpenCode called its breach “related to a large-scale distillation attack.”

Distillation means training a model on another model’s outputs. Frontier labs ban the Chinese labs that want those outputs, check identities, and throttle new accounts. In September, CISA, the NSA and the FBI put out a joint advisory naming DeepSeek, Moonshot AI, Alibaba, MiniMax, StepFun and Z.AI as having pulled billions of tokens from Claude, GPT, Gemini and Grok since at least late 2024.

Theo’s argument follows from that. If you can’t buy the tokens, you borrow someone else’s key. A stolen key doesn’t need a credit card or a fake ID. It works until the owner or the provider notices. That might be an hour, but in an hour the key can burn through hundreds or thousands of dollars of someone else’s money. So any platform that stores keys is now a target, and the old logic that a hosting provider’s secrets were only useful for slow data theft no longer holds.

To be fair, the distillation link is the companies’ claim, not a proven fact. TechCrunch notes skeptics who see a plain breach with a convenient story on top. For you it doesn’t matter. Whoever took the keys, the result was the same: unauthorized spend within hours.

The defenders were stuck too#

One more detail turns this from bad to grim. Raad said attackers kept at OpenCode’s systems for 48 hours, and the AI models his team used for analysis started refusing once the malicious code tripped their safety filters. Things improved after OpenCode got into OpenAI’s Daybreak Blue program, which gives vetted defenders models that refuse less.

Theo makes the same complaint about his own work. The labs have made attacks cheaper and made the response harder for anyone without special access. A small team that gets hit this weekend will not have a vetted security program waiting.

What I’m doing, and what you should do today#

I build agents for clients, and almost every one of them has a provider key sitting in an environment variable on some host. Here’s the checklist I’m running.

  1. Revoke at the provider, not the platform. Deleting a key from OpenCode Console or a Railway variable does nothing to a copy an attacker already has. Kill it in the OpenAI, Anthropic or Google dashboard, make a new one, then update every app that used the old one. If you’re on Railway, do this for every secret, not just AI keys. Its guidance covers databases, Stripe, GitHub, AWS and GCP.
  2. Set a hard spend limit, not just an alert. On OpenAI, a spend alert only sends an email while traffic keeps flowing. You have to turn on “Enforce a hard limit” at the organization or project level, and OpenAI warns enforcement can lag a little. Anthropic lets you set a monthly limit for the whole organization on the Billing page and per workspace, though not on the default workspace. Pick a number you could lose without a bad week.
  3. One key per tool, per environment. Put each app in its own OpenAI project or Anthropic workspace with its own key and its own cap. When something leaks, you revoke one key, the blast radius is one budget, and the usage page grouped by key shows you exactly what happened. A shared key across five tools turns one breach into five outages.
  4. Keep keys local when you can. The OpenCode CLI never sent keys anywhere. Only the hosted Console held them. Every hosted dashboard you paste a key into is one more company you’re trusting. Sometimes that’s worth it for a team. Make it a choice, not a default.

Then check your usage. Group by key and go back to at least October 16. Look for models you don’t use and traffic at hours you don’t work. If you find spend you didn’t make, save the data and contact the provider. OpenAI refunded OpenCode victims for credits used in the attack, so it’s worth asking.

The real lesson#

PHP2Shell will fade the usual way: patches roll out, scanners find the stragglers, and the long tail of dead WordPress sites gets owned as always. The key problem won’t fade. As long as frontier tokens are scarce for some buyers, every API key is cash sitting in a config file, and every platform that holds keys is a vault.

Treat your keys like a card number with no fraud protection. Cap them, split them, and make them easy to kill.