Computer-use models can click, type, and read every pixel on a screen. That includes password managers, clipboard contents, and browser autofill. Three sandbox patterns contain the blast radius without breaking the agent’s ability to do useful work.
The Problem Surface
A computer-use agent receives screenshots and emits mouse coordinates, keystrokes, and shell commands. The model sees everything the desktop shows. That means:
- Browser autofill: Chrome renders passwords into the DOM for one frame on focus. The screenshot catches it.
- Clipboard: Cmd+V reveals whatever the user copied last, including recovery phrases.
- OS notifications: 2FA codes, calendar invites, Slack DMs appear as banners.
- Cached sessions: Every site the agent visits inherits cookies from your profile.
- Filesystem:
~/.aws/credentials,~/.ssh/id_rsa,.envfiles are readable if the agent has shell access.
The model doesn’t need to be adversarial. A prompt like “log into Stripe and check the balance” will cause the agent to read credentials from wherever they live, then emit them into tool calls, reasoning traces, or long-term memory entries that get logged or shared.
Pattern 1: Ephemeral Container Per Session
Spin up a fresh container for each agent session. The container gets a clean browser profile, no host credentials, and a read-only overlay filesystem for the OS.
Architecture
┌─────────────────────────────────────┐
│ Orchestrator (host) │
│ - Manages container lifecycle │
│ - Injects secrets via env at boot │
│ - Captures screenshots via VNC │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Ephemeral Container │
│ - Ubuntu + Xvfb + Chrome │
│ - No ~/.aws, ~/.ssh, ~/.config │
│ - Secrets in env, not filesystem │
│ - Destroyed after 15 min or task │
└─────────────────────────────────────┘
Implementation Notes
- Use Docker with
--read-onlyand--tmpfs /tmpto prevent the agent from writing persistent state. - Inject credentials as environment variables at container start, not via mounted volumes.
- Capture screenshots via VNC (RFB protocol) or X11 forwarding. The agent never sees the host display.
- Set a hard timeout (15 minutes) and destroy the container even if the task isn’t done.
Trade-offs
| Dimension | Impact |
|---|---|
| Security | High. Credentials never touch the container filesystem. Blast radius is one container. |
| Performance | 2-4 second cold start per session. Acceptable for batch jobs, painful for interactive loops. |
| Agent capability | Limited. Agent can’t persist state across sessions or access host tools. |
| Observability | Good. Container logs are isolated. Easy to capture full session replay. |
When It Breaks
- Agents that need to install packages or modify system config.
- Workflows that span multiple sessions (the agent can’t resume from a checkpoint).
- Tasks that require access to host-only resources like a local database or SSH tunnel.
Pattern 2: Namespace Isolation with seccomp-bpf
Run the agent in a Linux namespace with a seccomp filter that blocks credential-reading syscalls. The agent shares the host kernel but can’t read files outside its mount namespace or make network calls to internal services.
Architecture
┌─────────────────────────────────────┐
│ Host │
│ - Credentials in ~/.aws, ~/.ssh │
│ - Agent runs in isolated namespace │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Agent Namespace │
│ - Mount: /tmp, /var/agent only │
│ - Network: loopback + egress only │
│ - seccomp: block open() on ~/.aws │
│ - No access to /proc/self/environ │
└─────────────────────────────────────┘
Implementation Notes
Use unshare to create a new mount and network namespace:
unshare --mount --net --pid --fork \
--mount-proc \
--root=/var/agent-root \
bash -c "
mount -t tmpfs tmpfs /tmp
mount -t proc proc /proc
exec agent-runner
"
Add a seccomp filter to block open(), openat(), and readlink() on paths matching ~/.aws, ~/.ssh, or .env:
// Simplified seccomp rule
if (syscall == SYS_openat) {
char *path = get_arg_string(1);
if (strstr(path, ".aws") || strstr(path, ".ssh")) {
return SECCOMP_RET_ERRNO | EACCES;
}
}
Trade-offs
| Dimension | Impact |
|---|---|
| Security | Medium. Blocks most filesystem reads but can’t prevent all exfiltration (agent could screenshot the terminal). |
| Performance | Near-native. No container overhead. |
| Agent capability | Medium. Agent can persist state in /var/agent-root but can’t access host services. |
| Observability | Harder. Namespace logs mix with host logs. Need BPF tracing to see blocked syscalls. |
When It Breaks
- Agents that need to read host environment variables (the namespace can’t see
/proc/1/environ). - Workflows that require access to Docker socket or Kubernetes API.
- Platforms without seccomp-bpf support (Windows, older kernels).
Pattern 3: Capability-Based Credential Proxy
The agent never sees raw credentials. Instead, it calls a proxy service that brokers access to external APIs. The proxy validates each request against a capability list and injects credentials server-side.
Architecture
┌─────────────────────────────────────┐
│ Agent │
│ - Calls proxy.stripe.get_balance() │
│ - Never sees Stripe API key │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Credential Proxy │
│ - Validates capability token │
│ - Injects real API key │
│ - Logs every call │
│ - Rate-limits by agent ID │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ External API (Stripe, AWS, etc.) │
└─────────────────────────────────────┘
Implementation Notes
The agent gets a short-lived capability token at session start:
{
"agent_id": "agent-7f3a",
"capabilities": [
"stripe:read_balance",
"aws:s3:list_buckets"
],
"expires_at": "2026-05-24T12:16:56Z"
}
The proxy validates the token and translates the call:
@app.post("/proxy/stripe/balance")
def get_balance(token: str):
caps = validate_token(token)
if "stripe:read_balance" not in caps:
raise Forbidden("Missing capability")
# Inject real key server-side
stripe.api_key = os.environ["STRIPE_KEY"]
balance = stripe.Balance.retrieve()
log_call(agent_id=caps["agent_id"], action="stripe:read_balance")
return balance
Trade-offs
| Dimension | Impact |
|---|---|
| Security | Highest. Agent never sees credentials. Every call is logged and rate-limited. |
| Performance | Adds 20-50ms per API call for proxy round-trip. |
| Agent capability | Depends on proxy coverage. Agent can only call APIs the proxy exposes. |
| Observability | Excellent. Centralized audit log for every credential use. |
When It Breaks
- Agents that need to call arbitrary APIs (you have to add a proxy endpoint for each one).
- Workflows that require raw credential access (SSH keys, TLS certs).
- High-throughput tasks where 50ms per call adds up.
Combining Patterns
Most production systems layer two or more patterns:
- Ephemeral container + credential proxy: Agent runs in a throwaway container and calls a proxy for secrets. High security, moderate performance.
- Namespace isolation + seccomp: Agent runs in a namespace with syscall filtering. Good for low-latency tasks that don’t need external APIs.
- Proxy + audit log + manual approval: Agent calls proxy, which queues high-risk actions (delete S3 bucket, charge credit card) for human review.
Observability Hooks
Regardless of pattern, instrument these signals:
- Blocked syscalls: Count how often seccomp denies
open()on credential paths. - Proxy rejections: Log every capability check failure with the requested action.
- Screenshot diffs: Hash each screenshot and alert if the agent sees a password manager or terminal with
AWS_SECRET_ACCESS_KEY. - Session duration: Track how long containers live. Agents that run for hours are either stuck or doing something unexpected.
Technical Verdict
Use ephemeral containers for batch jobs, one-shot automations, or any task where a 3-second cold start is acceptable. The blast radius is one container and cleanup is guaranteed.
Use namespace isolation for low-latency interactive agents that need to persist state across multiple tool calls but don’t need host credentials. Performance is near-native but security depends on seccomp rules staying tight.
Use a credential proxy when the agent must call external APIs and you need a centralized audit log. The proxy adds latency but gives you fine-grained control over what the agent can do with each credential.
Avoid giving the agent raw filesystem access to the host. Even read-only mounts leak secrets through .bash_history, .zsh_history, and cached browser profiles.
Avoid relying on the model to not read secrets. Prompt engineering (“don’t look at passwords”) doesn’t work. The model will emit whatever it sees if the task requires it.