
“Sorry, Typo”: Why a Markdown File Is Not a Security Control
PCWorld ran a piece last week on the one command you should never let an AI coding agent execute: rm -rf. The reporting is solid and the anecdotes are grim — developers who let an agent handle a routine cleanup task and lost a home directory, a project tree, or an entire drive. In one widely shared case, the agent was asked to create a backup, wrote it to the wrong location, recursively force-deleted the drive, and then apologized for the typo.
The recommended fix was to add a rule to CLAUDE.md or AGENTS.md instructing the agent never to run recursive forced deletions, including reordered flags, aliases, shell wrappers, and equivalents like find -delete or git clean -fdx.
That advice is directionally correct and worth doing. But it is not a control, and the distinction is the entire point of this post.
A CLAUDE.md instruction is a prompt. It is processed by the same probabilistic layer that generated the destructive command in the first place. You are asking the thing that made the mistake to please remember not to make the mistake. In control language, that is an awareness measure — the equivalent of a wall poster reminding staff not to click phishing links. Useful. Not the thing you point an auditor at.
Real controls sit below the model, in a layer the model cannot argue with.
Threat modeling the coding agent
Before reaching for controls, model the thing. An AI coding agent is a process with a shell, network egress, credentials, and a non-deterministic decision function. Run STRIDE against it as you would any other element in a data flow diagram:
| STRIDE | Threat against the agent | Likelihood | Impact |
|---|---|---|---|
| S — Spoofing | A malicious or typosquatted MCP server registers tools the agent trusts; a poisoned dependency masquerades as a legitimate package | M | H |
| T — Tampering | Agent modifies its own configuration, hooks, CI definitions, or .env files; commits changes no human reviewed | M | H |
| R — Repudiation | No durable log of which tool calls ran with which arguments; post-incident, nobody can reconstruct what the agent did | H | H |
| I — Information disclosure | Agent reads ~/.ssh, ~/.aws, credential stores, or an entire knowledge base and emits contents into a prompt, a commit, or an outbound request | H | C |
| D — Denial of service | Unbounded agent loop; destructive deletion of source, database dumps, or infrastructure state | M | C |
| E — Elevation of privilege | Agent runs under a broad service account and performs actions the invoking human is not authorized to perform | H | C |
Read that table again and notice what rm -rf actually is. It is one instance of D, in one row, on one machine. It is the failure mode that gets written up because it is loud and immediately visible. The rows that will actually end up in a breach notification are I and E, and they are silent.
This is OWASP’s Excessive Agency category (LLM06 in the 2025 Top 10 for LLM Applications). The vulnerability is not that the model is wrong sometimes — the model will always be wrong sometimes. The vulnerability is that a wrong decision has been wired to an unbounded capability.
The enforcement stack
Five layers, in order of how much they actually protect you. Each one holds when the layer above it fails.
1. Identity and scope — what the agent is
The agent is a non-human identity. Treat it like one. It gets its own service account, not a developer’s personal credentials. Its permissions are the union of what it needs for the task at hand, not the union of what its human operator happens to be entitled to.
This single decision determines blast radius. Everything downstream is mitigation.
2. Deny rules — declarative policy
Claude Code evaluates permission rules in deny → ask → allow order, and a deny at any settings level cannot be re-allowed by another level or by bypass mode. Managed (organization-level) denies are absolute. Write the deny list first, then decide how permissive to be about everything else:
{
"permissions": {
"deny": [
"Bash(rm:*)",
"Bash(git clean:*)",
"Bash(git reset --hard:*)",
"Bash(find:*)",
"Bash(curl:*)",
"Bash(sudo:*)",
"Read(./.env)",
"Read(~/.ssh/**)",
"Read(~/.aws/**)",
"Read(./secrets/**)"
],
"ask": [
"Bash(git push:*)",
"Bash(npm install:*)",
"Write(**)"
]
}
}
Two engineering notes that matter more than the syntax:
Deny the binary, not the flag combination. Pattern matching is prefix-based. A rule targeting the literal string rm -rf misses rm -fr, rm -r -f, rm --recursive --force, an alias, and anything wrapped in a shell script. Deny rm itself and grant exceptions deliberately.
Test that your rules fire. There are open reports of Bash permission patterns not being enforced as documented (see anthropics/claude-code issue #18846). An untested control is a documented control, which is worse than no control because it produces false assurance. Write a five-line test that attempts each denied command and confirms it is blocked. Re-run it after every CLI upgrade.
3. Policy-as-code hooks — the part that actually generalizes
A PreToolUse hook intercepts every tool call before execution and returns allow, ask, or deny. Two properties make this the load-bearing layer:
- It can parse the command rather than string-match it, so it catches the evasions a glob pattern cannot.
- It fires even under
--dangerously-skip-permissions.
That second property is the one to underline. In practice, “approval fatigue” is what kills agent security programs — a developer running several parallel sessions turns every confirmation prompt into a reflexive keystroke within about a day. The answer is not to demand more discipline from tired humans. It is to move the decision into code that does not get tired.
Hooks are also where the auditability comes from: a hook that logs every intercepted command with arguments, timestamp, session ID, and decision is your non-repudiation control for the R row above.
4. OS-level sandboxing — containing what does run
Permissions decide whether a call executes. Sandboxing decides what it can reach once it does. Claude Code’s sandbox uses Seatbelt on macOS and bubblewrap on Linux/WSL2 (native Windows and WSL1 are unsupported). Devcontainers, ephemeral VMs, and per-project containers do the same job at a coarser grain.
The rule of thumb: an agent operating with reduced human oversight should be operating inside a boundary that makes the reduced oversight defensible. Autonomy and isolation are traded against each other, and the trade has to be explicit.
5. Recoverability — the control that assumes the others failed
Version control on a remote the agent has no credentials to force-push to. Database backups on a system the agent cannot reach. And a restore you have actually performed at least once, because an untested backup is a hypothesis.
Governance mapping
For clients who need this to land in a management system rather than a wiki page:
| Control | ISO/IEC 42001 | NIST AI RMF | NIST CSF 2.0 |
|---|---|---|---|
| Agent inventory, ownership, approved-use policy | Clause 6, Annex A (AI policy, roles, impact assessment) | GOVERN, MAP | GV.OC, ID.AM |
| Scoped non-human identity, least privilege | Annex A (resources, lifecycle controls) | MANAGE | PR.AA |
| Deny rules, hooks, sandboxing | Annex A (operational controls) | MANAGE | PR.PS, PR.IR |
| Tool-call logging and anomaly review | Annex A (monitoring, event logging) | MEASURE, MANAGE | DE.CM, DE.AE |
| Human approval for irreversible actions | Annex A (human oversight) | MANAGE | GV.RM |
| Agent incident handling and post-mortem | Annex A (incident management) | MANAGE | RS.MA, RC.RP |
If you are already certified to ISO 27001, most of this is control extension rather than new work. The gap is almost always the same two things: the agent is not in the asset inventory, and no one has written down what it is permitted to do.
My perspective: the deletion story is the distraction
A lost home directory is recoverable, embarrassing, and over in a day. I want to close on the two failure modes that are neither loud nor recoverable, because they are where I expect the next several years of AI governance findings to concentrate.
Monitor for harmful instructions, because the agent cannot tell instructions from data
Every AI agent shares one architectural property: it has no reliable mechanism for distinguishing content it should reason about from commands it should obey. Everything arrives as tokens. The system prompt, the developer’s request, a README, a Jira comment, a dependency’s post-install script, a scraped web page, a row in a database, a response from an MCP tool — all of it lands in the same context window with the same claim to authority.
That means every data channel into the agent is also an instruction channel. The PCWorld story involved a wrong command the agent generated on its own. The same execution path is reachable by a command an attacker put there — planted in a code comment, an issue description, a vendor’s documentation page, a poisoned retrieval chunk. This is indirect prompt injection, and it is the vector I would use against a client whose agents are wired to real systems.
The cross-privilege version is worse and gets overlooked. A low-privilege user leaves a comment on a shared ticket. A senior engineer’s agent reads that ticket as context and follows the embedded instruction with the senior engineer’s entitlements. Nobody exploited a CVE. The AI layer was simply used as a confused deputy, and the privilege boundary your IAM team spent two years building was crossed sideways.
So: log prompts, completions, retrieved chunks, and every tool call with arguments. Feed them somewhere queryable and set detections on the sequences that indicate manipulation rather than on individual events — an unusual tool paired with an unusual argument, a retrieval followed immediately by an egress attempt, a sudden shift in the ratio of reads to writes, credential-shaped strings appearing in output. This is not novel detection engineering; it is the same behavioral analytics we already apply to service accounts, pointed at a new identity class. The organizations that will struggle are the ones treating agent activity as application telemetry rather than as security-relevant audit evidence.
Do not give an agent your whole knowledge base or database
This is where I push hardest with clients, and where I get the most resistance, because broad access is what makes the demo impressive.
Grant an agent read access to the entire knowledge base and you have collapsed, in a single configuration line, every compartment your organization built deliberately over years. HR files, board material, unreleased financials, customer contracts, security findings, the incident log. The access control model no longer reflects need-to-know; it reflects what was convenient to index.
Three reasons that is not a defensible position:
Read is exfiltration. “Read-only, so it’s low risk” is the most common error in this space. The entire value of a knowledge base is aggregation — a single well-crafted retrieval can surface more in one query than a determined insider could assemble in a month of browsing. Confidentiality impact does not require write access.
Broad service accounts break tenant and role isolation. If the agent queries under its own privileged identity rather than the requesting user’s, then every user effectively inherits the agent’s permissions. Row-level security, tenant filters, and role-based restrictions all sit underneath the layer the agent bypassed. Retrieval must be scoped to the invoking user’s actual entitlements, and vector stores must filter by tenant before results reach the context window — not after.
Aggregation changes the classification. Individually innocuous records combine into something that is not. A regulated institution can hold twenty datasets each rated internal-use and produce, through unrestricted joined retrieval, an output that is material non-public information or a reportable privacy event. Your data classification scheme almost certainly does not model this, because it was written for humans who could not join twenty datasets in 400 milliseconds.
The practical posture: per-purpose retrieval scopes rather than one omniscient index. Identity propagation so the agent’s reach is bounded by the human it acts for. Egress allowlists so a successful injection has nowhere to send anything. Human approval on irreversible and cross-boundary actions. Time-boxed and revocable credentials. Treat every tool response and retrieved document as untrusted input, because that is exactly what it is.
None of this is anti-AI. I use these tools daily and they have materially changed how much a small consultancy can deliver. But the governance question is not whether to adopt agents — that is settled. It is whether your agents are entitled to less than they can currently reach.
In financial data rooms, where a single unauthorized disclosure can move a transaction, that question has a very short answer. Everyone else is on the same trajectory; they just have not been tested yet.
DISC InfoSec helps B2B SaaS and financial services organizations build AI governance programs that survive an audit — ISO 42001 and ISO 27001 implementation, AI risk assessments, and vCISO advisory. If your organization has deployed AI agents faster than it has governed them, let’s talk.
DISC-AI-Governance-Readiness-Assessment-1-1 pdf downloadDownload
MachineLearning & Artificial Intelligence
AI Vulnerability Scorecard: Discover Your AI Attack Surface Before Attackers Do
Your Shadow AI Problem Has a Name-And Now It Has a Score
Most AI Security Tools Won’t Pass an Audit. Here’s a 15-Minute Way to Find Out.

InfoSec services | InfoSec books | Follow our blog | DISC llc is listed on The vCISO Directory | ISO 27k Chat bot | Comprehensive vCISO Services | ISMS Services | AIMS Services | Security Risk Assessment Services | Mergers and Acquisition Securit
DISC InfoSec blog | DISC InfoSec Site
- “Sorry, Typo”: Why a Markdown File Is Not a Security Control
- Security against defeat implies defensive tactics; ability to defeat the enemy means taking the offensive
- ISO 27001 Got You in the Door. ISO 42001 Keeps You There
- The Batch Model Is Broken: Vulnerability Management in the Era of AI-Accelerated Discovery
NIST CSF 2.0 and ISO 27001: Why the Strongest Programs Use Both


