This is Part 2 of our AI Coding Agent Horror Stories series, an in-depth look at real-world security incidents exposing the vulnerabilities in AI coding agents, and how Docker Sandboxes deliver workspace-scoped isolation that contains the worst failures at the execution layer.
In part 1 of this series, we mapped six categories of AI coding agent failures and the architectural reason they keep happening: the agent runs as you, on your filesystem, with your credentials, and nothing sits between the model’s decision and the shell’s execution. For Part 2, we’re going deep on the most destructive failure mode in the entire ecosystem: an AI coding agent deleting a developer’s entire home directory in a single command.
Today’s Horror Story: The Tilde That Wiped a Mac
In December 2025, a Reddit user posting under the handle u/LovesWorkin shared what became one of the most-discussed AI coding agent incidents of the year. They had asked Claude Code to clean up an old repository. Claude executed rm -rf tests/ patches/ plan/ ~/, and the trailing ~/ wiped their entire Mac.
This wasn’t a CVE. It wasn’t a sophisticated attack. It was the AI coding agent doing exactly what it was told, in a way the user did not anticipate, with no architectural boundary to catch the mistake.
In this issue, you’ll learn:
- How a single trailing slash in a
rm -rfcommand erased a developer’s entire Mac - Why the
--dangerously-skip-permissionsflag exists, and why developers keep using it anyway - The pattern this incident shares with the GitHub-issue-#10077 Ubuntu wipe and the Claude Cowork family-photos incident
- How Docker Sandboxes contains this entire class of failure at the execution layer
Why This Series Matters
Each “Horror Story” in this series examines a real-world incident that turns laboratory findings into production disasters. These aren’t hypothetical attacks. They’re documented cases with named victims, screenshotted command logs, and in several cases, public apologies from the vendors. Our goal is to show the human impact behind the security statistics, demonstrate how these failures unfold in practice, and provide concrete guidance on protecting your AI development infrastructure through Docker’s workspace-scoped execution model.
The story begins with something every developer has done: asking the agent to clean up an old repository.
The Problem
On December 8, 2025,a developer posting under the handle u/LovesWorkin shared a Reddit thread on r/ClaudeAI with the title that says everything: “Claude CLI deleted my entire home directory! Wiped my whole mac.” The post climbed past 1,500 upvotes within hours, was amplified by Simon Willison on X, covered by Gigazine in Japan on December 16, and became one of the most-discussed AI coding agent incidents of 2025.
The setup was unremarkable. The user asked Claude Code to clean up packages in an old repository. Routine maintenance, the kind any developer would hand off without thinking. Claude generated and executed:
rm -rf tests/ patches/ plan/ ~/
On the surface, this is a command to delete three project directories. The fatal error is the trailing ~/. In Unix, ~ expands to the user’s home directory. ~/ with the trailing slash means “everything inside the home directory.” Combined with rm -rf, which removes recursively and without confirmation, the command deletes the user’s entire home directory in a single shot.
Within seconds, the developer had lost:
- The Desktop, Documents, and Downloads folders
- The Library folder containing application state for every app on the system
- The Keychain, which broke authentication across every app, including Claude Code itself, which could no longer talk to its own backend
- Years of project files, family photos, and work product
- All of it on an SSD where TRIM had already zeroed the freed blocks by the time recovery was attempted
There was no recovery. As the developer put it in the original thread: “It nuked my whole Mac! What the hell?”
Caption: Once an AI agent gains direct filesystem access, “organize my desktop” can become catastrophic.
The Scale of the Problem
This wasn’t a one-off. It was an instance of a pattern.
On October 21, 2025, weeks before the LovesWorkin incident, developer Mike Wolak filed GitHub issue #10077 against the Claude Code repository. Wolak’s report described a similar failure on Ubuntu/WSL2: Claude Code had executed rm -rf starting from root, and the logs showed thousands of “Permission denied” messages for /bin, /boot, and /etc as the agent worked its way through the system trying to delete files it didn’t own. Every user-owned file on the system was gone. Anthropic tagged the issue area:security and bug. The damning detail in Wolak’s report: he was not running with --dangerously-skip-permissions. Claude Code’s permission system simply failed to detect that the agent’s command would expand destructively before the user approved it.
Two weeks later, on November 28, 2025, GitHub issue #12637 documented yet another variant. Claude Code had earlier created a directory literally named ~ by mistake. Later, when the agent tried to clean up that directory by running an unquoted rm -rf ~, the shell expanded ~ to the user’s actual home directory before rm saw the argument. Same destructive outcome, completely different mechanism. The agent had found a new way to destroy a developer’s work.
Shortly after the January 2026 launch of Anthropic’s Claude Cowork, Nick Davidov, founder of a venture capital firm, used Anthropic’s Claude Cowork, a general-purpose AI agent product to organize his wife’s desktop. He explicitly granted permission for temporary Office files only. The agent deleted a folder containing 15 years of family photos, somewhere between 15,000 and 27,000 files, via terminal commands that bypassed the macOS Trash entirely. Davidov recovered the photos only because iCloud’s 30-day retention happened to still be in effect. The Trash had been bypassed entirely.
These aren’t isolated stories. They’re the same story with different file paths.
How the Failure Works
To understand why these incidents keep happening, we need to look at the architecture of how a modern AI coding agent executes commands on a developer’s machine. The agent is doing exactly what its design says it should do. The architecture is the failure.
- The Coding Agent (Claude Code, Cursor, Replit, Kiro) is an AI-driven shell. It reads your prompt, reasons about how to satisfy it, generates a command, and runs that command directly on your operating system. There is no separate “execution proposal” step that a human approves. The reasoning step and the execution step are the same step.
- The User’s Shell is whatever shell the agent inherited when you launched it. On macOS, that’s typically zsh. The agent’s commands run through this shell with the developer’s full user permissions.
~expands to the developer’s home directory because that’s what~means in zsh. - Permission Inheritance is implicit and total. Whatever the developer’s shell can do, the agent can do. There is no separate identity for “the agent acting on the developer’s behalf.” The agent is the developer for as long as the session lasts.
- The
--dangerously-skip-permissionsFlag, which Lanzani’s technical blog post analyzes in detail, is what removes the one safety net that exists by default. Without the flag, Claude Code asks for confirmation before each shell command. With it, the agent runs commands in the background while the developer goes back to other work.
That last point is the one that matters. The flag exists because the default behavior, asking for confirmation on every shell command, makes multi-step tasks tedious. Developers add the flag to make the agent useful. The agent then becomes capable of executing destructive commands without intervention. The flag is named honestly. It is a dangerous flag. But it is also a popular one, because the alternative is approving every ls and cat the agent runs.
The vulnerability happens between steps 2 and 3. The agent reasons about what command to run. The shell executes that command on the host. Nothing sits in between. There is no architectural boundary that says “this command would delete the user’s home directory, refuse to run it.” The shell sees a syntactically valid rm -rf and does what rm -rf does.
Technical Breakdown: How a Trailing Slash Wipes a Mac
Here’s how the incident unfolds, step by step:
Caption: Diagram illustrating how unrestricted AI agent execution can escalate a simple cleanup task into full home-directory destruction
1. The User’s Request
The developer asks Claude Code to clean up packages in an old repository. The prompt is the kind of thing every developer types daily:
Please clean up unused test files, patches, and plan documents from this old repo.
2. The Agent’s Reasoning
The agent identifies three directories that match the request: tests/, patches/, and plan/. It then generates a rm -rf command, because removing directories recursively is the standard way to delete them. So far, this is correct behavior.
3. The Hallucinated Argument
The agent appends ~/ to the command. We don’t know exactly why. Possibly the agent inferred that “clean up” included tidying the home directory. Possibly it generated ~/ as a no-op separator and didn’t realize it was a destructive argument. Possibly its training data included shell snippets where ~/ appears in this position and it pattern-matched. The result either way is the same:
rm -rf tests/ patches/ plan/ ~/
This is a syntactically valid shell command. There is nothing in the syntax that says “this is dangerous.”
4. Shell Expansion
When this command runs in zsh on macOS, the shell expands ~/ to /Users/loveswarkin/. The command becomes, effectively:
rm -rf tests/ patches/ plan/ /Users/loveswarkin/
The shell does not warn. It does not confirm. It does not flag the home directory as protected. There is no system-level check that says “this command would delete a user’s entire home directory.” The shell does what shells do: expand the path and execute.
5. Recursive Force Deletion
rm -rf walks the filesystem under each argument and deletes everything. The Desktop, Documents, Library, Keychain, Application Support folders, Claude Code’s own config and credentials, the user’s SSH keys, the user’s git config, the user’s photos. All of it. In order. Without pausing.
The deletion runs to completion in seconds because most of these files are small, and the SSD’s controller acknowledges deletes nearly instantly. By the time the user notices their terminal is unresponsive and tabs out to check, it’s done.
6. The Aftermath
The keychain is gone, which means every app that authenticates against the keychain is now logged out. Mail, browsers, Slack, GitHub Desktop, every service that stored a token, every saved password. The user’s identity infrastructure on that machine is gone.
Claude Code itself can no longer authenticate, because its own credentials lived in the home directory. The agent that did the destruction can’t even apologize properly, because it can’t connect to its own backend.
The Impact
Within a single command execution, the developer has:
- Lost years of personal and professional files
- Lost cryptographic keys (SSH, GPG) needed to access remote systems
- Lost authentication state for every app on the system
- Lost git history for any uncommitted work
- Inherited a system in a partially-broken state where logging back in and reinstalling apps will take days
There is no recovery path. SSDs with TRIM enabled (which is the default on every modern Mac) zero freed blocks at the controller level, so even forensic recovery tools come up empty. The data is not “deleted” in the sense of “marked unavailable but recoverable.” It is gone.
This is what one trailing slash in one AI-generated command produces.
How Docker Sandboxes Eliminates This Attack Vector
The current AI coding agent ecosystem forces developers into the same dangerous tradeoff that the MCP ecosystem forced on users in Part 1 of our companion series. Every time you run claude --dangerously-skip-permissions or any equivalent flag in another agent, you’re executing arbitrary AI-generated commands directly on your host system with full access to:
- Your entire file system
- Your home directory and everything in it
- Your credentials, keychain, SSH keys, and cloud config
- Every running process and every network connection your shell can make
This is exactly how the rm -rf ~/ incident achieves total system destruction. The agent runs as the developer, on the developer’s filesystem, with no architectural boundary to stop it.
Docker’s Security-First Architecture
Docker Sandboxes represents a fundamental shift in how AI coding agents execute. Rather than running directly on the host with user-level permissions, the agent runs inside a microVM with its own kernel, its own filesystem, and its own network. The agent’s view of ~/ is the workspace mount, not the developer’s actual home directory. The developer’s actual home directory simply does not exist from inside the sandbox.
Docker Sandboxes are managed through the sbx CLI. A quick distinction worth making: Docker Sandboxes are the isolated microVM environments where agents actually run. sbx is the standalone CLI tool used to create, launch, and manage them. Sandboxes are the environments. sbx is what you type to control them.
Docker Sandboxes solves the rm -rf ~/ class of failure by making the destructive command architecturally impossible. The agent can absolutely generate rm -rf tests/ patches/ plan/ ~/. It can absolutely run that command. The command will absolutely succeed. But what gets deleted is the workspace inside the sandbox, not the developer’s actual home directory. The host filesystem isn’t visible from inside the microVM, so there is nothing to delete.
Workspace-Scoped Execution
The most important architectural shift is that the agent’s filesystem view is the workspace mount, and only the workspace mount.
# Install sbx and sign in
brew install docker/tap/sbx
sbx login
# Launch the agent inside a sandbox scoped to the project directory
cd ~/my-project
sbx run claude
Three commands and the agent is now running inside a microVM. From inside the sandbox, the agent’s ~/ IS the workspace, not the developer’s actual home directory. The Library folder, the keychain, the SSH keys, the AWS config – none of that exists inside the sandbox. The agent cannot reach what it cannot see.
A rm -rf ~/ from inside the sandbox deletes the workspace files. The developer can throw the sandbox away with sbx rm and start fresh. The host system is untouched.
Blocked Credential Paths
Even if a developer explicitly mounts additional paths into the sandbox, common credential directories are blocked from being mounted by default:
# Credential roots blocked by default:
# ~/.aws ~/.ssh ~/.docker ~/.gnupg
# ~/.netrc ~/.npm ~/.cargo ~/.config
# A misconfigured mount that tries to include these is rejected
# before the sandbox even starts.
sbx run claude
This blocklist directly addresses the keychain-deletion fallout from the LovesWorkin incident. Even an agent that decides to recursively delete its workspace cannot reach the credentials that keep the developer’s authentication state intact.
Read-Only Mounts for Sensitive Workspaces
For workflows where the agent should read but not write to a directory, the :ro suffix declares a mount as read-only:
# Mount the project workspace as writable, the docs as read-only
sbx run --name docs-review claude /path/to/project /path/to/docs:ro
A rm -rf against a read-only mount fails at the kernel level. The microVM enforces the mount mode, which means the agent cannot decide to override it through reasoning, prompt manipulation, or flag misuse. The infrastructure decides what’s writable. The model doesn’t get a vote.
Git-Worktree Isolation for Risky Operations
For destructive operations like cleanup tasks, refactors, and “let me just clean this up” requests, sbx run --branch lets the agent operate on an isolated Git worktree:
# Create a sandbox on a fresh feature branch
sbx run --name cleanup-agent --branch=cleanup/old-files claude .
# Review what got cleaned up before merging
sbx exec cleanup-agent git diff main
# If the agent did something destructive, throw it away
sbx rm cleanup-agent
This is the architectural answer to “the agent decided to drop and recreate the schema.” The agent’s changes never touch the main branch until the developer reviews them. If the agent runs rm -rf ~/, the worktree gets wiped and the main branch is untouched. The developer reviews git diff main, sees what happened, and decides whether to merge or discard.
Throwaway Sandboxes by Design
The final piece is that sandboxes are designed to be discarded:
# When the work is done, list active sandboxes and remove the one you're done with:
sbx ls
sbx rm <sandbox-name>
This is what makes the Docker Sandboxes model fundamentally different from running an agent on the host. On the host, a destructive command leaves permanent damage. Inside a sandbox, every session is throwaway. The worst the agent can do is destroy the workspace, which is reproducible from the source repo. The keychain, the credentials, the years of personal data, none of those can be touched, because none of those exist from inside the sandbox.
What This Looks Like in Practice
Here’s the LovesWorkin incident replayed under Docker Sandboxes. The user asks the same question. The agent generates the same command. The shell executes the same expansion.
# After Docker Sandboxes:
$ cd ~/my-project
$ sbx run claude
> Please clean up unused test files, patches, and plan documents
[Agent runs: rm -rf tests/ patches/ plan/ ~/]
[Workspace inside the sandbox wiped. Host home directory intact.]
# The sandbox is throwaway. List it and remove it to start fresh:
$ sbx ls
$ sbx rm <sandbox-name>
The agent’s behavior is identical. The architectural outcome is completely different.
The Practical Improvements
|
Security Aspect |
Traditional AI Coding Agent |
Docker Sandboxes |
|---|---|---|
|
Execution Environment |
Direct host execution as the user |
Isolated microVM with its own kernel |
|
Filesystem View |
Full host filesystem, including |
Workspace mount only |
|
Credential Access |
All credentials in user’s home dir |
Credential paths blocked by default |
|
Destructive Command Impact |
Permanent host damage |
Throwaway sandbox |
|
Review Before Merge |
None |
Git worktree isolation with |
|
Recovery |
Often impossible (TRIM zeroes blocks) |
|
Best Practices for Secure AI Coding Agent Deployment
- Stop running coding agents directly on your host. Containerization or microVM isolation should be the default, not an advanced option.
- Use
sbx runfor every coding task that involves filesystem operations. Especially “clean up,” “organize,” “refactor,” and “delete unused” prompts. These are the prompt categories most likely to produce a destructiverm -rf. - Use Git worktrees for destructive operations.
sbx run --name <name> --branch=<branch> claudeensures the agent’s changes are reviewable before they touch your main branch. - Never use
--dangerously-skip-permissionson the host machine. If you need the agent to run commands without per-command approval, run it inside a sandbox. The sandbox boundary is what makes “skip permissions” safe. - Treat the sandbox as throwaway. Don’t store anything important inside it. The whole point is that you can
sbx rmand start fresh. - Audit the policy log.
sbx policy logshows every allowed and denied connection attempt, which becomes your forensics trail if something does go wrong.
Take Action: Secure Your AI Coding Agent Today
The path to safe AI coding agent execution starts with one command. Here’s how to move away from running agents on the host:
- Install Docker Sandboxes. Visit the Docker Sandboxes documentation to install sbx and run your first sandboxed agent in under five minutes.
- Try it with your existing workflow.
sbx run claude(orsbx run cursor,sbx run codex, etc.) drops your existing agent into a microVM with no configuration changes required. - Read the architecture deep-dive. The Docker Sandboxes architecture documentation explains the microVM model, the workspace mounting, and the network policy layer.
- Browse the MCP Catalog. If your agent uses MCP servers, the Docker MCP Catalog provides containerized, verified servers that complement sandboxed agent execution.
Conclusion
The LovesWorkin incident, the Mike Wolak Ubuntu wipe, the Claude Cowork family-photos deletion, and the GitHub issue #12637 shell-glob expansion bug are all the same story. An AI coding agent reasoned its way through a task, generated a command that contained a destructive argument, and the shell executed it because there was nothing in the architecture to say “this command would destroy the developer’s work.”
These aren’t bugs in Claude Code, or Cursor, or Kiro, or any individual agent. They’re properties of the execution model. As long as agents run on the host with the user’s permissions, this category of failure will keep happening, with new variations each time.
Docker Sandboxes doesn’t try to make the agent smarter. It changes where the agent runs. The agent gets a workspace. It does not get your machine.
Coming up in our series: Issue 3 will explore the AWS Cost Explorer outage, where Amazon’s own Kiro agent decided to delete and rebuild a production environment in seconds, and what scoped-identity sandbox configuration prevents that class of failure.
Learn More
- Run agents safely with Docker Sandboxes: Visit the Docker Sandboxes documentation to get started with workspace-isolated agent execution in minutes.
- Explore the Docker MCP Catalog: Discover MCP servers that connect your agents to external services through Docker’s security-first architecture.
- Download Docker Desktop: The fastest path to a governed AI agent environment, with Docker Sandboxes, MCP Gateway, and Model Runner in a single install.
- Read the MCP Horror Stories series: Start with issue 1 to understand the protocol-layer security risks that complement the agent-layer risks covered here.