# Lambda MicroVM Sandbox (Direct Mode)

Run the vulnerability pipeline agents inside AWS Lambda MicroVMs with
Firecracker hardware isolation. Claude Code runs directly inside the MicroVM
and calls Bedrock via `CLAUDE_CODE_USE_BEDROCK=1` — the simplest possible
MicroVM setup.

## Why Lambda MicroVMs

| Concern | Docker + gVisor | Lambda MicroVM |
|---------|----------------|----------------|
| Isolation | User-space kernel (gVisor) | Hardware microVM (Firecracker) |
| Setup | Install runsc, configure Docker daemon | Deploy CDK stack + build image |
| Scaling | Manual (`--parallel` flag on one host) | Lambda auto-scales per agent |
| Cost | EC2 instance-hours (always on) | Per-invocation (pay for agent runtime only) |
| Cleanup | `docker rm` after run | Automatic (Lambda lifecycle) |
| State leakage | Possible if container reused | Impossible (ephemeral microVM per invocation) |

## Architecture

```
┌───────────────────────────────────────────────────────────────┐
│  Lambda MicroVM (Firecracker isolation)                        │
│                                                                │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ Claude Code CLI                                          │   │
│  │  • CLAUDE_CODE_USE_BEDROCK=1                            │   │
│  │  • AWS_REGION=us-west-2                                 │   │
│  │  • Credentials via IMDS (execution role)                │   │
│  │                                                          │   │
│  │  Calls Bedrock directly ──────────────────────────►     │   │
│  │                                       bedrock-runtime    │   │
│  │  Tools: bash, file I/O, search ──► local filesystem     │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                │
│  Network: HTTP_INGRESS (upload/download) + INTERNET_EGRESS     │
│  Credentials: IMDSv2 → execution role (bedrock:InvokeModel*)  │
└───────────────────────────────────────────────────────────────┘

┌───────────────────────────────────────────────────────────────┐
│  Orchestrator (your machine / CI / Lambda)                     │
│                                                                │
│  1. Launch MicroVM                                            │
│  2. Upload target source via HTTP_INGRESS → /upload           │
│  3. Trigger scan via POST /scan (runs claude -p inside)       │
│  4. Poll /results until complete                              │
│  5. Download findings via /download                           │
│  6. Terminate MicroVM                                         │
└───────────────────────────────────────────────────────────────┘
```

## Prerequisites

- AWS CLI v2 with `lambda-microvms` subcommand (`aws lambda-microvms help`)
- IAM roles:
  - **Build role** — S3 read (artifact bucket), CloudWatch Logs
  - **Execution role** — `bedrock:InvokeModel*` (Claude Code calls Bedrock from inside)
- S3 bucket for the image artifact (same region as the MicroVM image)
- (Optional) VPC with Bedrock VPC endpoint for no-internet deployment

## Quick Start

```bash
# 1. Build the MicroVM image artifact
cd /tmp/defending-code-reference-harness
./scripts/build_microvm_artifact.sh canary

# 2. Upload to S3
aws s3 cp microvm-artifacts/canary.zip s3://my-bucket/vuln-pipeline/canary.zip

# 3. Create the MicroVM image
aws lambda-microvms create-microvm-image \
  --name vuln-pipeline-canary \
  --base-image-arn arn:aws:lambda:<region>:aws:microvm-image:al2023-1 \
  --build-role-arn arn:aws:iam::<acct>:role/MicroVMBuildRole \
  --code-artifact '{"uri":"s3://my-bucket/vuln-pipeline/canary.zip"}' \
  --additional-os-capabilities '["ALL"]'

# 4. Run the pipeline
CLAUDE_CODE_USE_BEDROCK=1 AWS_REGION=us-west-2 \
  python3 -m harness.cli run canary \
  --model us.anthropic.claude-sonnet-4-6 \
  --sandbox microvm \
  --microvm-image arn:aws:lambda:<region>:<acct>:microvm-image:vuln-pipeline-canary \
  --microvm-execution-role arn:aws:iam::<acct>:role/MicroVMExecutionRole
```

## How It Works

1. **Image build** — A Dockerfile packages Claude Code CLI, file_server.py, and
   analysis tools into an OCI image. Lambda builds this into a snapshot-resumable
   MicroVM image.

2. **Launch** — Orchestrator calls `RunMicrovm` with HTTP_INGRESS + INTERNET_EGRESS.
   The MicroVM boots from snapshot in <3s.

3. **Upload** — Orchestrator pushes target source code via `POST /upload` to the
   file server running on port 8080 inside the MicroVM.

4. **Scan** — Orchestrator triggers `POST /scan` which runs `claude -p` inside
   the MicroVM. Claude Code calls Bedrock directly via `CLAUDE_CODE_USE_BEDROCK=1`,
   using credentials from the execution role (IMDS).

5. **Collect** — Orchestrator polls `GET /results` and downloads findings.

6. **Terminate** — `TerminateMicrovm` destroys the environment. No state persists.

## Security Properties

- **Hypervisor isolation** — Each agent runs in its own Firecracker VM with a
  dedicated kernel. Container escape ≠ host escape.
- **No shared filesystem** — Agents cannot access each other's data or the
  orchestrator's filesystem.
- **Ephemeral** — MicroVM is terminated after use. No forensic artifacts remain.
- **IAM-scoped** — Execution role grants only `bedrock:InvokeModel*`. No S3, no
  EC2, no other AWS access from inside the sandbox.
- **Time-bounded** — Auth tokens expire in ≤60 minutes. MicroVM auto-terminates
  on idle timeout.

## Environment Variables

Claude Code inside the MicroVM uses these (set in the image):

| Variable | Value | Purpose |
|----------|-------|---------|
| `CLAUDE_CODE_USE_BEDROCK` | `1` | Use Bedrock instead of Anthropic API |
| `AWS_REGION` | `us-west-2` | Bedrock endpoint region |
| `ANTHROPIC_MODEL` | `us.anthropic.claude-sonnet-4-6` | Model to use |

Credentials come automatically from IMDSv2 (the execution role).

## VPC Endpoint Mode (Optional)

For deployments that require no internet egress, replace `INTERNET_EGRESS` with
a Lambda Network Connector (LNC) that routes to a Bedrock VPC endpoint:

```bash
# Create network connector
aws lambda-microvms create-network-connector \
  --name vuln-pipeline-vpc-connector \
  --vpc-id vpc-xxx \
  --subnet-ids subnet-xxx \
  --security-group-ids sg-xxx

# Run with LNC instead of internet
python3 -m harness.cli run canary \
  --sandbox microvm \
  --microvm-image arn:aws:lambda:<region>:<acct>:microvm-image:vuln-pipeline-canary \
  --microvm-execution-role arn:aws:iam::<acct>:role/MicroVMExecutionRole \
  --microvm-network-connector arn:aws:lambda:<region>:<acct>:network-connector:vuln-pipeline-vpc-connector
```

## Alternative: Zero-Egress Mode

For scanning adversarial or untrusted code where you need maximum isolation
(no outbound network from the MicroVM at all), see the
[zero-egress mode documentation](lambda-microvm-zero-egress.md).

In zero-egress mode:
- The MicroVM has no internet access
- The orchestrator proxies all Bedrock calls
- Source code physically cannot be exfiltrated

## See Also

- [Zero-Egress Mode](lambda-microvm-zero-egress.md) — Maximum security for adversarial code
- [EC2 Sandbox](ec2-sandbox.md) — Standard EC2 via SSM, no MicroVM preview needed
- [Bedrock Authentication](bedrock.md) — Setting up Bedrock credentials
