DEV Community

Malik Taimoor Awan
Malik Taimoor Awan

Posted on

Why You Shouldn't Let AI Agents Run Naked Bash: Building an Unprivileged Sandbox in Rust

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 .env configuration.
  • 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:

  1. Linux User Namespaces – Isolate user and group identities.
  2. Mount Namespaces – Provide a private filesystem view.
  3. PID Namespaces – Isolate processes.
  4. Network Namespaces – Restrict outbound network access by default.
  5. Landlock LSM – Enforce filesystem access restrictions.
  6. Seccomp BPF – Block selected high-risk system calls.
  7. 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
Enter fullscreen mode Exit fullscreen mode

2. Build the project

You need Rust 1.80 or later.

cargo build --release
Enter fullscreen mode Exit fullscreen mode

3. Install the binary

sudo cp target/release/shadow /usr/local/bin/
Enter fullscreen mode Exit fullscreen mode

4. Check system compatibility

shadow doctor
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

By default, outbound network access is blocked.

If a task requires network access, you can explicitly allow it:

shadow run --allow-network -- cargo build
Enter fullscreen mode Exit fullscreen mode

You can also configure execution timeouts:

shadow run --timeout 30 -- ./agent-script.sh
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

View a summary:

shadow diff --stat
Enter fullscreen mode Exit fullscreen mode

Review modifications interactively:

shadow review
Enter fullscreen mode Exit fullscreen mode

Apply approved changes:

shadow apply --all --yes
Enter fullscreen mode Exit fullscreen mode

If you need to undo the most recent apply operation:

shadow apply --rollback
Enter fullscreen mode Exit fullscreen mode

Or discard unapplied sandbox changes:

shadow discard
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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 (10)

Collapse
 
florian131313 profile image
G •

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.

Collapse
 
6t9 profile image
Malik Taimoor Awan •

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 doctor is 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.

Collapse
 
analista_83 profile image
Sammi De Blas •

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.

Collapse
 
6t9 profile image
Malik Taimoor Awan •

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 .env files 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.

Collapse
 
autenai profile image
Auten •

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.

Collapse
 
6t9 profile image
Malik Taimoor Awan •

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 doctor is 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.

Collapse
 
mp3sss31 profile image
mp3sss •

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.

Collapse
 
6t9 profile image
Malik Taimoor Awan •

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.

Collapse
 
reidmarlow profile image
Reid Marlow •

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.

Collapse
 
6t9 profile image
Malik Taimoor Awan •

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 doctor is 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.