Claude Code 2.1.223: verify the permission-bypass fixes before restoring autonomy
Quick answer
Claude Code 2.1.223, released August 6, 2026, fixes four security-relevant boundaries: a crafted Bash command could hide part of itself from permission checks; tabs or invisible Unicode could hide content in the approval prompt; workflow scripts could use dynamic import() to execute outside the workflow sandbox; and an agent definition using bypassPermissions could ignore an organization policy that disabled bypass mode.
Upgrade every Claude Code launcher that can execute commands, restart existing sessions, and keep unattended workflows paused until a harmless regression pack passes. Test the prompt renderer, command parser, managed bypass policy, and workflow sandbox separately. Do not copy a public exploit string into a production terminal: use marker-only fixtures in an isolated repository and verify that no unapproved marker file is created.
The release note does not publish a CVE, severity, exploit payload, or complete affected-version range. Treat 2.1.223 as the minimum verified fixed build for these four items, not as evidence that every earlier build is exploitable in every configuration.
Who this is for
This guide is for developers and platform teams running Claude Code locally, in IDEs, through background agents, or in managed automation. It matters most when Bash commands can mutate a repository, agent definitions request a permission mode, or workflow scripts execute code.
This page covers permission interpretation and workflow isolation. Use the credential-file masking checklist for secret injection, the strict network allowlist checklist for egress, and the broader sandbox and worktree checks for filesystem isolation.
What changed, and what did not
| Boundary fixed in 2.1.223 | What to verify | Safe evidence |
|---|---|---|
| Bash permission analysis | Every executable part is classified before it runs | The benign second marker command prompts or is denied |
| Approval-dialog rendering | Tabs and invisible formatting cannot conceal command meaning | The dialog shows the full normalized action or blocks it |
| Workflow script sandbox | Dynamic imports cannot escape the workflow boundary | An outside-boundary fixture remains unread and unwritten |
| Organization bypass policy | Agent-level bypassPermissions cannot override the admin disable policy |
The agent request is rejected or falls back to an allowed mode |
These fixes do not make every shell command safe, turn the permission dialog into a semantic code review, or replace OS-level isolation. Anthropic documents permissions as a pre-execution decision layer and the Bash sandbox as a separate OS-enforced filesystem and network layer. Keep both.
A six-stage rollout workflow
1. Inventory every launcher
List the executable and version used by the terminal, desktop app, IDE integration, CI job, background agent, and corporate launcher. Record the install channel and resolved path. A package lock or another developer's terminal is not runtime evidence.
Surface:
Resolved executable:
Reported version:
Permission mode:
Managed-settings source:
Sandbox status:
Workflow scripts enabled:
Owner:
If one surface still reports an older build, keep that surface out of autonomous work even when another surface has upgraded.
2. Upgrade, restart, and prove the process version
Upgrade through the channel you already manage, close long-running sessions, then launch a new process and run claude --version. Preserve the output with a timestamp. Do not assume a resumed or background session adopted the new executable.
3. Keep bypasses closed during the canary
Use trusted user or managed settings, not repository-controlled configuration, to disable bypass mode. If sandboxing is a required boundary, also make unavailable sandbox support fail closed and disable the unsandboxed retry escape hatch.
{
"permissions": {
"disableBypassPermissionsMode": "disable"
},
"sandbox": {
"enabled": true,
"failIfUnavailable": true,
"allowUnsandboxedCommands": false
}
}
Claude Code evaluates explicit deny rules before ask and allow rules. Keep a narrow deny or ask rule for consequential commands even when a sandbox is enabled; sandbox auto-approval and command permission are related but distinct controls.
4. Run a payload-free command and prompt matrix
Create a disposable repository containing no credentials. Each fixture may only print a unique marker or create a file inside a temporary canary directory. Test these classes without publishing the historical bypass syntax:
- A normal read-only command behaves as expected.
- A compound command whose first half is allowed and second half creates a marker still evaluates the second half.
- Leading tabs do not hide the second marker action in the prompt.
- Unicode formatting characters cannot make the displayed command differ from the action that would run.
- A wrapper or environment assignment does not cause a denied marker command to inherit an unrelated allow rule.
- Canceling the prompt leaves the marker absent.
The pass condition is not merely “a prompt appeared.” Compare the displayed meaning, final decision, exit result, and marker state. If the dialog is ambiguous, cancel and record a failure.
5. Test agent policy and workflow isolation separately
Create a test agent definition that requests bypassPermissions, while managed settings disable that mode. The agent must not gain bypass behavior. Then create a trusted workflow canary whose normal import reads an in-boundary fixture and whose negative case targets a harmless fixture outside the workflow sandbox. The outside fixture must remain inaccessible and unchanged.
Do not test with SSH keys, environment files, package credentials, or production paths. The purpose is to prove enforcement, not to demonstrate impact.
6. Restore autonomy one surface at a time
Start with one low-impact repository and one launcher. Observe permission decisions, sandbox failures, unexpected mode fallbacks, and workflow errors. Expand only after the same evidence pack passes on each OS and interface you support.
Eight acceptance gates
| Gate | Required result |
|---|---|
| Version | The actual launching process reports 2.1.223 or newer |
| Session freshness | Long-running and resumed sessions were restarted or re-proved |
| Prompt fidelity | Tabs and Unicode cannot hide a marker action |
| Parser completeness | Every compound-command action receives its own decision |
| Deny precedence | A denied marker remains denied across wrappers and assignments |
| Admin policy | Agent definitions cannot reactivate bypass mode |
| Workflow isolation | Dynamic imports cannot touch the outside fixture |
| Containment | Sandbox-unavailable and canceled cases leave no marker or side effect |
Common mistakes
Upgrading only the interactive CLI. IDEs, background agents, desktop sessions, and corporate launchers may resolve a different binary.
Using a real exploit or real secret as the canary. A regression test should be safe even when the product fails it.
Treating a readable prompt as proof of enforcement. Check the resulting marker and exit state; rendering and execution are two different assertions.
Re-enabling bypass mode immediately. The 2.1.223 fix protects the organization policy boundary, but bypass mode still intentionally skips most prompts. Anthropic recommends using it only inside isolated environments.
FAQ
Must every pre-2.1.223 installation be treated as compromised?
No. The release confirms fixes, not exploitation. Inventory exposure and review logs for unexpected commands or policy violations. Rotate credentials only when your evidence or incident policy justifies it, not because a version number alone proves compromise.
Is the Bash sandbox enough after upgrading?
No. Permissions decide which tools and commands may start; the sandbox limits filesystem and network access for Bash commands and child processes. Keep narrow rules, sandbox boundaries, least-privilege credentials, and human review for consequential actions.
Top comments (0)