Restricting what an AI agent can reach is a race you lose
You strip a permission on Monday, and an engineer with a blocked ticket grants it back by Thursday. You put a human approval in front of the dangerous actions, and by Anthropic's own count, that human says yes 97% of the time. And the one control that catches rm -rf on sight cannot see the API call that wipes a customer table, because to anything reading the traffic, the two look nothing alike.
Every published guide to agent security says the opposite. OWASP, Microsoft, GitHub, and both companies at the center of the July intrusion landed on some version of scope it tighter and watch it closely. All of it is worth doing, as long as it is not where you stop.
Everyone agrees on the fix, and recovery is not part of it
OWASP calls the problem Excessive Agency: an agent with more functionality, permissions, or autonomy than its task needs. In the 2026 edition of its Top 10 for LLM Applications, published August 4, 2026, Excessive Agency jumped from sixth place to third, the biggest move on the list. The reason is blunt. OWASP checked its practitioner survey against 7,714 real incidents this year, and agentic deployments are where the damage is landing.
Read the right-hand column. It is one idea in five vocabularies: keep the agent away from things, and notice fast when it gets near them. Recovery does not appear in any row.
Recovery is the control everyone left out
Every control in that column runs before the write, and when the last of them fails, the only question left is whether you can put the data back.
Not one of these documents tells you how to put the data back, and from what we hear in customer conversations, that gap is now the biggest risk in the room.
Least privilege works until you need the agent to do its job
To be fair, everything in that table shrinks the surface an agent can damage. A dedicated identity per agent means you revoke one thing instead of rotating a shared secret, and task-scoped roles cut the blast radius of an honest mistake. Allowlisted tools keep an agent from discovering a capability nobody meant to hand it.
Nobody should stop doing this work. The argument is narrower: restriction cannot be the finish line, and the guidance published so far treats it as one. The open question is what happens once you finish scoping and the agents are still writing to production.
Your own team hands the permissions back
Every permission you strip makes the agent worse at the job you hired it for, so the pressure to loosen comes from inside the team. Microsoft's guidance describes the pattern without flinching. A team grants a broad Reader role because the use case looks read-only, the workflow expands to fixing what it finds, and instead of redesigning the role, the team grants something broader and moves on.
Anthropic measured the same erosion in Claude Code. As of June 2026, 49.5% of active Claude Code CLI users had written a rule telling the tool to stop asking before it runs shell commands. The share was growing about 5 percentage points every 5 weeks. Beyond those rules, 62% had switched Bash prompts off entirely or clicked "don't ask again," and 25% of interactive sessions started with permissions bypassed.

Those are developers on their laptops, where a bad command usually costs a git reset. Now apply the same erosion to the service account an agent uses against a production database. The person deciding whether to widen that role is usually the engineer the agent is blocking, and the role does not get narrower after that.
Bash is also the one channel the built-in undo in these tools does not cover, which we took apart in Claude Code's /rewind Won't Bring Back What Bash Deleted.
So the permissions come back, and the last line of defense is the approval prompt.
Human approval decays to 5% inside one session
Claude Code users reject 3% of individual permission prompts and 39% of the plans put in front of them, per Anthropic's August 7, 2026 data. People do say no when they actually read the prompt, but when dozens of prompts come up a day, they may start clicking “Approve” without reading.
Anthropic measured the decline in a controlled study of 1,053 paid professional testers. A research vendor swapped one permission prompt in each session for a clearly dangerous command. Early in a session, testers caught about 17%. After 50 or more prior prompts, the catch rate fell to about 5%. Nobody reads the fortieth prompt of the hour.

Swapping the human for a model does not close the gap
The obvious fix is to replace the tired human with a model, and Anthropic made its classifier the default on August 14. The classifier is better than the human and, by Anthropic's own account, still not good enough for production.
The March 25 engineering write-up reports that the classifier let through 17% of the real cases where the agent went further than the user asked. The August post still recommends that people review the agent's actions themselves for high-stakes changes to production infrastructure. The review Anthropic recommends for production is the one that caught 13.6% of dangerous commands in its own study.
The review Anthropic recommends for production is the one that caught 13.6% of dangerous commands in its own study.
And even a gate that never tires has a built-in blind spot.
The dangerous part of an API call is the part no gate reads
A classifier can catch rm -rf because the command announces itself, and that is the whole reason a reviewer or a classifier stands a chance. A reviewer often won’t catch a well-formed POST to a documented archive endpoint. Whether it is routine cleanup or a catastrophe depends entirely on the request body, the part of the call that names which records, and nothing in the request itself tells you which.
Anthropic's classifier authors say as much. Their classifier deliberately never sees the results of the agent's earlier steps. So if the user never named the target, it cannot tell whether the agent pulled that ID from a query or made it up. A row delete in production is a valid SQL statement or API call, identical to the thousands of harmless ones before it.
Hugging Face saw exactly this in July 2026, when OpenAI's models escaped an evaluation sandbox during an internal cyber-capability test and got into Hugging Face's production systems. Its dataset loader carried a URL allowlist, and the allowlist worked: it rejected every attempt to make the worker fetch a remote resource. So the agent stopped asking the worker to fetch things and instead acted on local ones, through a data file that pointed to a local path and a template field that ran code. In Hugging Face's words, neither is a URL fetch, so the allowlist never saw them.
A gate can only judge what it can see, and it never sees which records the call names.
July was a containment and exfiltration story, and recovery does nothing for exfiltration. The data-loss version had already happened in February.
One command took the database and its backups together
On February 26, 2026, the founder of DataTalks.Club used a coding agent to fold a static website into the Terraform setup that already ran his production course platform. The Terraform state file was still on his old laptop, so Terraform believed nothing existed and started creating duplicates of resources that were already running.
He stopped the apply and copied the old machine's Terraform archive over. The archive held the production state, and the agent unpacked it without him noticing. With the full picture in hand, the agent proposed terraform destroy as the cleaner way to remove the duplicates. Auto-approve was on. He did not stop it.
The destroy removed the VPC, RDS database, ECS cluster, load balancers, bastion host, and every nightly snapshot. Two and a half years of student submissions were gone: 1,943,200 rows in one table alone. The platform came back about 24 hours later, after he upgraded to AWS Business Support and an engineer found an internal snapshot that was not visible in his console.
Nothing in that sequence is specific to AI. Someone with the same state file and permissions could have done it, minus the pause a person usually notices.
Automated backups were deleted together with the database.
His lesson, in his words: "Automated backups were deleted together with the database." Native snapshots and versioning live in the same account, under the same credentials, in the same lifecycle as the data. They cover an isolated mistake. Against a full-resource removal or an actor holding the account's credentials, the call that deletes the resource deletes them too.
What to do instead of racing
A VP of architecture at a payments company put it plainly to our team: the scenario that worries them is their own code, ahead of ransomware. Here are some controls to implement:
- Give the agent its own identity. An agent on a developer's credentials inherits everything the developer can do. A dedicated identity forces the decision about what this agent may touch, makes every action attributable, and ends a session with one revoked role.
- Put human review outside the agent's reach, and only on irreversible actions. Destroy, drop, replace, schema changes. A prompt inside the tool is the first thing a blocked engineer switches off, so put the review somewhere the agent cannot bypass. Gating everything is how you end up at 97%.
- Treat state as production data. Terraform state and migration history decide what "cleanup" means. State belongs in versioned remote storage with deletion protection, moves between machines through that storage and never by hand, and the agent's identity reads it at most.
- Protect the resource at the platform level. Deletion protection on the database, prevent_destroy on the module, Object Lock on the bucket. A rule in a config file is advice the model can override; these hold regardless of what the agent decides. They stop removal, do nothing about a valid write to the contents, and are not a backup.
- Keep a copy that survives the loss of the thing it protects. A separate account with its own identities, so a credential that can destroy the infrastructure cannot reach the copy. Granular to the row or object, so you put back what the agent touched and nothing else. Native snapshots fail this test; DataTalks.Club proved it in one command.
- Make every write attributable. Identity plus audit logging means every mutating call ties to a specific agent, resource, set of records, and time. When a valid credential makes a valid call against the wrong records, nothing alerts, and the first hour is spent figuring out what changed. The hour is short only if you recorded the answer before the incident.
Controls one through four decide how often a bad change reaches production. Five and six decide what happens when one does, and five is the one almost nobody has.
We built Eon Data Protection for control five. Eon's backups land in isolated vaults, logically air-gapped and immutable, held in a separate account from your production environment and apart from your native snapshots. Access runs through time-bound keys, so the recovery copy sits outside the blast radius of compromised production credentials. Eon detects corruption and ransomware signals inside backups across VMs, object storage, and databases, then restores exactly what you need, a file, object, table, or database row, without rebuilding the environment around it. SoFi cut recovery time from a day to minutes across five AWS regions.
DataTalks.Club got its data back because an AWS engineer found a snapshot the customer could not see. Do not build a plan on that. Know, before the agent runs, exactly which records you could put back and how long it would take.





