# How gVisor Provides Sandbox Isolation in Agent Substrate

> Agent Substrate leverages gVisor's runsc userspace kernel for robust sandbox isolation, enhancing actor security within your WorkerPool.

- Repository: [Agent Substrate/substrate](https://github.com/agent-substrate/substrate)
- Tags: internals
- Published: 2026-08-22

---

**Agent Substrate isolates each actor by running it inside a gVisor-backed sandbox that uses the `runsc` userspace kernel to mediate system calls, configured via the `gvisor` SandboxClass in WorkerPool manifests.**

Agent Substrate leverages gVisor to provide kernel-level sandboxing for workload isolation. By setting the `sandboxClass` to `gvisor` in a WorkerPool, the platform launches the `ateom-gvisor` herder container inside each worker pod. This architecture ensures that actor processes never execute directly on the host kernel, forming a critical layer in the Defense-in-Depth security model.

## Selecting the gVisor Sandbox Class

The platform defines the gVisor runtime through the `SandboxClassGvisor` enum in [`pkg/api/v1alpha1/sandboxconfig_types.go`](https://github.com/agent-substrate/substrate/blob/main/pkg/api/v1alpha1/sandboxconfig_types.go). This constant (`"gvisor"`) serves as the identifier that triggers the gVisor isolation pathway throughout the control plane.

To activate gVisor sandboxing, create a WorkerPool that specifies the gVisor class in its specification:

```yaml
apiVersion: ate.dev/v1alpha1
kind: WorkerPool
metadata:
  name: gvisor-pool
spec:
  sandboxClass: gvisor            # selects the gVisor runtime

  # optional: name of a custom SandboxConfig; omitted => default

  # sandboxConfigName: my-gvisor-config

```

When the control plane observes `spec.sandboxClass: gvisor`, it schedules the `ateom-gvisor` herder container (defined in `cmd/ateom-gvisor`) inside each worker pod instead of the standard runtime.

## Provisioning Runtime Binaries via SandboxConfig

The `SandboxConfig` resource supplies the gVisor release artifacts required to bootstrap the sandbox. The default configuration is defined in [`manifests/ate-install/sandboxconfig-gvisor.yaml`](https://github.com/agent-substrate/substrate/blob/main/manifests/ate-install/sandboxconfig-gvisor.yaml) and named `gvisor-default`.

This manifest declares the **pause container image** that anchors the sandbox namespace and an **asset** named `gvisor` containing the release tarball:

```yaml
apiVersion: ate.dev/v1alpha1
kind: SandboxConfig
metadata:
  name: gvisor-default
spec:
  sandboxClass: gvisor
  default: true
  pauseImage: "registry.k8s.io/pause:3.10.2@sha256:f548e0e8e3dc1896ca956272154dde3314e8cc4fde0a57577ee9fa1c63f5baf4"
  assets:
    amd64:
      gvisor:
        url: "gs://gvisor/releases/release/20260803/x86_64/gvisor.tar.bz2"
        sha256: "9e7a5fcc2cbd28c9cd4af910a9327abcf07a8efcce242c285b860d79010c2db5"

```

When a worker pod starts, the `atelet` supervisor fetches this asset, verifies the SHA256 checksum, extracts the `runsc` binary and its helper binaries, and mounts them into the `ateom-gvisor` container at runtime.

## Isolation Mechanism and Security Boundaries

Inside the worker pod, the `ateom-gvisor` process invokes the `runsc` binary to create the sandbox environment. The `runsc` implementation acts as a userspace kernel that intercepts and mediates all system calls from the actor’s process.

This architecture provides:

- **Separate cgroup namespace** for resource isolation
- **Separate network namespace** for traffic segmentation
- **Userspace syscall filtering** that prevents direct host kernel access

Because the sandboxed process never executes on the host kernel directly, container-escape attempts are confined to the gVisor boundary. According to the architecture documentation in [`docs/architecture.md`](https://github.com/agent-substrate/substrate/blob/main/docs/architecture.md), this design provides kernel-level sandboxing that prevents container escapes, fulfilling the platform’s Defense-in-Depth requirements.

## Native Checkpoint and Restore Capabilities

The gVisor backend supports efficient suspend and resume operations through native checkpoint/restore functionality. When the control plane requests a suspension, `ateom-gvisor` executes `runsc checkpoint`, which produces a consistent snapshot of the process tree and memory state.

To trigger a checkpoint via the Go client:

```go
client := ateapi.NewClient(...)
ctx := context.Background()
_, err := client.CheckpointWorkload(ctx, &ateapi.CheckpointRequest{
    ActorName: "my-actor",
    SnapshotId: "snap-001",
})
if err != nil {
    log.Fatalf("checkpoint failed: %v", err)
}

```

To resume the workload, the platform calls `runsc restore`, which reconstructs the process tree inside the same sandbox environment. The `PauseImage` field recorded in the snapshot manifest ensures that identical container images and binaries are used during restoration:

```go
_, err = client.RestoreWorkload(ctx, &ateapi.RestoreRequest{
    ActorName: "my-actor",
    SnapshotId: "snap-001",
})
if err != nil {
    log.Fatalf("restore failed: %v", err)
}

```

## Summary

- **Sandbox selection** occurs via the `SandboxClassGvisor` enum in [`pkg/api/v1alpha1/sandboxconfig_types.go`](https://github.com/agent-substrate/substrate/blob/main/pkg/api/v1alpha1/sandboxconfig_types.go), activated by setting `spec.sandboxClass: gvisor` in a WorkerPool.
- **Binary provisioning** relies on the `SandboxConfig` resource in [`manifests/ate-install/sandboxconfig-gvisor.yaml`](https://github.com/agent-substrate/substrate/blob/main/manifests/ate-install/sandboxconfig-gvisor.yaml), which supplies the gVisor release tarball as a versioned asset.
- **Runtime isolation** is enforced by the `runsc` userspace kernel, which mediates syscalls within separate cgroup and network namespaces via the `ateom-gvisor` herder.
- **State persistence** utilizes gVisor’s native `runsc checkpoint` and `runsc restore` commands to enable fast suspend/resume while maintaining sandbox boundaries.

## Frequently Asked Questions

### How do I enable gVisor sandboxing for a specific WorkerPool?

Create or update a WorkerPool resource and set `spec.sandboxClass` to `gvisor`. This value corresponds to the `SandboxClassGvisor` constant defined in [`pkg/api/v1alpha1/sandboxconfig_types.go`](https://github.com/agent-substrate/substrate/blob/main/pkg/api/v1alpha1/sandboxconfig_types.go). The control plane will automatically inject the `ateom-gvisor` herder container into pods belonging to that pool.

### What files are required to configure the gVisor runtime?

You need the `SandboxConfig` manifest (typically [`manifests/ate-install/sandboxconfig-gvisor.yaml`](https://github.com/agent-substrate/substrate/blob/main/manifests/ate-install/sandboxconfig-gvisor.yaml)) which declares the pause container image and the gVisor release asset URL. The `atelet` component on each worker node downloads and extracts these binaries before starting the sandbox.

### How does gVisor prevent container escapes in Agent Substrate?

The `runsc` binary implements a userspace kernel that intercepts all system calls from the actor process. Because the workload runs within separate cgroup and network namespaces and never accesses the host kernel directly, escape attempts are contained within the gVisor sandbox boundary, as documented in [`docs/architecture.md`](https://github.com/agent-substrate/substrate/blob/main/docs/architecture.md).

### Does the gVisor integration support workload migration and failover?

Yes. The `ateom-gvisor` herder leverages gVisor’s native checkpoint/restore functionality. When suspended, `runsc checkpoint` captures the full process state to durable storage. The `runsc restore` command recreates the environment identically on any compatible worker node, preserving the sandbox configuration and pause image references stored in the snapshot manifest.