A permission prompt is not a safety control if the person approving it cannot reliably see what it means.
Claude Code’s July 15 v2.1.211 release fixed a subtle but important issue: permission previews relayed to chat channels did not neutralize bidirectional-override, zero-width, and look-alike quote characters. In other words, tool input could visually alter the approval message. The release notes describe the fix directly.
This is not a reason to panic or abandon coding agents. It is a reason to stop treating a rendered approval sentence as the whole control plane.
For teams that let agents read tickets, PR comments, web pages, or MCP results, the practical implication is simple: untrusted text can reach an agent workflow, while an approval UI may be the last human checkpoint before a privileged action. OWASP lists prompt injection as a core LLM risk and recommends least privilege, segregation of external content, and human approval for high-risk actions. OWASP LLM01
The threat model: the dangerous string may not look dangerous
Imagine a coding agent reads an issue, a PR comment, or a fetched page. That content suggests a command. The user sees a friendly-looking approval preview in a chat relay and approves it.
The v2.1.211 fix specifically concerns Unicode controls and visually confusable characters in the preview. It does not mean every approval prompt is compromised, and it does not prove a command will execute. It does show why an approval message must be backed by technical limits that still work if text is ambiguous or misleading.
Anthropic’s own security guidance makes the same design direction clear: Claude Code defaults to read-only access, requests permission for sensitive actions, supports sandboxing, and recommends reviewing commands, avoiding direct piping of untrusted content, and using isolated environments for risky external interactions. Claude Code security guidance
Build a four-layer approval path
1. Keep the default capability small
Start agents in a project directory, not your home directory or a broad monorepo root. Give each task the smallest write scope and the smallest credential scope it needs.
A useful default is:
| Capability | Default | Escalate only when |
|---|---|---|
| Read repository files | Allowed inside the task workspace | The task needs a documented external dependency |
| Edit files | Allowed in a disposable branch or worktree | The diff is reviewed before merge |
| Run shell commands | Prompt or sandboxed | The command is in an explicit task allowlist |
| Network access | Disabled or allowlisted | A specific host is needed for the task |
| Git push, deploy, secrets | Denied | A separate, human-owned release step approves it |
This is least privilege in operational form. An agent that cannot reach production or read a token cannot turn a misleading approval prompt into a production incident.
2. Sandbox the work that does not need your machine
Use a disposable dev container, VM, or sandbox for tasks that process external content or run generated code. The point is not to trust the agent more. It is to make a bad decision less expensive.
Claude Code documents a sandboxed Bash mode with filesystem and network isolation; its cloud execution environment also uses isolated VMs and scoped credentials. Sandboxing guidance Claude Code security guidance
A simple policy shape might look like this:
agent_task:
workspace: ./worktrees/issue-1842
network:
allow: ["registry.npmjs.org", "api.github.com"]
write_scope: ["src/**", "tests/**"]
deny_actions: ["git push", "deploy", "read ~/.ssh/**", "read .env"]
human_gate:
required_for: ["network changes", "dependency upgrades", "database migrations"]
The syntax is illustrative. The important part is that enforcement happens outside the model’s prose.
3. Put policy in hooks and CI, not only in prompts
A system prompt can tell an agent not to touch deployment files. A hook or CI check can refuse the action.
In the same v2.1.211 release, Claude Code fixed auto mode overriding a PreToolUse hook’s ask decision for unsandboxed Bash. That is a valuable reminder: use hooks as a gate, then test the gate after upgrades. v2.1.211 release notes
For example, make a policy check fail closed when an attempted command includes a deployment path, secret filename, destructive database operation, or an unapproved network destination. Require a human-owned CI job for the actual release.
This complements the approach in Your Coding Agent Is Tripping EDR Alarms (And the Rules Are Right): security tooling should observe and constrain risky behavior, rather than blindly suppress it.
4. Log the exact action, not just the summary
For privileged approvals, retain the raw command or structured tool arguments, the working directory, the network destination, the identity that approved it, and the policy decision. Render a safe summary for humans, but make the canonical record machine-readable and auditable.
That lets your reviewer answer a better question than “Did the prompt look okay?”: “What exact operation was authorized, under which policy, and could it have reached anything sensitive?”
A 20-minute hardening pass
What to do now
- Update Claude Code to v2.1.211 or later if you use relayed permission previews. Release notes
- List every route where untrusted content enters an agent: issues, PR comments, docs, web fetches, MCP servers, and uploaded files.
- Move external-content tasks into a sandbox or disposable worktree with an explicit network allowlist.
- Add one enforced gate for high-impact actions. Good first candidates:
git push, deployment commands, migrations, credential reads, and curl/wget to unknown hosts. - Run a negative test: put misleading Unicode text in a fixture or test issue and confirm that the policy gate still blocks the underlying action.
- Review the exact approval and tool-event logs for one agent task this week.
Where this does not apply
If your agent only makes local, reviewed edits in a throwaway workspace with no network, credentials, or deployment access, the blast radius is already much lower. You still benefit from clear logs, but you may not need a complex policy system.
Conversely, a polished approval UI is not enough for agents with broad host access, automatic network access, or authority to merge and deploy. The more autonomous the workflow, the more your safety needs to come from isolation, deterministic enforcement, and auditable handoffs.
For another reliability control that pairs well with this, turn real failures into repeatable tests: Stop Replaying Coding-Agent Bugs by Hand: Turn Traces Into Regression Tests. For collaboration design, see Claude Code Agent Teams: When Shared Context Beats More Subagents.
Sources
- Claude Code v2.1.211 release notes
- Claude Code security guidance
- Claude Code sandboxing documentation
- OWASP LLM01: Prompt Injection
Where does your team enforce the final boundary for an agent action: in the approval UI, a sandbox, a hook, CI, or somewhere else?
Top comments (0)