- Home
- The Thinking Wire
- Miss One Tool and the Allowlist Is Already Defeated
Miss One Tool and the Allowlist Is Already Defeated
Two teams shipped the same two conclusions in the same week without citing each other.
The first, from the Kiro team at AWS, describing why they rebuilt the permission model shared by their CLI and IDE agents: “In both clients, permissions were per-tool: a single intent like deny reads to .env had to be configured separately for every tool that could read files (read, glob, grep, code intelligence). Miss one and the agent could still access the file through a different tool.”
The second, from Magnus Hedemark, writing about QM, the fleet manager Y Combinator open-sourced after provisioning more than 50 Hermes agents as personal assistants for employees and finding even that size of fleet hard to manage: “A company isn’t one person with a very long chat history.”
Both sentences are about the same thing. A permission rule has a unit, and most teams have chosen the wrong one.
The unit is the capability, not the tool name
Kiro’s replacement is one line long: “A deny on fs_read blocks every tool that reads files (read_file, grep_search, file_search, and any future read tool) without enumerating them individually.”
The load-bearing phrase is “any future read tool.” An enumerated allowlist is a list that ages. Every tool added to the harness after the rule was written silently widens what the rule permits, and nobody opens a ticket, because nothing breaks. The agent just gains a second door to a room you locked once. Semantic search, a new code-intelligence backend, an MCP server someone wired in on a Thursday: each of them can read .env while your denylist still names read and looks satisfied.
Capability classes invert the default. You write the intent once, against fs_read or fs_write or exec, and every present and future implementation of that capability inherits it. New tools arrive already governed. Enumeration becomes the exception you justify, rather than the mechanism you depend on.
We have argued before that permissions belong where the data lives, and measured how badly instruction hierarchies resolve at runtime. Capability classes are the missing piece of syntax that makes both of those practical. A rule you cannot express compactly is a rule you will not maintain.
Three matching semantics for one product
Before the unification, Kiro’s own surfaces disagreed about what a rule even means: “the CLI used regex-based allowedCommands/deniedCommands, while the IDE used prefix matching for trustedCommands and substring matching for its denylist.”
Regex, prefix, and substring are three different theories of what a rule covers. A substring denylist entry for rm matches charm, format, and any path containing those two letters, while a prefix rule for git fails to catch sudo git. One security engineer writing one policy for one company produces three different enforcement outcomes depending on which client the developer happened to open.
The fix is boring and correct: one matching language across every surface, glob for paths, with the same semantics wherever the rule is evaluated. If you run agents in more than one place, and almost everyone does now (terminal, IDE, CI, a hosted runner), the first question is not what your policy says. It is whether the two places that read it agree on what it says.
Deny always wins, and the agent cannot edit the rules
Kiro’s policies are written in Cedar, described by the team as “a formally verified policy language.” They compose across scopes with deny-always-wins semantics, they can be pushed by enterprise administrators through MDM, and they enforce one invariant that most home-grown setups quietly violate: “the agent cannot modify its own permission files.”
That invariant is worth checking today. In a typical repo, the agent config sits in the repo, and the agent has write access to the repo. The ceiling is therefore advisory. An agent that can edit its own denylist does not have a denylist; it has a suggestion file with good intentions and a git history.
The separation is architectural, too. On why the permission engine runs as its own process, the Kiro team wrote: “We saw from earlier attempts that shared libraries don’t enforce a strong enough boundary… A standalone process makes the separation real.” That is the same reasoning that produced OS-level containment for agent execution, applied one layer up. A boundary that lives inside the thing it constrains is decoration.
Five scopes, because authority is organizational
QM arrives at the problem from the opposite end. Where Kiro asks what a single agent may touch, QM asks whose authority the agent is acting under. Hedemark notes that QM defines five scope kinds in src/types.ts: personal, channel, group, team, and organization. Turns are routed to swappable harness adapters for Pi, OpenCode, Codex and Claude Code.
His framing of the split is the cleanest I have read: “The loop does the turn. The control plane keeps track of the organization in which the turn means something.”
The consequence is an operational one most teams have not faced yet. “When an employee leaves, their authority needs to leave with them.” If your agent permissions live in dotfiles on laptops and in per-repo config, offboarding an employee does not offboard their agents. The credentials might get revoked. The delegated authority, the standing approval that lets some workflow act on that person’s behalf, keeps running until someone remembers it exists.
This is also why harness adapters matter more than they look. The vendor under your agents will change. Your org chart, your scopes, and your audit obligations will not. A control plane that is welded to one harness has to be rebuilt every time the market moves. The containment stack is only durable if its top floor outlives the floors below it.
The honest part: a named posture is not an enforcement
Hedemark does not sell the thing he is describing. He pins every QM claim to a single repo commit, writes explicitly as a Hermes Agent user, and frames the piece as “a useful contrast, not an objective product comparison.” He then lists what does not work yet: Auto is the default security posture; Strict “pauses for human approval on every harness tool call except two no-effect turn enders”; and “Local Docker and the default AWS backend don’t enforce QM’s domain egress allowlist.”
The last item is the sharp one. A workspace labeled with an egress allowlist, running on the default backend, has a label. The packets still leave. Every governance layer has some version of this: a posture name in a config file that no runtime component is actually checking.
Neither of these two pieces contains efficacy measurements. Both are architecture writeups, not results. The Kiro post carries no publication date and states no roles for the people credited on it. Take both as design arguments that converged independently, which is evidence of a real constraint, and not as proof that either implementation holds under attack.
Do this now
Four checks, roughly an hour, on the agent setup you already run.
Count the doors for one rule. Pick a single permission you believe you have, like “agents cannot read secrets.” Write the intent in one sentence. Then list every tool in your harness that could satisfy that intent: read, grep, glob, semantic search, code intelligence, every MCP server, shell. If the tool count exceeds your rule count, you have the Kiro bug right now.
Diff the matching semantics. Find where each surface evaluates its rules. Is it regex, prefix, substring, or glob? If two surfaces answer differently, your policy has two meanings and you have been reading one of them.
Check who can write the policy file. Run ls -l on it, then check whether it sits inside the workspace the agent can edit. If it does, treat the whole permission model as advisory until you move it.
Name your scopes out loud. Personal, team, organization: which of those exist as enforced objects in your setup, rather than as conventions? Then test the one that matters: if someone resigns tomorrow, what revokes the authority their agents are acting under, and how long does it take?
The team that fixes only the first check still improves. The team that answers the fourth one has a control plane.
This analysis synthesizes One agent, every surface: how we built the Kiro agent harness (Kiro, AWS, 2026) and QM Is Trying to Solve the Company Agent Problem (Magnus Hedemark, Notes from the Rabbit Hole, July 2026).
Victorino Group helps engineering organizations rewrite per-tool agent permissions into capability classes and organizational scopes that survive the next harness. Let’s talk.
All articles on The Thinking Wire are written with the assistance of Anthropic's Opus LLM. Each piece goes through multi-agent research to verify facts and surface contradictions, followed by human review and approval before publication. If you find any inaccurate information or wish to contact our editorial team, please reach out at editorial@victorinollc.com . About The Thinking Wire →
If this resonates, let's talk
We help companies implement AI without losing control.
Schedule a Conversation