For genuinely untrusted work — third-party repos, community MCP servers, “let me try this random tool” — run the agent inside a container with no network and no host filesystem.

Minimal Containerfile

Containerfile:

FROM node:22-bookworm-slim
 
RUN apt-get update && apt-get install -y --no-install-recommends \
    git ca-certificates jq curl \
  && rm -rf /var/lib/apt/lists/*
 
# Non-root user
RUN useradd -m -s /bin/bash agent
USER agent
WORKDIR /work
 
# Default to no network, no host mounts at runtime
CMD ["bash"]

Build it once:

podman build -t kiro-sandbox -f Containerfile .
# or: docker build -t kiro-sandbox -f Containerfile .

Running

podman run --rm -it \
  -v "$PWD":/work:Z \
  --network=none \
  --read-only \
  --tmpfs /tmp \
  --tmpfs /home/agent \
  kiro-sandbox

Flag-by-flag:

  • --rm — destroy the container on exit
  • -v "$PWD":/work:Z — mount the current dir; :Z is SELinux relabeling on Fedora-likes (drop on Debian/Ubuntu)
  • --network=none — no network, no exfiltration
  • --read-only — root filesystem is read-only
  • --tmpfs /tmp --tmpfs /home/agent — writable scratch space that disappears on exit

When you do need network

For pulling deps, allow it once, then drop:

# Step 1: install with network, no host mount
podman run --rm -it \
  -v deps-cache:/work/node_modules \
  --network=bridge \
  kiro-sandbox \
  bash -c "cd /work && npm ci --ignore-scripts"
 
# Step 2: run agent with deps pre-installed, no network
podman run --rm -it \
  -v "$PWD":/work:Z \
  -v deps-cache:/work/node_modules:ro \
  --network=none \
  kiro-sandbox

Cost / benefit

This workflow is painful. Use it for:

  • Auditing a third-party repo before merging
  • Running a community MCP server you haven’t read end-to-end
  • Reproducing a reported vulnerability
  • Demoing this talk

Don’t use it for:

  • Daily work in your own trusted repo (use hooks + [[community/demo/20260427 - Secure Practices in Agentic IDEs/defenses/kiroignore|.kiroignore]])

What sandboxing doesn’t cover

  • Prompts you paste into the agent — secrets still go to the model provider
  • Steering / spec leakage if you mount them in
  • Time-bombed payloads that wait for the next session

Counters which threats

  • Supply chain — postinstall can’t reach the network, can’t touch host
  • MCP poisoning — server can’t read host filesystem, can’t exfiltrate
  • Untrusted execution — rm -rf / only kills the container