Skip to main content

Isolation Models: VMs vs Containers vs Safehouse

Safehouse is not a VM replacement. It’s a low-friction host-level containment layer optimized for local agent workflows on macOS. Understanding the differences helps you choose the right tool for your threat model.

Quick Comparison

FeatureVMsContainersSafehouse
Isolation BoundaryGuest OS boundaryProcess namespace/cgroupmacOS Seatbelt policy
Kernel SeparationYes (separate kernel)No (shared kernel*)No (shared kernel)
Default FilesystemGuest filesystem onlyContainer filesystemDeny-first host paths
Performance OverheadHighLow to mediumVery low
Agent Workflow CompatibilityLower (requires setup/sync)MediumHigh (native tooling)
Best ForStrong adversarial isolationApp packaging & deploymentDay-to-day coding agent use
*Containers on macOS often run inside a lightweight VM (Docker Desktop, Lima, etc.), adding VM-level isolation.

Virtual Machines

How They Work

VMs run a complete guest operating system on a hypervisor:
1

Hypervisor Layer

Software like VMware, Parallels, or Apple’s Hypervisor.framework creates isolated guest instances
2

Separate Kernel

Each VM runs its own kernel, completely isolated from the host
3

Guest Filesystem

VM disk is a file on the host; guest sees it as a complete filesystem
4

Explicit Host Mounts

Host directories must be explicitly shared and mounted

Security Properties

✅ Strongest Isolation

Separate kernel means bugs in the guest cannot directly affect the host

✅ Escape Resistance

VM escapes exist but are rare and typically patched quickly

✅ Network Isolation Options

Can fully disconnect guest from network or use NAT/bridge configurations

✅ Snapshotting

Easy rollback to known-good states after risky operations

Practical Tradeoffs

High Overhead: VMs require significant resources (RAM, disk, CPU) and add latency to I/O operations.
Workflow Friction:
  • Duplicate toolchains: Must install Node, Python, Go, etc. inside the guest
  • Workspace syncing: Need strategy for keeping host/guest files in sync
  • Credential management: SSH keys, git config, API tokens must be managed separately
  • GUI limitations: Running GUI agents (Cursor, Claude.app) in a VM is awkward
  • Copy/paste friction: Clipboard integration varies by hypervisor

When to Use VMs

Adversarial Scenarios

Testing untrusted code, analyzing malware, or defending against sophisticated attackers

Air-Gapped Environments

Work that must be completely network-isolated

Regulatory Compliance

Environments where VM boundaries are required by policy

Containers

How They Work

Containers use OS-level virtualization (namespaces, cgroups) to isolate processes:
1

Shared Kernel

All containers share the host kernel (unlike VMs)
2

Namespace Isolation

Process, network, filesystem, and user namespaces provide separation
3

Container Filesystem

Layered filesystem (overlayfs) provides isolated view of files
4

Explicit Bind Mounts

Host directories must be explicitly mounted with -v or --mount

Security Properties

✅ Process Isolation

Container processes cannot see or signal host processes

✅ Filesystem Isolation

Container sees only its own filesystem unless bind mounts are added

⚠️ Shared Kernel

Kernel exploits can potentially escape the container

⚠️ Privileged Containers

Easy to accidentally weaken isolation with --privileged or excessive capabilities

Practical Tradeoffs

Better for Apps Than Agents:
  • Containers excel at packaging server applications with dependencies
  • Desktop-hosted agents (Cursor, Claude.app) don’t fit the container model well
  • CLI agents in containers work but lose native shell integration
Workflow Considerations:
  • Toolchain packaging: Can bundle exact versions, good for reproducibility
  • Volume mounting: Easy to mount host workdir read-only or read/write
  • Credential mounting: Can mount SSH keys, cloud configs as volumes (security risk)
  • Network: Usually NAT’d by default, can be isolated if needed
  • macOS specifics: Docker Desktop runs containers inside a lightweight Linux VM

When to Use Containers

Reproducible Environments

Ensuring the agent uses exact toolchain versions across machines

CLI-Only Agents

Non-GUI agents (Aider, Goose) running on servers or in CI

Dependency Isolation

Preventing agent dependencies from conflicting with host packages

Safehouse (sandbox-exec)

How It Works

Safehouse uses macOS’s built-in Seatbelt/sandbox-exec mechanism:
1

Policy Composition

Assembles a Sandbox Profile Language (.sb) policy from modular components
2

Sandbox-Exec Invocation

Launches your command under sandbox-exec -f policy.sb -- command
3

Kernel Enforcement

macOS kernel enforces the policy for the process and all its children
4

Filesystem Interposition

Every file operation is checked against the policy; unauthorized attempts are denied

Security Properties

✅ Filesystem Containment

Fine-grained control over which paths are readable/writable

✅ Process Restrictions

Can limit process signaling, debugging, and IPC (configurable)

⚠️ Shared Kernel

Same kernel as host; not a VM boundary

⚠️ Escape Potential

Sandbox escapes have occurred in the past; not proof against sophisticated attackers

Practical Tradeoffs

Optimized for Usability:
  • Native tooling: Uses your host’s Node, Python, Go installations directly
  • No duplication: No need for separate tool installs inside a container/VM
  • Zero syncing: Works directly on host filesystem (with restrictions)
  • GUI support: Works perfectly with desktop agents like Cursor and Claude.app
  • Minimal overhead: Near-zero performance impact
Workflow Integration:
  • Same shell environment (with sanitization)
  • Same git config and SSH setup
  • Same editor/IDE
  • Same package manager caches

When to Use Safehouse

Daily Coding Workflows

Regular use of agents on your local machine

GUI Agents

Cursor, Claude.app, VS Code with Copilot, etc.

Low-Friction Security

Want protection without workflow disruption

Blast Radius Reduction

Limit damage from mistakes, not defending against nation-states

Detailed Comparison

Threat Model Match

ThreatVMContainerSafehouse
Prompt injection✅ Excellent✅ Good✅ Good
Buggy commands✅ Excellent✅ Good✅ Good
Confused deputy✅ Excellent✅ Good✅ Good
Supply chain compromise✅ Excellent⚠️ Medium⚠️ Medium
Sophisticated attacker✅ Excellent⚠️ Medium❌ Limited
Network exfiltration✅ Good (can air-gap)⚠️ Medium (NAT)❌ Not protected

Workflow Compatibility

WorkflowVMContainerSafehouse
CLI agents⚠️ Requires setup✅ Native fit✅ Seamless
GUI agents❌ Awkward❌ Not supported✅ Seamless
Shell integration❌ Separate env⚠️ Limited✅ Native
Toolchain usage❌ Duplicate install⚠️ Must package✅ Host tooling
Performance❌ High overhead⚠️ Medium✅ Minimal
Workspace sync❌ Required⚠️ Volume mounts✅ Not needed

Administrative Overhead

TaskVMContainerSafehouse
Initial setup❌ High⚠️ Medium✅ Low
Maintenance❌ High⚠️ Medium✅ Low
Updates❌ Guest OS + tools⚠️ Rebuild images✅ Host updates apply
Credential management❌ Duplicate/mount⚠️ Mount secrets✅ Selective access

Layering Models

For maximum protection, combine models: Run your agent inside a VM, then run Safehouse inside that VM.

VM + Safehouse

1

VM Isolation

Run your coding workflow inside a VM (UTM, Parallels, VMware)
2

Safehouse Inside VM

Install Safehouse in the VM guest and wrap your agent commands
3

Defense in Depth

  • VM boundary protects host from guest escapes
  • Safehouse restricts agent filesystem access inside guest
  • Network isolation can be added at VM level
Result: Strong isolation boundary plus granular in-guest path control.

Container + Safehouse

1

Container Base

Package your agent environment as a container
2

Safehouse Layer

Install Safehouse in the container and set it as the entrypoint wrapper
3

Combined Protection

  • Container provides process/network isolation
  • Safehouse restricts filesystem within container
Result: Reproducible environment plus defense-in-depth filesystem policy.

Choosing the Right Model

  • You’re doing daily coding with agents on your local machine
  • You want protection without workflow disruption
  • You use GUI agents (Cursor, Claude.app, etc.)
  • Threat model is mistakes and simple attacks, not sophisticated adversaries
  • You need minimal overhead and native tooling
  • You’re running CLI-only agents in server environments
  • You need reproducible toolchain versions
  • You’re packaging agents for deployment or CI/CD
  • You can tolerate the overhead of volume mounts and networking config
  • You’re testing untrusted code or analyzing malware
  • Your threat model includes sophisticated attackers or sandbox escapes
  • Regulatory/compliance requirements mandate VM boundaries
  • You need true air-gapped environments
  • Workflow friction and resource overhead are acceptable
  • You want the strongest practical protection
  • You can tolerate VM overhead
  • You still want fine-grained filesystem control inside the guest
  • Defense-in-depth is a priority

Summary

VMs

Strongest isolationBest for adversarial scenarios, but highest friction and overhead

Containers

App packagingGreat for servers and CLI tools, awkward for desktop agents

Safehouse

Practical hardeningNative workflows with meaningful blast-radius reduction
There’s no single “best” model. Choose based on your specific threat model, workflow needs, and tolerance for friction.

Next Steps

Default Assumptions

Learn what Safehouse allows and denies by default

Getting Started

Install Safehouse and run your first sandboxed agent

Build docs developers (and LLMs) love