Security Model
Security Overview
Runner Codes is designed with security as a primary concern. Running untrusted code generated by LLMs requires multiple layers of isolation.
Security Architecture
Isolation Layers
Layer 1: Hardware Virtualization (KVM)
Firecracker uses Linux KVM for hardware-level virtualization:
- Separate kernel: Each VM runs its own Linux kernel
- Memory isolation: VM memory is isolated from host and other VMs
- CPU isolation: Virtual CPUs separate from host CPUs
Layer 2: Minimal Device Model
Firecracker implements only essential devices:
| Device | Purpose | Security Impact |
|---|---|---|
| virtio-block | Storage | Read-only possible |
| virtio-net | Network | Disabled by default |
| virtio-vsock | Communication | Host-initiated only |
| Serial | Debug | Output only |
Fewer devices = smaller attack surface. Firecracker is only ~50,000 lines of Rust code.
Layer 3: Network Isolation
VMs have no network access by default:
Benefits:
- No data exfiltration via network
- No downloading malware
- No C2 communication
- No lateral movement
Layer 4: Resource Limits
Each VM has enforced limits:
| Resource | Default | Configurable |
|---|---|---|
| vCPUs | 1 | Yes |
| Memory | 512 MiB | Yes |
| Timeout | 10 seconds | Yes |
| Disk | Read-write, ephemeral | No |
Threat Model
Threats Mitigated
VM Escape
Threat: Malicious code escapes VM to host
Mitigation: Hardware virtualization via KVM provides strong isolation. Guest code cannot access host memory or processes.
Data Exfiltration
Threat: Code sends sensitive data to external servers
Mitigation: No network access. The only communication channel is vsock, which is controlled by the host agent.
Resource Exhaustion
Threat: Code consumes excessive resources
Mitigation:
- CPU: Limited vCPUs (default 1)
- Memory: Capped at 512 MiB
- Time: Execution timeout (default 10s)
- Disk: Ephemeral, destroyed after execution
Cryptocurrency Mining
Threat: Code mines cryptocurrency
Mitigation:
- Timeout limits execution time
- No network prevents pool connection
- VM destroyed after execution
Lateral Movement
Threat: Code attacks other systems
Mitigation: No network access. Cannot reach other VMs or external systems.
Residual Risks
These risks are not fully mitigated in the current PoC:
| Risk | Impact | Recommendation |
|---|---|---|
| KVM vulnerabilities | VM escape | Keep kernel updated |
| Firecracker vulnerabilities | VM escape | Keep Firecracker updated |
| Side-channel attacks | Information leak | Disable SMT, use jailer |
| Timing attacks | Information leak | Normalize execution time |
Production Hardening
Enable Jailer
The Firecracker jailer provides additional isolation:
jailer --id ${VM_ID} \
--exec-file /usr/bin/firecracker \
--uid 10000 \
--gid 10000 \
--chroot-base-dir /srv/jailer \
--daemonize
Features:
- chroot: Filesystem isolation
- uid/gid: Run as non-root
- seccomp: System call filtering
- cgroups: Resource control
Seccomp Profiles
Enable strict seccomp filtering:
{
"default_action": "trap",
"filter_action": "allow",
"filters": [
{ "syscall": "read" },
{ "syscall": "write" },
{ "syscall": "exit" },
{ "syscall": "exit_group" }
]
}
Disable SMT
Simultaneous Multi-Threading (SMT) can enable side-channel attacks:
{
"vcpu_count": 1,
"mem_size_mib": 512,
"smt": false
}
Read-Only Rootfs
For maximum isolation, use read-only rootfs:
{
"drive_id": "rootfs",
"path_on_host": "/srv/firecracker/rootfs.ext4",
"is_root_device": true,
"is_read_only": true
}
Read-only rootfs requires a writable tmpfs for /tmp. Configure in kernel boot args.
Input Validation
Code Validation
Before executing code, validate:
func validateJob(job Job) error {
// Check trace_id format
if !validTraceID(job.TraceID) {
return errors.New("invalid trace_id")
}
// Check language
validLangs := map[string]bool{
"python": true, "node": true, "go": true,
"rust": true, "bash": true,
}
if !validLangs[job.Lang] {
return errors.New("unsupported language")
}
// Check code size
if len(job.Code) > 1024*1024 { // 1MB limit
return errors.New("code too large")
}
// Check timeout
if job.Timeout <= 0 || job.Timeout > 300 {
return errors.New("invalid timeout")
}
return nil
}
Dangerous Pattern Detection
Optionally scan for dangerous patterns:
var dangerousPatterns = []string{
`rm\s+-rf\s+/`, // rm -rf /
`dd\s+if=.*of=/dev`, // dd to devices
`:(){ :|:& };:`, // Fork bomb
`while.*true.*do`, // Infinite loops (bash)
}
func scanDangerousPatterns(code string) []string {
var matches []string
for _, pattern := range dangerousPatterns {
re := regexp.MustCompile(pattern)
if re.MatchString(code) {
matches = append(matches, pattern)
}
}
return matches
}
Pattern detection is defense-in-depth. The VM isolation is the primary security control.
Logging and Monitoring
Security Events
Log these security-relevant events:
type SecurityEvent struct {
Timestamp time.Time `json:"timestamp"`
EventType string `json:"event_type"`
TraceID string `json:"trace_id"`
Details string `json:"details"`
}
// Events to log:
// - VM_START: VM started
// - VM_STOP: VM stopped (normal)
// - VM_TIMEOUT: Execution timeout
// - VM_OOM: Out of memory
// - VALIDATION_FAIL: Input validation failed
// - DANGEROUS_PATTERN: Dangerous code pattern detected
Metrics
Collect security metrics:
| Metric | Description |
|---|---|
vm_timeouts_total | Executions killed by timeout |
vm_oom_total | Out of memory events |
validation_failures_total | Input validation failures |
dangerous_patterns_total | Dangerous patterns detected |
vm_boot_time_seconds | Time to boot VM |
vm_execution_time_seconds | Code execution time |
Comparison with Alternatives
| Feature | Runner Codes | Docker | gVisor | Kata |
|---|---|---|---|---|
| Isolation | Hardware (KVM) | Namespace | Syscall filter | Hardware |
| Attack surface | Very small | Large | Medium | Small |
| Kernel shared | No | Yes | Emulated | No |
| Network control | Built-in | Requires config | Requires config | Requires config |
| Startup time | ~3s | ~100ms | ~100ms | ~1s |
| Memory overhead | ~5MB | ~1MB | ~10MB | ~50MB |
Security Checklist
Deployment
- Run on dedicated hosts (no other workloads)
- Keep kernel updated
- Keep Firecracker updated
- Enable seccomp filtering
- Disable SMT on host
- Use jailer in production
- Monitor security events
- Set up alerting for timeouts/OOM
Configuration
- Set appropriate timeout limits
- Set appropriate memory limits
- Disable network (default)
- Use minimal rootfs images
- Remove unnecessary packages from rootfs
Operations
- Regular security audits
- Incident response plan
- Log retention policy
- Access control for host