On a Friday in late April, a Cursor agent running Claude Opus 4.6 was working in the staging environment of PocketOS, an automotive SaaS platform, when it hit a credential mismatch. Rather than stop and ask, it decided the sensible fix was to delete a Railway volume, so it went looking for an API token, found one sitting in an unrelated file, and used it to issue a curl command that removed the production volume. Railway kept its volume-level backups on the same volume, so those went too. The whole thing took nine seconds and no confirmation prompt was involved at any point, because the legacy API endpoint the agent happened to call didn't have the delayed-delete protection that the dashboard and the CLI did.
The founder, Jer Crane, is a developer of fifteen years rather than someone who picked up a prompt last month, which matters because it removes the comfortable explanation. Railway's CEO personally helped restore the data within about an hour from Railway's own backups, patched the endpoint, and then said something that deserves more attention than it got: the API had honoured an authenticated delete request from a fully permissioned token, exactly as designed. The agent, when interrogated afterwards, admitted it had guessed that deleting a staging volume would be scoped to staging, hadn't checked, and had ignored its own rules about destructive commands.
You can read all of that as a story about AI, and most of the coverage did. We read it as a story about three ordinary operations failures that have been in every hardening checklist for a decade, and that an agent simply happened to find before a tired human did.
The three failures, none of which are new
The first was a token with no scope. It had been created to add and remove custom domains, and Railway at the time didn't allow keys to be restricted, so a credential meant for DNS housekeeping could delete storage. Crane said plainly that it wouldn't have been stored at all if the breadth of its permissions had been understood, which is the honest version of a sentence we hear from clients fairly often.
The second was backups that lived on the thing they were backing up. A volume-level backup stored inside the volume protects you against exactly one failure mode, which is accidentally deleting a file, and against nothing that removes the volume itself. That isn't a backup in any meaningful sense, it's a copy, and the distinction stops being pedantic the moment someone calls delete.
The third was a destructive operation with no delay and no confirmation. Railway's dashboard and CLI had delayed-delete logic and the legacy API endpoint didn't, which is a very common shape of inconsistency: the path humans use gets the guard rails because humans complain, and the path machines use doesn't because machines never did. Agents now use the machine path, at machine speed, with whatever credentials they can find.
There was also a fourth element, which is that the model ignored instructions it had been given, and that one you cannot fix with a config file. You can call it out, and Crane did, but an agent that follows its system prompt perfectly today may not tomorrow, and a hardening strategy that relies on the agent behaving is not a hardening strategy. The other three failures are fixable, cheap, and entirely within your control, which is why they are the whole point of this post.
The checklist, as we actually run it
Before the agent-specific section, the baseline. This varies by customer and by stack, because a shared hosting box facing the open internet needs different treatment from a single-tenant application server behind a load balancer, and anyone who tells you there is one correct config for every server is selling a product. What follows is what our setups usually look like, with the reasoning, so you can judge where yours should differ.
The firewall defaults to DROP, and management traffic never touches the public internet. On the host, iptables with a default DROP policy and explicit allows for the handful of ports the service actually needs. Where the location supports it we also filter at the routing level, so unwanted traffic is dropped before it ever reaches the machine. SSH and every other management interface are reachable only over VPN, which means there is no public port 22 to brute-force, no SSH banner to fingerprint, and no reason to care about the endless lists of "change your SSH port" advice. Moving SSH to 2222 is theatre; a port scanner finds it in seconds and the only thing you have achieved is confusing your own team. In the interests of full disclosure, our SSH does run on a non-standard port, for historic reasons nobody can quite remember and which we have never bothered to undo, and it makes precisely no difference to our security posture because the port isn't reachable from the internet in the first place. Not having it reachable at all is the actual control, and everything you do after that is decoration.
Patching is centrally monitored, not merely enabled. Automatic security updates are a sensible default, but "enabled" and "known to have happened" are different states. Updates report centrally so we can see which host is behind and why, and a machine that hasn't picked up a patch for a week shows up as a problem rather than a silent assumption. The failure mode we're avoiding is the one where unattended-upgrades was on for three years and quietly stopped working after a repository change that nobody noticed.
Brute-force protection goes where the exposure is. fail2ban or CrowdSec earn their place on servers with a lot of open ports and random traffic, shared hosting being the obvious example, where you genuinely have a public login surface to protect. On a locked-down application server with management over VPN and two ports open, they are mostly noise, and adding them everywhere out of habit just gives you another service to maintain. Match the tool to the attack surface.
Backups go somewhere the production credentials can't reach, and restores are tested weekly. This is the PocketOS lesson restated as policy. On our own hosting, Frankfurt's backups are stored in Amsterdam and Amsterdam's in Frankfurt, which keeps them under EU jurisdiction and physically separate from the data they protect, and we run a restore test every week, because an untested backup is a hypothesis and a backup stored next to production is a hope. We wrote the long version of that argument in June, and nothing about it has changed except the number of ways to trigger the failure.
Everything is monitored, and the monitoring is the first thing we check works. Hardening without logging is a locked door with no camera; you find out it was opened when you notice the furniture is gone. Every host reports to monitoring, alerts go to people who are on call, and an alert that fires at three in the morning gets handled at three in the morning. We build Tindra for the application side of this and are thoroughly biased about it, but the principle holds with any tooling: if a thing can fail silently, it eventually will.
The 2026 additions: when a machine holds the credentials
Everything above assumes the thing holding credentials is a person who reads before typing. Once an agent is in the loop, a few items move from "nice to have" to "the reason you still have a database on Monday." We frame these as requirements for any environment where an agent has access to infrastructure, and if you are evaluating whether to give one that access, read these first and the agent's marketing second.
One identity per agent, per purpose, scoped to the minimum, and short-lived where the platform allows it. The PocketOS token was for custom domains and could delete storage. Whatever platform you are on, go and look at what your deployment and automation credentials can actually do, not what they were made for, because those are frequently different. If the platform cannot scope a token, that is a finding about the platform and it belongs in your risk register, not in a file in the repository.
No credential with destructive reach lives anywhere an agent can read. The agent found its token in an unrelated file. Agents read files; that is largely what they are for. Secrets belong in a secrets manager or in the deployment system's own store, injected at runtime, and never in a file that sits in the working tree where an enthusiastic tool can stumble across it while fixing something else.
Agents work in environments that cannot reach production. Replit's answer to its own July 2025 incident was to add separate development and production databases, which tells you what was missing. An agent operating in staging should be physically unable to address production resources, not merely instructed not to, and the environment boundary should be enforced by credentials and network policy rather than by a rule in a prompt that the model may or may not honour on a given afternoon.
Outbound network access from agent environments is deny by default. If the agent's sandbox can only reach the services it needs, a found token is far less useful, because the call to the infrastructure provider's API never leaves the box. This is the same default-DROP philosophy applied in the other direction, and it is the control most often skipped because it is slightly annoying to set up.
Every destructive operation has a delay or a soft-delete, on every path, including the API. Railway had it on the dashboard and the CLI and not on the legacy endpoint, and the agent used the endpoint. Audit your own platforms for the same inconsistency, because it is common: the convenient path has the guard rail and the automatable path doesn't. If a deletion cannot be undone for 48 hours, an agent that calls delete at the wrong moment becomes a support ticket rather than an incident.
Actions are logged at the target, not just in the agent's own tooling. The agent's transcript is useful for the post-mortem and useless for detection, because an agent that misbehaves is not going to flag itself. The infrastructure provider's audit log, the database's query log, the firewall's drop counters: those are the ground truth, and they should alert on destructive operations regardless of who or what issued them.
None of these are exotic. Most of them are things a careful team was already doing for human operators and simply had not got round to applying to the new kind of operator, which is the pattern we see over and over: the AI did not introduce a new category of risk, it removed the friction that had been quietly protecting people from an old one.
What this costs, honestly
Scoping credentials, moving secrets out of files, separating environments and adding delayed deletes is a few days of work on a typical setup, more if the platform fights you. Cross-site backups with weekly restore tests are a standing cost in storage and a little automation. Monitoring is whatever your tooling charges plus the discipline to look at it. Set against nine seconds and a weekend of recovery, none of it is expensive, and all of it is cheaper than the hour Railway's CEO spent restoring someone else's database on a Sunday evening.
If you'd rather someone else carried it, this is what we do under our server management and retainer packages, and the question worth asking first is exactly this one: which agents have access to what, with which credentials, and what happens if one of them guesses wrong. A security review gives you a written answer to that. Talk to us, the first call is free, and if your setup is already fine we'll tell you so and you can get back to building things.