Securing Local Agents: Sandboxing Gemini 3 Tool Execution for Enterprise Safety
A developer laptop holds years of credentials. Learn how to sandbox local Gemini 3 agent tool execution with hardened containers, gVisor, and microVMs.
Published on • August 1, 2026
AI Assistant

A typical developer laptop contains years of accumulated credentials: AWS or Google Cloud keys, kubeconfig files, Docker registry credentials, GitHub personal access tokens, SSH private keys, Terraform state files, local .env files, and database connection strings.
When you run a local Gemini 3 agent with shell, filesystem, and network access, that agent can read all of it. And a single prompt injection — embedded in a web page, a PDF, or an email the agent reads — can turn that access against you. The HiddenLayer 2026 AI Threat Landscape Report found that 1 in 8 AI security breaches now involves an agentic system.
In this tutorial, you will learn the threat model for local agents, why Docker alone is not a security boundary, and how to build a properly isolated sandbox for Gemini 3 tool execution.
The Threat Model: What’s on a Developer Laptop
The relevant question is not “what can an attacker send to the model?” but “what can the model do to my infrastructure when instructed to do something unexpected?”
Local agents execute shell commands, call APIs, read and write filesystems, and spawn subprocesses — all without a human approving every step. The secrets on your machine become the agent’s blast radius.
flowchart LR
A["Gemini 3 Agent"]
B["Shell / Subprocess"]
C["~/.aws credentials"]
D["kubeconfig"]
E[".env files"]
F["SSH keys"]
A --> B
B --> C
B --> D
B --> E
B --> F
classDef agent fill:#e0f2fe,stroke:#0284c7,color:#0f172a;
classDef secret fill:#fee2e2,stroke:#dc2626,color:#0f172a;
class A agent;
class B,C,D,E,F secret;
Why Docker Alone Is Not Enough
Standard containers share the host kernel with every other container. A kernel vulnerability or misconfiguration can allow a container escape, giving the attacker access to the host and all other containers.
Real-world CVEs prove the point:
- Flowise CustomMCP RCE: User-provided configuration strings were executed as arbitrary JavaScript with
child_processandfsaccess. 12,000+ internet-facing instances were exposed. Root cause: a missing execution sandbox. - Google Antigravity sandbox escape: A tool passed an unvalidated
Patternparameter to the underlyingfdbinary, achieving arbitrary code execution that bypassed the IDE’s highest security configuration. - CVE-2025-59536 (Claude Code): Configuration injection through the Hooks feature, plus a companion flaw allowing API key theft via a redirected proxy.
The lesson: application-level security controls cannot govern subprocesses once execution transfers to a native binary. Kernel-level isolation, applied at the process boundary, is required.
Isolation Tiers Compared
| Tier | Technology | Isolation level | Best for |
|---|---|---|---|
| Hardened container | Docker with seccomp, no-new-privileges, read-only rootfs | Process (shared kernel) | Low-risk, internal-only tools |
| User-space kernel | gVisor | Syscall-level | Compute-heavy multi-tenant workloads |
| MicroVM | Firecracker, Kata Containers | Kernel-level | Regulated data, strongest isolation |
OWASP’s Agentic AI Top 10 (December 2025) classifies ASI05 (Unexpected Code Execution) as a top-tier risk and states: “Never execute agent-generated code without strict sandboxing, input validation, and allowlisting.” It is a control, not a recommendation.
Microsoft’s Agent Governance Toolkit and NVIDIA’s sandboxing guidance converge on four mandatory layers: network egress, filesystem boundaries, secrets scoping, and configuration file protection.
Building a Hardened Local Sandbox
Here is a Docker image that applies the four mandatory layers for local agent tool execution.
# syntax=docker/dockerfile:1
FROM alpine:3.21
# 1. Run as non-root with no extra privileges
RUN adduser -D -u 10001 agent
USER agent
# 2. Read-only rootfs, no shell for the agent itself
WORKDIR /work
# 3. Drop capabilities and deny privilege escalation
ENTRYPOINT ["/bin/sh", "-c"]
Run the agent tool execution with strict runtime constraints:
docker run --rm \
--name gemini-agent-tool \
--network none \
--read-only \
--tmpfs /tmp:size=64m \
--cap-drop ALL \
--security-opt no-new-privileges \
--security-opt seccomp=agent-seccomp.json \
--memory 512m --cpus 1 \
-v "$PWD/workspace:/work:rw" \
sandboxed-agent-tools
Key flags explained:
--network none— network egress control. The agent can’t exfiltrate data or reach attacker infrastructure.--read-only— filesystem boundary. The root filesystem is immutable; only/tmpand the mounted workspace are writable.--cap-drop ALL+--security-opt no-new-privileges— the process can never escalate privileges.--security-opt seccomp=...— restrict the system calls the sandbox may make.
Scoping Secrets: Only Mount What the Task Needs
Never mount ~/.ssh or ~/.aws wholesale. Inject only the specific credentials a task requires, scoped to the least privilege:
# BAD: the agent can read every credential on your machine
# -v "$HOME/.aws:/home/agent/.aws:ro"
# -v "$HOME/.ssh:/home/agent/.ssh:ro"
# GOOD: a single read-only token scoped to one operation
env AWS_ACCESS_KEY_ID="$(echo "$SECRET" | jq -r .access_key)" \
AWS_SECRET_ACCESS_KEY="$(echo "$SECRET" | jq -r .secret_key)" \
docker run --rm --network none sandboxed-agent-tools \
aws s3 cp s3://bucket/object - --region us-east-1
Integrating the Sandbox with Gemini 3 Agents
Wire the sandbox into your agent’s tool layer. Instead of executing tools directly on the host, route them through a sandboxed subprocess boundary:
import subprocess
import tempfile
from pathlib import Path
IMAGE = "sandboxed-agent-tools"
def run_sandboxed_tool(command: str, workspace: str, env: dict | None = None) -> str:
"""Execute an agent tool inside an isolated, networkless container."""
with tempfile.TemporaryDirectory() as tmp:
result = subprocess.run(
[
"docker", "run", "--rm",
"--network", "none",
"--read-only",
"--cap-drop", "ALL",
"--security-opt", "no-new-privileges",
"--memory", "512m",
"-v", f"{Path(workspace).resolve()}:/work:rw",
IMAGE,
command,
],
env=env or {},
capture_output=True,
text=True,
)
return result.stdout
# The Gemini 3 agent tool calls this, never the host shell
def read_workspace_file(path: str) -> str:
return run_sandboxed_tool(f"cat /work/{path}", workspace="./workspace")
For stronger isolation in regulated environments, replace the container runtime with a microVM runtime (Firecracker or Kata) — the Dockerfile and flags stay the same, but each execution gets its own lightweight kernel.
Verification Checklist
Before putting local agents into production, verify all four converged layers:
- Network egress:
--network noneor an allow-listed egress proxy. - Filesystem boundaries: read-only rootfs, limited writable mounts.
- Secrets scoping: least-privilege credentials injected per task, never wholesale mounts.
- Configuration file protection: prevent writes to shell configs, hooks, and credential stores.
- Non-root user, dropped capabilities,
no-new-privileges, seccomp profile applied. -
docker inspectconfirms no privileged flags are set.
Conclusion
Local Gemini 3 agents are powerful — and they inherit the blast radius of your developer machine. Docker alone is not a security boundary, but a properly hardened, networkless, capability-dropped sandbox is a strong containment layer for the vast majority of tool executions.
Start with hardened containers and strict flags, escalate to gVisor or microVMs for regulated data, and always scope secrets to the task. The goal is simple: even if the agent is hijacked, it should be unable to touch anything beyond the one task it was asked to perform.