I have been using Claude Code as my primary coding agent for a couple of months by now. While it has its own sandboxing, I have found this part of the sandbox to always be an absolutely scary thing to read for any program that has unfettered internet access:
Default read behavior: Read access to the entire computer, except certain denied directories
That means CC is allowed by default to look in your ~/.ssh folder, your ~/Documents, ~/Pictures, or hell, why not just vacuum your entire drive for .env files? I did ask it to tell me the content of ~/.ssh folder, and I REALLY did not like the answer I received. It is primed for a simple prompt injection to say the least.
Judging by the threads on Reddit and Hacker News, llms have gone awry plenty of times already and I think it's just a matter of time until a real disaster occurs somewhere it really matters.
I am not waiting around to find out, so I have been running my coding agents in a headless VM for a couple of months now to completely isolate them from accessing anything on my own machine. Not bulletproof, but as good as it comes without hauling around another separate machine.
That said, running VMs is resource intensive, and I've been running short of RAM quite a bit. So here's a middle-of-the-road method that would isolate your CC session using bubblewrap on linux. I came across this article on Hacker News and got interested to try it out for myself.
Put it in your ~/.local/bin folder and instead of running claude, you can run claude-sandbox.sh and you'll be good
to go. It will only see the current folder it's been launched in plus some of the other folders that are required for
claude to run its binaries, but other than that you can ask it to show you what it sees in your ~/Document or ~/.ssh and
you'll be pleased with the results.
#!/bin/bash
# Claude Code Sandbox Script
# Run this from any project directory to launch Claude in a sandboxed environment
PROJECT_DIR="$(pwd)"
CLAUDE_PATH="$(command -v claude)"
CLAUDE_REAL_PATH="$(readlink -f "$CLAUDE_PATH")"
CLAUDE_BIN_DIR="$(dirname "$CLAUDE_PATH")"
CLAUDE_INSTALL_DIR="$(dirname "$(dirname "$CLAUDE_REAL_PATH")")"
# Ensure directories exist
mkdir -p "$HOME/.claude"
mkdir -p "$HOME/.cache/claude-cli-nodejs"
mkdir -p "$HOME/.cache/claude"
mkdir -p "$HOME/.local/state/claude"
BWRAP_ARGS=(
# System binaries and libraries (read-only)
--ro-bind /usr /usr
--ro-bind /lib /lib
--ro-bind /lib64 /lib64
--ro-bind /bin /bin
# System config (read-only)
--ro-bind /etc/resolv.conf /etc/resolv.conf
--ro-bind /etc/hosts /etc/hosts
--ro-bind /etc/ssl /etc/ssl
--ro-bind /etc/passwd /etc/passwd
--ro-bind /etc/group /etc/group
# Claude installation (read-only)
--ro-bind "$CLAUDE_BIN_DIR" "$CLAUDE_BIN_DIR"
--ro-bind "$CLAUDE_INSTALL_DIR" "$CLAUDE_INSTALL_DIR"
# Claude config and state (read-write for auth/settings)
--bind "$HOME/.claude" "$HOME/.claude"
--bind "$HOME/.cache/claude-cli-nodejs" "$HOME/.cache/claude-cli-nodejs"
--bind "$HOME/.cache/claude" "$HOME/.cache/claude"
--bind "$HOME/.local/state/claude" "$HOME/.local/state/claude"
# Project directory (read-write)
--bind "$PROJECT_DIR" "$PROJECT_DIR"
# Temp, proc, dev
--tmpfs /tmp
--proc /proc
--dev /dev
# Namespacing
--share-net
--unshare-pid
--die-with-parent
--chdir "$PROJECT_DIR"
)
# Add ~/.claude.json if it exists
if [[ -f "$HOME/.claude.json" ]]; then
BWRAP_ARGS+=(--bind "$HOME/.claude.json" "$HOME/.claude.json")
fi
# Add .gitconfig if it exists
if [[ -f "$HOME/.gitconfig" ]]; then
BWRAP_ARGS+=(--ro-bind "$HOME/.gitconfig" "$HOME/.gitconfig")
fi
# Add .nvm if it exists (needed for node)
if [[ -d "$HOME/.nvm" ]]; then
BWRAP_ARGS+=(--ro-bind "$HOME/.nvm" "$HOME/.nvm")
fi
# Add Rust toolchain if it exists (needed for cargo)
if [[ -d "$HOME/.cargo" ]]; then
BWRAP_ARGS+=(--ro-bind "$HOME/.cargo" "$HOME/.cargo")
fi
if [[ -d "$HOME/.rustup" ]]; then
BWRAP_ARGS+=(--ro-bind "$HOME/.rustup" "$HOME/.rustup")
fi
# Add SSH known_hosts for host verification (read-only)
if [[ -f "$HOME/.ssh/known_hosts" ]]; then
BWRAP_ARGS+=(--ro-bind "$HOME/.ssh/known_hosts" "$HOME/.ssh/known_hosts")
fi
# OPTIONAL: Uncomment if you need git over SSH (exposes your SSH keys read-only)
# if [[ -d "$HOME/.ssh" ]]; then
# BWRAP_ARGS+=(--ro-bind "$HOME/.ssh" "$HOME/.ssh")
# fi
exec bwrap "${BWRAP_ARGS[@]}" "$CLAUDE_PATH" "$@"
Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.