opencode icon indicating copy to clipboard operation
opencode copied to clipboard

Is there a way to sandbox the agent ?

Open edmBernard opened this issue 4 months ago • 10 comments

Hi,

Is there a way to restrict terminal command from a agent to access/edit file outside the current directory ? I see that gemini-cli or codex-cli use seatbelt on macOS. I don't see any equivalent for copencode.

Thanks,

edmBernard avatar Aug 25 '25 15:08 edmBernard

This issue might be a duplicate of existing issues. Please check:

  • #2206: This is a comprehensive feature request for adding sandboxing capabilities to OpenCode, addressing the same core concern about restricting agent access to files and system commands outside the current directory. It discusses security risks with the current bash tool and proposes solutions including sandboxing mechanisms similar to what you're asking about.

Feel free to ignore if none of these address your specific case.

github-actions[bot] avatar Aug 25 '25 15:08 github-actions[bot]

yeah we need better sandboxing, we try to restrict to cwd but agent can use bash to get around it

rekram1-node avatar Aug 25 '25 15:08 rekram1-node

Could Anthropic's new sandboxing runtime be used for this? https://github.com/anthropic-experimental/sandbox-runtime

TyceHerrman avatar Oct 25 '25 13:10 TyceHerrman

Oo thats a good callout we will need to look into that, I wonder how easy it is to hookup

rekram1-node avatar Oct 25 '25 21:10 rekram1-node

I currently mitigate this by running opencode inside a docker container, with bind mounts of just the folders I want it to access (or which it needs); can also restrict network activity too if desired this way. Its a bit fiddly and of course container escape is possible, but better than nothing.

gimbo avatar Oct 25 '25 23:10 gimbo

Docker containers are a good start, but when coding on Mac, you loose native tools, and docker (by itself) does not sandbox network requests, which means secret exfiltration is not mitigated at all. I very much second the attention to the anthropics sandbox-runtime.

dwt avatar Dec 02 '25 08:12 dwt

I started off with docker as well, but as mentioned there's a lot of obstacles, incl. the auto-copy on selection in OpenCode being a big problem.

I've spent some time on the macOs sandbox-exec, which is the underlying tool anthropic's srt is using. The issue I had with srt is that I would need to build a deny list for reading permissions instead of an allowlist, and therefore used the macOs tool straight away.

https://gist.github.com/robbash/84aaa7c4133535b59cbaf0c1761031a4

I don't have a lot of experience with the tool though, and there was a lot of trial and error involved. Happy about feedback.

robbash avatar Dec 02 '25 10:12 robbash

Thanks for sharing! For those here not using macos and ready to test this (had no time to do so yet), here is what the bot says:

To create a similar sandbox on Debian GNU/Linux & Co. without Docker/Podman, you can use bubblewrap (bwrap), which is Linux's equivalent to macOS's sandbox-exec. Bubblewrap provides lightweight containerization with namespace isolation.

Installation

sudo apt install bubblewrap

Sandbox Script

Here's a bubblewrap-based sandbox configuration equivalent to your macOS setup:

#!/bin/bash
# Save as ~/opencode-sandbox.sh and chmod +x it

# Define your workspace directories
WORKSPACES=(
    "$HOME/Development/docker"
    "$HOME/Development/dotnet"
    "$HOME/Development/node"
)

# Build workspace bind mounts
WORKSPACE_BINDS=()
for ws in "${WORKSPACES[@]}"; do
    if [ -d "$ws" ]; then
        WORKSPACE_BINDS+=(--bind "$ws" "$ws")
    fi
done

# Execute OpenCode in sandbox
bwrap \
    --unshare-all \
    --share-net \
    --die-with-parent \
    --new-session \
    \
    `# Basic filesystem structure` \
    --ro-bind /usr /usr \
    --ro-bind /lib /lib \
    --ro-bind /lib64 /lib64 \
    --ro-bind /bin /bin \
    --ro-bind /sbin /sbin \
    --symlink usr/lib /lib \
    --symlink usr/lib64 /lib64 \
    --symlink usr/bin /bin \
    --symlink usr/sbin /sbin \
    --proc /proc \
    --dev /dev \
    --tmpfs /tmp \
    --tmpfs /run \
    \
    `# Minimal /etc files needed` \
    --ro-bind /etc/resolv.conf /etc/resolv.conf \
    --ro-bind /etc/hosts /etc/hosts \
    --ro-bind /etc/nsswitch.conf /etc/nsswitch.conf \
    --ro-bind /etc/passwd /etc/passwd \
    --ro-bind /etc/group /etc/group \
    --ro-bind /etc/localtime /etc/localtime \
    \
    `# SSL certificates for API access` \
    --ro-bind /etc/ssl /etc/ssl \
    --ro-bind-try /etc/ca-certificates /etc/ca-certificates \
    \
    `# Home directory structure` \
    --dir "$HOME" \
    --setenv HOME "$HOME" \
    --chdir "$HOME" \
    \
    `# OpenCode config and cache directories (read-write)` \
    --bind-try "$HOME/.cache/opencode" "$HOME/.cache/opencode" \
    --bind-try "$HOME/.local/share/opencode" "$HOME/.local/share/opencode" \
    --bind-try "$HOME/.local/state/opencode" "$HOME/.local/state/opencode" \
    --bind-try "$HOME/.config/opencode" "$HOME/.config/opencode" \
    \
    `# Workspace directories (read-write)` \
    "${WORKSPACE_BINDS[@]}" \
    \
    `# Terminal and environment` \
    --setenv TMPDIR /tmp \
    --setenv PATH /usr/local/bin:/usr/bin:/bin \
    \
    `# Run OpenCode` \
    opencode "$@"

Usage

# Make executable
chmod +x ~/opencode-sandbox.sh

# Create config directories if they don't exist
mkdir -p ~/.cache/opencode ~/.local/share/opencode \
         ~/.local/state/opencode ~/.config/opencode

# Run OpenCode in sandbox
~/opencode-sandbox.sh

Key Differences from macOS Version

  1. Network isolation: Uses --share-net to allow network access (similar to allow network* in macOS)
  2. Filesystem: Read-only binds for system directories, read-write for workspaces
  3. No full HOME access: Only specific OpenCode directories are accessible
  4. Process isolation: --unshare-all creates new namespaces (PID, mount, IPC, UTS, cgroup)

Alternative: More Restrictive Network Control

If you want to limit network access (e.g., only API calls), you could combine bubblewrap with iptables or nftables rules, though this requires root privileges and is more complex.

Debugging

To troubleshoot, run with verbose output:

strace -f ~/opencode-sandbox.sh 2>&1 | grep -i "denied\|error"

This setup provides isolation comparable to Claude Code CLI's sandbox while remaining lightweight and avoiding full container solutions.

redtux avatar Dec 03 '25 02:12 redtux

Bubblewrap is the other backend that sandbox-runtime is using. For sure you can deal with all those options, but I think it makes a lot of sense to use something like sandbox-runtime to keep that much simpler to use. Plus, you get the network sandboxing with a man in the middle proxy for which you can also specify rules.

dwt avatar Dec 06 '25 11:12 dwt

I ended up writing this simple tool: https://github.com/frequenz-floss/contai

It is still super simple, and far from user-friendly or finished, but it fulfills my needs for some sense of security while running AI agents, so maybe somebody else also find it useful.

llucax avatar Dec 11 '25 12:12 llucax