What If Your AI Coding Agent Deletes Your Project? Building a Zero-Trust Sandbox with Rust
AI coding agents are becoming an important part of modern software development.
Tools like Claude Code, OpenAI Codex, Aider, OpenHands, Cursor, and other autonomous coding agents can execute terminal commands, modify source files, install dependencies, and run scripts.
But there is one important question:
What happens when an AI agent executes a dangerous command on your actual development machine?
Imagine an agent accidentally:
- Deletes important project files.
- Overwrites your
.envconfiguration. - Reads SSH keys or cloud credentials.
- Modifies Git history.
- Executes an untrusted installation script.
- Makes unexpected outbound network connections.
A simple confirmation prompt isn't always enough.
I started building ShadowCLI to explore a different approach: putting a zero-trust security boundary between AI coding agents and the developer's machine.
Introducing ShadowCLI
GitHub: https://github.com/6t9xstar/shadowcli
ShadowCLI is an open-source, Rust-based execution sandbox for AI coding agents.
Instead of allowing commands to modify your actual project immediately, ShadowCLI executes them inside an isolated Linux environment.
Changes are captured in a temporary copy-on-write layer. Developers can inspect the resulting differences, review modifications, approve changes, or discard the session.
The goal is simple:
Let AI agents work, but keep developers in control of what reaches their actual projects.
How Does It Work?
ShadowCLI uses multiple Linux security mechanisms to isolate command execution.
Its architecture combines:
- Linux User Namespaces – Isolate user and group identities.
- Mount Namespaces – Provide a private filesystem view.
- PID Namespaces – Isolate processes.
- Network Namespaces – Restrict outbound network access by default.
- Landlock LSM – Enforce filesystem access restrictions.
- Seccomp BPF – Block selected high-risk system calls.
- OverlayFS / CopyFS – Capture filesystem modifications without directly changing the host project during execution.
These layers work together to create a defense-in-depth execution environment.
Getting Started
ShadowCLI is designed for Linux systems with the required kernel and sandbox capabilities.
1. Clone the repository
git clone https://github.com/6t9xstar/shadowcli.git
cd shadowcli
2. Build the project
You need Rust 1.80 or later.
cargo build --release
3. Install the binary
sudo cp target/release/shadow /usr/local/bin/
4. Check system compatibility
shadow doctor
This checks important system capabilities, including kernel compatibility, user namespaces, Landlock, Seccomp, and filesystem support.
5. Run a command inside the sandbox
shadow run -- npm test
By default, outbound network access is blocked.
If a task requires network access, you can explicitly allow it:
shadow run --allow-network -- cargo build
You can also configure execution timeouts:
shadow run --timeout 30 -- ./agent-script.sh
Inspect Changes Before Applying Them
One of the most important parts of ShadowCLI is its review workflow.
After an agent executes commands, inspect the captured changes:
shadow diff
View a summary:
shadow diff --stat
Review modifications interactively:
shadow review
Apply approved changes:
shadow apply --all --yes
If you need to undo the most recent apply operation:
shadow apply --rollback
Or discard unapplied sandbox changes:
shadow discard
This creates a workflow where executing commands and accepting their modifications are separate decisions.
Who Can Use ShadowCLI?
ShadowCLI is designed as a general execution boundary for tools that execute terminal commands.
Potential integration targets include:
- Claude Code
- OpenAI Codex
- Aider
- OpenHands
- Gemini CLI
- OpenCode
- Cline
- Roo Code
- Custom AI coding agents
For example, you can wrap a terminal-based agent command:
shadow run -- aider
You can also integrate sandboxed command execution into your own Python-based agent:
import subprocess
result = subprocess.run(
[
"shadow",
"run",
"--project",
".",
"--allow-network",
"--",
"npm",
"test"
],
capture_output=True,
text=True
)
print(result.stdout)
print(result.stderr)
Actual compatibility depends on how an agent interacts with the filesystem and launches subprocesses.
Security Is More Than a Confirmation Prompt
I believe AI-assisted development needs more than a simple permission dialog.
A secure execution workflow should consider:
- Filesystem isolation.
- Credential protection.
- Network restrictions.
- Process isolation.
- System call restrictions.
- Change inspection.
- Explicit approval.
- Recovery and rollback.
ShadowCLI brings these ideas together using native Linux security technologies and Rust.
It is not a replacement for security auditing, backups, or a hardened virtual machine. Its protection also depends on the host kernel, filesystem, configuration, and the correctness of its isolation mechanisms.
Open Source and Contributions
ShadowCLI is released under the Apache-2.0 license.
I'm continuing development and would appreciate feedback from developers working with:
- Rust and Linux systems programming.
- AI coding agents.
- Linux kernel security.
- Sandboxing and container isolation.
- DevSecOps and application security.
If you're interested in this area, explore the repository, review the implementation, report issues, or contribute improvements.
GitHub Repository: https://github.com/6t9xstar/shadowcli
I'd particularly like to hear your thoughts:
Would you trust an AI coding agent with unrestricted access to your development machine, or would you prefer every modification to go through an isolated execution and review process?
Let's discuss.
Top comments (12)
Clone and cargo build are not enough on Debian or Ubuntu. Unprivileged user namespaces stay off by default there, a sysctl on Debian and an AppArmor switch on Ubuntu 24.04, so the namespace stack in the post never starts. shadow doctor is the check that shows it.
Thanks everyone — these are exactly the kinds of real-world edge cases I want ShadowCLI to be tested against.
The namespace setup requirements need clearer distro-specific documentation;
shadow doctoris the starting point, but the install guidance should do more to explain host prerequisites.The current staging/review model covers filesystem changes made by commands routed through ShadowCLI. It does not capture or roll back external side effects from desktop-control tools, logged-in browsers, or other MCP servers. Those need separate account isolation and action-approval controls.
And the package-cache, OverlayFS, and Git-index points are excellent performance and compatibility items. I’m adding them to the investigation list rather than assuming the current behavior is optimal.
Appreciate the thoughtful feedback — this is how the project gets more robust.
Running agent shell commands as an unprivileged user is the cheapest containment there is. The part most people miss is the filesystem: a sandbox that can read the home directory leaks secrets even when the process cannot write anything. Mounting only the workspace and dropping capabilities closes most of the gap.
Absolutely. Least privilege is a great starting point—but filesystem visibility is just as important as write access. A process that can read
~/.ssh, cloud credentials, or.envfiles can still expose secrets even if it can’t modify them.That’s why ShadowCLI focuses on staging workspace changes while restricting the filesystem view and applying kernel-level controls to commands explicitly routed through it. The boundary matters: anything executed outside that path isn’t automatically contained.
The separation between command execution and applying changes is what makes this approach particularly interesting. Sandboxing limits what an agent can access, while the review stage gives developers control over what actually reaches the project. One area worth considering is how to handle actions outside the filesystem, such as API calls, browser automation, or MCP tools, since those side effects cannot always be captured or rolled back through a file diff. A layered approach combining OS-level isolation with tool-level permissions could make agent execution much safer.
Agreed—that’s an important next layer. ShadowCLI currently focuses on filesystem and process boundaries for commands explicitly routed through its sandbox; browser, API, and third-party MCP side effects aren’t automatically captured by a file diff or rolled back.
Combining OS-level isolation with narrowly scoped tool permissions is the right direction. The goal is to make the boundary explicit, limit what each tool can do, and keep consequential actions under developer control.
Does the staging layer also cover tools that never touch the shell, like an MCP server that clicks around a desktop or a logged-in browser? A sent email or a submitted form can't be diffed and rolled back like a file.
For screen-control agents (Auten team here, that's what we build) the closest thing we've found is a separate desktop user holding only the accounts the task needs, plus keeping the client's approval prompt on for send, buy and delete.
Thanks everyone — these are exactly the kinds of real-world edge cases I want ShadowCLI to be tested against.
The namespace setup requirements need clearer distro-specific documentation;
shadow doctoris the starting point, but the install guidance should do more to explain host prerequisites.The current staging/review model covers filesystem changes made by commands routed through ShadowCLI. It does not capture or roll back external side effects from desktop-control tools, logged-in browsers, or other MCP servers. Those need separate account isolation and action-approval controls.
And the package-cache, OverlayFS, and Git-index points are excellent performance and compatibility items. I’m adding them to the investigation list rather than assuming the current behavior is optimal.
Appreciate the thoughtful feedback — this is how the project gets more robust.
This maps almost exactly onto the Electron security model — the renderer is the untrusted agent and the main process is the naked bash shell: if you expose ipcRenderer directly, the renderer can ask for anything, and a prompt-based confirmation is no real boundary. The fix is the same one: a contextBridge that exposes only a whitelisted surface, validates every argument, and refuses commands outside the declared permission set. The zero-trust framing is useful here too — assume the untrusted side will exploit whatever you leak, and keep the dangerous primitives (fs, child_process, shell) behind main-process validation rather than trusting the caller.
That’s a strong analogy. A narrow, validated interface is much safer than exposing powerful primitives and relying on prompts for approval.
ShadowCLI applies a similar principle to commands routed through its sandbox: stage workspace changes, restrict access where supported, and keep apply under developer control. The important caveat is that it doesn’t intercept every agent action—native editor tools and external integrations can still operate outside that boundary.
Beyond the unprivileged namespace sysctl, the piece that usually catches people with OverlayFS and coding agents is package caching.
If the agent runs cargo build or npm install inside the scratch layer, the upper directory ends up capturing hundreds of megabytes of downloaded crates and node_modules alongside the actual code diff. Unless you explicitly bind-mount the host global cache read-only into ~/.cargo and ~/.cache, the sandbox re-downloads the world on every attempt, and walking thousands of tiny files across the overlay copy-on-write layer kills disk latency.
The other quirk to watch is git index writes. Some tools rely on hardlinks or atomic renames within the working tree, which can trigger cross-device link errors across overlayfs layers unless the mount specifically enables index and metacopy options.
Thanks everyone — these are exactly the kinds of real-world edge cases I want ShadowCLI to be tested against.
The namespace setup requirements need clearer distro-specific documentation;
shadow doctoris the starting point, but the install guidance should do more to explain host prerequisites.The current staging/review model covers filesystem changes made by commands routed through ShadowCLI. It does not capture or roll back external side effects from desktop-control tools, logged-in browsers, or other MCP servers. Those need separate account isolation and action-approval controls.
And the package-cache, OverlayFS, and Git-index points are excellent performance and compatibility items. I’m adding them to the investigation list rather than assuming the current behavior is optimal.
Appreciate the thoughtful feedback — this is how the project gets more robust.