Sandbox-Here is a convenience script around bubblewrap to sandbox agents and similar semi-trusted processes
Python
8
10 commits
updated Aug 17, 2026
Run a command so it can only see the current directory and its own config files. Everything else in your home directory is either read-only or hidden completely.
It's a Python script that builds a bubblewrap container and drops your command inside.
AI coding agents run LLM-generated shell commands on your machine. A
command can read SSH keys, scrape shell history, exfiltrate ~/Documents,
modify git config, or leak internal hostnames — even after you approved it.
sandbox-here blocks all of that. The command sees the project directory
and its own config. Nothing else.
It's not a jail for untrusted code. A determined attacker will get out.
User namespaces are a hardening tool, not a security boundary. With
--net, the command can make arbitrary outbound connections. There's no
seccomp filter unless you add one, no resource limits, and writes to the
app's own config directory persist on disk.
Think of it like locking your car. Stops casual snooping and mistakes. Won't stop someone with a brick. For running code you don't trust, use a VM or a separate machine.
mkdir -p ~/.config/sandbox-here
cp sandbox-here ~/.config/sandbox-here/
chmod +x ~/.config/sandbox-here/sandbox-here
Needs bubblewrap 0.11+ and Python 3.10+. That's it.
Then alias it in your shell:
alias sbh="$HOME/.config/sandbox-here/sandbox-here"
(sbh is what I use day-to-day. The full name works too.)
# Show usage and options
sbh --help
# Open a shell sandboxed to the current directory
sbh
# Run a command
sbh npm install
sbh make
sbh cargo build
# Allow network — for package managers or curl
sbh --net pip install requests
# Mount container runtime sockets
sbh --docker docker build .
sbh --podman podman run ...
sbh --docker --net docker pull alpine
# Mount extra files/dirs
# Shortcut: mount SRC read-write at its own path (relative paths OK)
sbh --add ../test-dir
# Full form: mode + SRC + DST (for remapping)
sbh --add ro /usr/share/dict/words /usr/share/dict/words
sbh --add rw /tmp/scratch /tmp/scratch
sbh --add ro /some/config.json /etc/myapp/config.json
When you run sbh npm, the script detects npm and mounts ~/.npm/
read-write. sbh cargo gets ~/.cargo/, sbh git gets ~/.gitconfig.
sbh with no command opens your shell and makes the shell's own configs
writable.
Symlinks are followed. If /usr/bin/sh points to bash, running sbh sh
grants write access to ~/.bashrc and ~/.config/bash/.
Sensitive paths are invisible — not even mounted read-only:
.ssh .gnupg .codex .pki .docker .mozilla .thunderbird .librewolf
.aws .azure .gcloud .gsutil .copilot .electrum .tor .gnome .kde4
Environment variables are wiped clean. Only a short safelist gets
re-injected (PATH, HOME, TERM, LANG, a few toolchain vars).
DEEPSEEK_API_KEY, SSH_AUTH_SOCK, SSLKEYLOGFILE, DISPLAY,
DBUS_SESSION_BUS_ADDRESS — all stripped. If you need to pass something
through, prefix it with SANDBOX_.
/etc/hosts is overlaid with a minimal file so your LAN machines,
Tailnet nodes, and other internal hostnames don't leak.
Network is off by default. --net turns it on.
Container sockets (--docker, --podman, --containerd) are not
mounted by default. Pass the flag to bind-mount the socket into the
sandbox so docker, podman, or ctr work inside. --docker
respects DOCKER_HOST when set to a unix:// path; TCP daemons need
--net instead (no local socket to mount).
Use --add to mount arbitrary paths. --add SRC mounts the path
read-write at its own location — relative paths resolve against the
current directory, so sbh --add ../test-dir works from anywhere.
The full form --add ro|rw SRC DST mounts SRC at DST instead, for
remapping (e.g. a config file into /etc). ro gives read-only
access, rw gives read-write. Repeat --add for multiple paths.
Both SRC and DST are required in the full form — if you want the same
path at the same mount point, specify it twice.
Any dotfile not on the blocklist is visible read-only — .bashrc,
.gitconfig, .vimrc. If you stash secrets in those, they're visible.
With --net, the command has the same network access you do. It can hit
localhost services, scan your LAN, make outbound connections.
The app's own config directory is writable and persists to disk. If you
run sbh pi, the agent's config at ~/.pi/ survives sandbox teardown.
A compromised agent can modify its own settings to persist across
restarts.
/etc/passwd, /proc/cpuinfo, and other world-readable system files are
visible. No attempt is made to hide them.
Optional. Drop a seccomp.bpf next to the script and it gets loaded.
bubblewrap's repo has example policies. Without one, no syscall filtering
happens.
~/.config/sandbox-here/
├── sandbox-here the script
├── seccomp.bpf optional syscall filter
├── README.md this file
└── AGENTS.md reference for AI agents running inside the sandbox
Do whatever you want. It's a few hundred lines of Python that wraps bubblewrap. Don't care.
65 followers · starred Jul 2026
Python
100.0%
Sandbox-Here is a convenience script around bubblewrap to sandbox agents and similar semi-trusted processes
Python
8
10 commits
updated Aug 17, 2026
Run a command so it can only see the current directory and its own config files. Everything else in your home directory is either read-only or hidden completely.
It's a Python script that builds a bubblewrap container and drops your command inside.
AI coding agents run LLM-generated shell commands on your machine. A
command can read SSH keys, scrape shell history, exfiltrate ~/Documents,
modify git config, or leak internal hostnames — even after you approved it.
sandbox-here blocks all of that. The command sees the project directory
and its own config. Nothing else.
It's not a jail for untrusted code. A determined attacker will get out.
User namespaces are a hardening tool, not a security boundary. With
--net, the command can make arbitrary outbound connections. There's no
seccomp filter unless you add one, no resource limits, and writes to the
app's own config directory persist on disk.
Think of it like locking your car. Stops casual snooping and mistakes. Won't stop someone with a brick. For running code you don't trust, use a VM or a separate machine.
mkdir -p ~/.config/sandbox-here
cp sandbox-here ~/.config/sandbox-here/
chmod +x ~/.config/sandbox-here/sandbox-here
Needs bubblewrap 0.11+ and Python 3.10+. That's it.
Then alias it in your shell:
alias sbh="$HOME/.config/sandbox-here/sandbox-here"
(sbh is what I use day-to-day. The full name works too.)
# Show usage and options
sbh --help
# Open a shell sandboxed to the current directory
sbh
# Run a command
sbh npm install
sbh make
sbh cargo build
# Allow network — for package managers or curl
sbh --net pip install requests
# Mount container runtime sockets
sbh --docker docker build .
sbh --podman podman run ...
sbh --docker --net docker pull alpine
# Mount extra files/dirs
# Shortcut: mount SRC read-write at its own path (relative paths OK)
sbh --add ../test-dir
# Full form: mode + SRC + DST (for remapping)
sbh --add ro /usr/share/dict/words /usr/share/dict/words
sbh --add rw /tmp/scratch /tmp/scratch
sbh --add ro /some/config.json /etc/myapp/config.json
When you run sbh npm, the script detects npm and mounts ~/.npm/
read-write. sbh cargo gets ~/.cargo/, sbh git gets ~/.gitconfig.
sbh with no command opens your shell and makes the shell's own configs
writable.
Symlinks are followed. If /usr/bin/sh points to bash, running sbh sh
grants write access to ~/.bashrc and ~/.config/bash/.
Sensitive paths are invisible — not even mounted read-only:
.ssh .gnupg .codex .pki .docker .mozilla .thunderbird .librewolf
.aws .azure .gcloud .gsutil .copilot .electrum .tor .gnome .kde4
Environment variables are wiped clean. Only a short safelist gets
re-injected (PATH, HOME, TERM, LANG, a few toolchain vars).
DEEPSEEK_API_KEY, SSH_AUTH_SOCK, SSLKEYLOGFILE, DISPLAY,
DBUS_SESSION_BUS_ADDRESS — all stripped. If you need to pass something
through, prefix it with SANDBOX_.
/etc/hosts is overlaid with a minimal file so your LAN machines,
Tailnet nodes, and other internal hostnames don't leak.
Network is off by default. --net turns it on.
Container sockets (--docker, --podman, --containerd) are not
mounted by default. Pass the flag to bind-mount the socket into the
sandbox so docker, podman, or ctr work inside. --docker
respects DOCKER_HOST when set to a unix:// path; TCP daemons need
--net instead (no local socket to mount).
Use --add to mount arbitrary paths. --add SRC mounts the path
read-write at its own location — relative paths resolve against the
current directory, so sbh --add ../test-dir works from anywhere.
The full form --add ro|rw SRC DST mounts SRC at DST instead, for
remapping (e.g. a config file into /etc). ro gives read-only
access, rw gives read-write. Repeat --add for multiple paths.
Both SRC and DST are required in the full form — if you want the same
path at the same mount point, specify it twice.
Any dotfile not on the blocklist is visible read-only — .bashrc,
.gitconfig, .vimrc. If you stash secrets in those, they're visible.
With --net, the command has the same network access you do. It can hit
localhost services, scan your LAN, make outbound connections.
The app's own config directory is writable and persists to disk. If you
run sbh pi, the agent's config at ~/.pi/ survives sandbox teardown.
A compromised agent can modify its own settings to persist across
restarts.
/etc/passwd, /proc/cpuinfo, and other world-readable system files are
visible. No attempt is made to hide them.
Optional. Drop a seccomp.bpf next to the script and it gets loaded.
bubblewrap's repo has example policies. Without one, no syscall filtering
happens.
~/.config/sandbox-here/
├── sandbox-here the script
├── seccomp.bpf optional syscall filter
├── README.md this file
└── AGENTS.md reference for AI agents running inside the sandbox
Do whatever you want. It's a few hundred lines of Python that wraps bubblewrap. Don't care.
65 followers · starred Jul 2026
Python
100.0%