If your coding agent can shell out on a shared laptop or a long-lived runner, you do not have a sandbox — you have a future incident. Run agent tools inside ephemeral ECS tasks: no long-lived credentials, disk quotas, egress allowlists, and hard TTLs so a compromised session cannot reach production data stores.
⚡ TL;DR: Spawn Fargate/ECS tasks per agent session; inject short-lived task roles; block IMDS where possible; allowlist egress; destroy the task on idle. Mirror patterns from LLM coding agents in Lambda sandboxes and Claude Code risky shell hooks.
Ephemeral task per session
// sandbox_launcher.ts
import { ECSClient, RunTaskCommand, StopTaskCommand } from "@aws-sdk/client-ecs";
export async function startAgentSandbox(sessionId: string) {
const ecs = new ECSClient({});
const out = await ecs.send(
new RunTaskCommand({
cluster: process.env.SANDBOX_CLUSTER!,
taskDefinition: "agent-sandbox:47",
launchType: "FARGATE",
networkConfiguration: {
awsvpcConfiguration: {
subnets: process.env.SANDBOX_SUBNETS!.split(","),
securityGroups: [process.env.SANDBOX_SG!],
assignPublicIp: "DISABLED", // ✅ private only
},
},
overrides: {
containerOverrides: [
{
name: "agent",
environment: [
{ name: "SESSION_ID", value: sessionId },
{ name: "MAX_RUNTIME_SEC", value: "1800" },
],
},
],
// Task role is session-scoped via intermediate assume-role if needed
},
tags: [{ key: "sessionId", value: sessionId }],
})
);
return out.tasks?.[0]?.taskArn!;
}
// ❌ Reuse one fat EC2 instance for all tenants' agents
✅ New task ARN per session; stop on complete/idle.
❌ Shared Docker socket on a CI box with prod kubeconfig mounted.
Credentials, disk, egress
{
"family": "agent-sandbox",
"taskRoleArn": "arn:aws:iam::123:role/agent-sandbox-session",
"ephemeralStorage": { "sizeInGiB": 20 },
"containerDefinitions": [{
"name": "agent",
"linuxParameters": {
"capabilities": { "drop": ["ALL"] },
"readonlyRootFilesystem": true
},
"environment": [
{ "name": "HTTP_PROXY", "value": "http://egress-proxy.internal:3128" }
]
}]
}
# IAM — illustrative least privilege for sandbox role
# ✅ S3 read on session bucket prefix only
# ✅ ECR pull
# ❌ s3:* on *
# ❌ iam:CreateAccessKey
# ❌ sts:AssumeRole on prod account roles
Egress SG + proxy allowlist: package registries, Bedrock VPC endpoint, git over HTTPS to your org — nothing else. See VPC private Bedrock.
Kill switches and audit
# watchdog.py
def enforce_ttl(task_arn: str, started_at: float, max_sec: int = 1800):
if time.time() - started_at > max_sec:
stop_task(task_arn, reason="ttl_exceeded") # ✅ hard stop
emit_metric("SandboxTtlKill", 1)
# Log every tool: command hash, exit code, bytes written — no secret values
| Control | Purpose |
|---|---|
| Task TTL | Bound blast window |
| Disk quota / readonly root | Stop crypto-miner scratch |
| Egress allowlist | Block exfil |
| Session task role | No long-lived keys on disk |
| CloudTrail + exec logs | Forensics |
Closing checklist
✅ Dos
– ✅ One ECS/Fargate task per agent session
– ✅ Short-lived roles + private subnets
– ✅ Egress proxy allowlists
– ✅ TTL watchdog and idle stop
– ✅ Drop Linux caps; readonly root where feasible
❌ Don’ts
– ❌ Don’t mount prod kubeconfigs or cloud admin keys
– ❌ Don’t share sandboxes across tenants
– ❌ Don’t allow unrestricted outbound curl
– ❌ Don’t skip idempotency if tools write
– ❌ Don’t treat “Docker on the laptop” as production isolation
Related reading
- LLM Coding Agents: Lambda Sandboxes
- Claude Code Hooks: Gate Risky Shell Commands Before CI Runs
- AI Coding in VPC: Private Bedrock Endpoints and Secret Hygiene
- Bedrock Agents: Idempotent Tool Calls Against DynamoDB Writes
Last updated on September 11, 2026
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.

Pingback: Lambda Warm Pools: Low-Latency Backends for Coding Agent Tools - CheatCoders
Pingback: Ephemeral Debug Sidecars: Audited Access Without Permanent Prod Shells - CheatCoders