# Agent Isolation Architecture: The Four-Layer Security Model (https://jackin.tailrocks.com/reference/research/security/isolation-architecture/agent-isolation-architecture/)



**Status**: Open — research complete, design approved, implementation sequenced

## What This Document Is [#what-this-document-is]

This is the master security architecture document for jackin❯. It explains why jackin❯ needs a layered isolation model, how we arrived at each decision through research and verification, what each layer solves, and how the layers compose into a complete security story equivalent to — and in operator experience, better than — Docker Sandboxes.

Every design decision here was reached through a deliberate research trail starting from the question: "we use Docker today and it seems fine — why would we need to change anything?" This document answers that question honestly.

***

## Part 1: How We Arrived Here — The Research Trail [#part-1-how-we-arrived-here--the-research-trail]

### The Starting Point [#the-starting-point]

jackin❯ launched as a Docker-first orchestration layer for AI agents. The initial security model was practical and correct for a proof-of-concept:

* explicit workspace bind mounts (only operator-approved paths)
* host Docker socket excluded from agent containers
* per-agent Docker network
* TLS-authenticated DinD sidecar for Docker workflows inside the agent

That model is already better than a developer container with the host socket mounted. The question in June 2026 was: "is it good enough, and if not, where are the real risks?"

### Step 1: Researching OrbStack Isolated Machines [#step-1-researching-orbstack-isolated-machines]

The first candidate for improvement was OrbStack isolated machines — a macOS-native feature that creates machines without the default full-Mac-filesystem passthrough. The hypothesis was that an isolated machine would give each jackin❯ session a stronger boundary.

**What we found**: OrbStack isolated machines share OrbStack's Linux kernel. They provide namespace isolation within the existing OrbStack VM — cgroups and namespaces, not a hypervisor boundary per workload. For the current audience (100% macOS ARM operators who already use OrbStack as their Docker engine), the role container already lives inside OrbStack's Linux VM. An isolated machine would add a namespace layer on the same kernel.

**Conclusion**: [OrbStack isolated machine backend](/reference/research/isolation/orbstack-isolated-machines/) deferred. Namespace isolation within a shared kernel does not address the kernel escape risk that motivates VM-level separation.

### Step 2: Researching the Actual Threat [#step-2-researching-the-actual-threat]

After the OrbStack deferral, the question became: what exactly is the threat that shared-kernel containers cannot address?

Research into the 2025–2026 CVE landscape established concrete evidence:

**runc vulnerabilities (November 2025)**: Three high-severity CVEs allowing container escape to the host system, affecting Docker, containerd, and every managed Kubernetes service. The attack path starts inside a container and reaches the host kernel.

**CVE-2026-34040**: Docker authorization bypass via oversized HTTP requests — allows unauthorized creation of containers with full host access. Fixed in Docker Engine 29.3.1.

**CVE-2024-1086**: Use-after-free in Linux's netfilter subsystem. Confirmed actively exploited in ransomware campaigns (CISA advisory, October 2025). Reachable from inside a container.

**DinD `--privileged`**: jackin❯ runs a privileged DinD sidecar today. A `--privileged` container has near-full access to the host kernel — in jackin❯s case, OrbStack's Linux VM kernel. Recent attack chains have started from legitimate AI agent setups that followed Docker's own security recommendations.

**The shared-kernel insight**: The attack surface for all of these is the kernel. Every jackin❯ session shares one OrbStack Linux VM kernel. A successful kernel exploit in one session reaches all sessions. This is not a configuration problem — it is structural.

### Step 3: Mapping the Full Problem Space [#step-3-mapping-the-full-problem-space]

Concurrent with the kernel research, a second problem emerged from operator experience: credential exposure.

The current jackin❯ model injects agent credentials (Claude API key, GitHub token, SSH keys) into the role container as environment variables or synced files. This means:

* The agent process can `printenv` and read raw API keys
* The agent can read credential files from the agent home mount
* The agent retains credential values in its context window across prompts
* Multiple agents sharing a workspace can access each other's credentials if one is compromised
* An agent prompted to exfiltrate data can extract raw token values

This is not a kernel-level problem. It exists regardless of whether the backend is Docker, OrbStack isolated, or a full microVM. A VM boundary gives each session its own kernel — but if the API key is an environment variable inside that VM, the agent can still read it.

**The two problems are independent and require independent solutions.**

### Step 4: Researching the Microvm Landscape [#step-4-researching-the-microvm-landscape]

With the kernel boundary problem defined, we researched what provides a true per-workload kernel boundary on macOS ARM.

**Firecracker**: requires KVM (Linux-only). On macOS ARM, needs nested virtualization inside a Linux VM — not officially supported by the Firecracker project. Not viable.

**gVisor**: syscall interception in userspace — no KVM required. But confirmed broken on OrbStack macOS ARM ([orbstack/orbstack#2362](https://github.com/orbstack/orbstack/issues/2362) — `/tmp → /private/tmp` symlink causes runsc to crash immediately). Claude Code hangs indefinitely in gVisor on macOS ARM ([anthropics/claude-code#35454](https://github.com/anthropics/claude-code/issues/35454)). Not viable on current platform stack.

**smolvm**: uses Hypervisor.framework on macOS and libkrun on Linux. Pre-1.0. Has a documented Docker-in-VM path (v0.7.0, requires Alpine base + ext4 bind mount + virtio-net). **Deferred** in June 2026 — Apple Container is the primary macOS 26 VM track (zero install friction, gRPC/vsock attach, Virtualization.framework). smolvm remains the fallback if Apple Container Phase 0 fails the Docker-inside test. See [smolvm backend research](/reference/research/isolation/smolvm-backend/).

**Docker Sandboxes**: productized microVM runner from Docker Inc. (launched January 2026). Runs each agent session in a dedicated VM using a proprietary VMM on Apple's Hypervisor.framework. Has a built-in credential proxy and network proxy. However: not a backend API for jackin❯ to build on — it is a complete agent runner that replaces jackin❯s role (see [Part 3](#part-3-why-apple-container-not-docker-sandboxes)).

**Apple Container framework** (macOS 26 Tahoe, WWDC 2025, `apple/container` v0.11.0 March 2026): each OCI container runs in its own dedicated lightweight VM via Virtualization.framework, natively on Apple Silicon. Sub-second start times. Own kernel per container. Own IP per container via vmnet. OCI-compatible. CLI with Docker-compatible surface (`container run`, `container exec`, `container stop`, `container rm`). PID 1 is `vminitd` — a minimal Swift static binary that exposes a gRPC API over vsock for process management and I/O streaming. Zero install friction on macOS 26.

**Key finding for Apple Container**: `--privileged` is not supported. The documented alternative is `--cap-add <CAP>` for specific capabilities. This means the current jackin❯ DinD sidecar (which requires `--privileged`) cannot run inside an apple/container VM without changes. Rootless DinD — which replaces `--privileged` with specific capability grants — is the compatibility path, but requires the [Docker runtime hardening contract](/roadmap/docker-runtime-hardening-contract/) work to complete first.

### Step 5: Recognizing That VM Isolation Alone Is Not Enough [#step-5-recognizing-that-vm-isolation-alone-is-not-enough]

After establishing Apple Container as the right VM primitive, a third problem surfaced: even inside a perfectly isolated VM with its own kernel, an agent's individual tool calls are unconstrained.

When an agent runs `npm install`, that subprocess inherits every secret in the container's environment, can write to every writable path, and can reach every network endpoint. The VM boundary prevents kernel escapes — it does not prevent an agent from reading a secret it was given or writing to a path it should not touch.

This is the gap that process-level sandboxing fills. Research into [Zerobox](https://github.com/afshinm/zerobox) — the open-source library powering OpenAI Codex CLI's sandbox mode — confirmed that per-operation isolation is achievable with 10 ms overhead per invocation, using OS-native primitives (Bubblewrap + Seccomp + Landlock on Linux, Apple Seatbelt on macOS).

### Step 6: The `jackin-exec` Insight [#step-6-the-jackin-exec-insight]

The credential exposure problem requires a different mechanism than both VM isolation and process sandboxing. The question is: how does an agent run `ssh sentry` without jackin❯ injecting the SSH key into the container's environment?

The answer: a two-tier workspace env model and a `jackin-exec` subcommand of `jackin-capsule`.

**Two env tiers — same `env` map, one new flag:**

* `{ op = "...", path = "..." }` (default): injected into container at launch, all processes see the resolved value
* `{ op = "...", path = "...", on_demand = true }`: NOT injected at launch, NOT visible via `printenv`; appears in a TUI picker dialog when the agent calls `jackin-exec`, operator selects which credentials to attach, host resolves via `op read` at that moment, injected ephemerally for the command duration

**`jackin-exec` = `jackin-capsule exec`**: a symlink, not a separate binary. The agent calls `jackin-exec gh pr create`; the capsule subcommand shows the on-demand picker, resolves selected credentials via the host process, injects them as temp env vars, runs the command, scans output for leaked values, deletes temp values. Raw credential values never appear in the container's process environment.

This is the same architecture Docker Sandboxes uses for its host-side credential proxy — except jackin❯ builds it explicitly, with a TUI-native picker dialog and full operator control.

***

## Part 2: The Four-Layer Security Model [#part-2-the-four-layer-security-model]

The research trail produced four independent, complementary isolation layers. Each layer closes a gap the others cannot. All four are needed for the complete picture.

```
┌─────────────────────────────────────────────────────────────────┐
│  Layer 4: Network Egress Policy                                  │
│  (per session, domain allowlist, enforcement-quality reporting)  │
├─────────────────────────────────────────────────────────────────┤
│  Layer 3: jackin-exec Credential Injection                       │
│  (per command, secrets never in agent context)                   │
├─────────────────────────────────────────────────────────────────┤
│  Layer 2: Apple Container VM Boundary                            │
│  (per session, own kernel via Virtualization.framework)          │
├─────────────────────────────────────────────────────────────────┤
│  Layer 1: Docker Hardening Contract                              │
│  (per session, rootless DinD, capability policy, read-only root) │
├─────────────────────────────────────────────────────────────────┤
│  Cross-layer: Process-Level Sandboxing (zerobox)                 │
│  (per operation, filesystem + network + env restriction)         │
└─────────────────────────────────────────────────────────────────┘
```

### What Each Layer Closes [#what-each-layer-closes]

| Threat                                       | Without any layer                                  | Layer 1 (Docker hardening)              | Layer 2 (Apple Container VM)                 | Layer 3 (jackin-exec)              | Cross-layer (zerobox)      | Layer 4 (egress policy)      |
| -------------------------------------------- | -------------------------------------------------- | --------------------------------------- | -------------------------------------------- | ---------------------------------- | -------------------------- | ---------------------------- |
| DinD `--privileged` → kernel access          | ❌ open                                             | ✅ rootless DinD eliminates              | ✅ own kernel, --privileged blocked by design | —                                  | —                          | —                            |
| Kernel escape via CVE                        | ❌ open → reaches OrbStack VM kernel → all sessions | Partial (fewer caps, hardened profile)  | ✅ kernel escape reaches only this VM         | —                                  | —                          | —                            |
| One session reaching another session's state | ❌ shared OrbStack VM kernel                        | Partial                                 | ✅ separate kernel per session                | —                                  | —                          | —                            |
| Agent reads raw API key / SSH key            | ❌ env var visible                                  | ❌                                       | ❌                                            | ✅ jackin-exec never injects to env | ❌                          | —                            |
| Agent's tool call reads unintended file      | ❌                                                  | ❌                                       | ❌                                            | —                                  | ✅ per-op filesystem policy | —                            |
| Agent's tool call calls unintended endpoint  | Partial (per-agent network)                        | Partial (profile reporting)             | —                                            | —                                  | ✅ per-op network allowlist | ✅ session-level allowlist    |
| Agent exhausts CPU/memory/PIDs               | ❌                                                  | ✅ resource limits in `hardened` profile | —                                            | —                                  | —                          | —                            |
| Agent exfiltrates data over network          | ❌                                                  | Partial (reporting only)                | —                                            | —                                  | Partial (per-op deny)      | ✅ session allowlist enforced |
| Mutable root filesystem                      | ❌                                                  | ✅ read-only root in `hardened` profile  | —                                            | —                                  | —                          | —                            |

### The Tiers at a Glance [#the-tiers-at-a-glance]

```
Overhead    Granularity       Layer
─────────────────────────────────────────────────────────────────
< 10 ms     per operation     Process sandbox (zerobox + jackin-exec)
100–500 ms  per session       Container hardening (Docker profiles)
< 1 s       per session       Apple Container VM boundary
```

***

## Part 3: Why Apple Container, Not Docker Sandboxes [#part-3-why-apple-container-not-docker-sandboxes]

This comparison matters because Docker Sandboxes and Apple Container appear to address the same problem. They do not. Understanding the difference is essential for understanding why jackin❯ builds on Apple Container instead of integrating with Docker Sandboxes.

### What Docker Sandboxes Is [#what-docker-sandboxes-is]

Docker Sandboxes (launched January 2026) is a **complete agent runner**. It runs Claude Code, Codex CLI, GitHub Copilot CLI, and other supported agents in a dedicated microVM. Each sandbox has:

* A dedicated VM via a proprietary VMM (Hypervisor.framework on macOS)
* A built-in private Docker daemon
* A host-side credential proxy (secrets never enter the sandbox)
* A host-side network policy proxy (domain allowlist, raw TCP/UDP blocked)
* Explicit workspace mounts (same absolute host path)

Docker Sandboxes is designed to answer: "run this agent for me, safely." The operator hands the agent to Docker, and Docker manages the isolation, credentials, and network policy.

### What Apple Container Is [#what-apple-container-is]

Apple Container (`apple/container`, macOS 26 Tahoe) is a **VM primitive**. It runs any OCI container image in its own VM via Virtualization.framework. It provides:

* A VM per container with its own kernel
* An OCI-compatible run/exec/stop/rm/ps CLI
* A structured gRPC/vsock API via `vminitd` for I/O streaming and signal forwarding
* Per-container IP address via vmnet

Apple Container is designed to answer: "here is a VM primitive, build on it." jackin❯ builds its own credential proxy (jackin-exec), network policy (egress policy), session model, role system, and TUI on top of this primitive.

### Why jackin❯ Needs a Primitive, Not a Product [#why-jackin-needs-a-primitive-not-a-product]

jackin❯ is itself an orchestration layer. It manages roles, workspaces, session reconnect, TUI, multiple agent runtimes, and operator UX. Integrating with Docker Sandboxes would mean jackin❯ becomes subordinate to Docker's product decisions — operators would use Docker Sandboxes to run agents, and jackin❯ would have no role.

More concretely: Docker Sandboxes CLI (as of May 2026) has no events stream, no `--format json`, no per-sandbox stdout/log hooks. It is intentionally designed as an agent runner, not a backend API. It cannot serve as the programmatic substrate for jackin❯s lifecycle management.

### The Comparison Table [#the-comparison-table]

| Capability                                                   | Docker Sandboxes                        | jackin❯ + Apple Container (full stack)                |
| ------------------------------------------------------------ | --------------------------------------- | ----------------------------------------------------- |
| VM per session (own kernel)                                  | ✅ proprietary VMM                       | ✅ Virtualization.framework                            |
| Private Docker daemon (no `--privileged`)                    | ✅ built-in                              | ✅ rootless DinD inside VM (requires Docker hardening) |
| Credentials never in sandbox                                 | ✅ host-side credential proxy (built-in) | ✅ jackin-exec (jackin builds this)                    |
| Network domain allowlist                                     | ✅ host-side proxy (built-in)            | ✅ egress policy (jackin builds this)                  |
| Per-operation filesystem/network policy                      | ❌                                       | ✅ zerobox (jackin builds this)                        |
| TUI-native operator approval UI                              | ❌                                       | ✅ jackin❯ owns the terminal                           |
| Role system (Dockerfile-based)                               | ❌ fixed agent runners                   | ✅ full role authoring                                 |
| Session reconnect / eject / purge                            | ❌                                       | ✅                                                     |
| Multiple agent runtimes (Claude, Codex, Amp, Kimi, OpenCode) | 7 fixed                                 | ✅ unlimited                                           |
| Workspace-aware behavior                                     | ❌                                       | ✅                                                     |
| Operator-controlled secret bindings                          | ❌                                       | ✅ jackin-exec workspace bindings                      |
| macOS 26 install friction                                    | Requires Docker Desktop                 | ✅ zero — built into macOS 26                          |
| Open source (VM layer)                                       | ❌ proprietary VMM                       | ✅ `apple/container` (open source)                     |

**jackin❯ + Apple Container full stack reaches Docker Sandboxes security parity while preserving jackin❯s own operator experience.** Docker Sandboxes is the benchmark for what the security story should look like; Apple Container is the primitive jackin❯ uses to build that story on its own terms.

***

## Part 4: The Progressive Enhancement Path [#part-4-the-progressive-enhancement-path]

The full four-layer model is built incrementally. Each step is independently valuable. Operators benefit immediately from each layer as it lands.

### Today: Current Docker + OrbStack (Baseline) [#today-current-docker--orbstack-baseline]

```
macOS ARM → OrbStack Linux VM → Docker daemon → --privileged DinD + role container
```

Risks:

* DinD `--privileged` → kernel access to OrbStack VM
* Shared kernel → all sessions share one attack surface
* Credentials in env vars → agent can read raw API keys
* No per-operation access control
* Open network egress

### Step 1: Docker Hardening Contract (In Progress) [#step-1-docker-hardening-contract-in-progress]

```
macOS ARM → OrbStack Linux VM → Docker daemon → rootless DinD + role container
                                                  (capability policy, read-only root,
                                                   resource limits, profile reporting)
```

What changes:

* DinD sidecar moves to rootless mode (no `--privileged`) or uses minimal capability set
* `hardened` profile: `--cap-drop=ALL` + minimal caps, read-only root, resource limits
* Session contract output: operators see exactly what was enforced

What remains:

* Shared OrbStack VM kernel (structural)
* Credentials still in env vars
* No per-operation isolation
* Open egress

See: [Docker runtime hardening contract](/roadmap/docker-runtime-hardening-contract/)

### Step 2: Apple Container VM Boundary [#step-2-apple-container-vm-boundary]

```
macOS ARM → apple/container VM (own kernel, Virtualization.framework)
              → rootless DinD + role container + jackin-capsule
```

What changes:

* Each jackin❯ session gets its own Linux kernel via Apple's hypervisor
* Kernel exploit in one session cannot reach other sessions or the host
* OrbStack VM no longer in the critical path for session isolation
* Zero install friction on macOS 26 (built into the OS)
* gRPC/vsock attach via `vminitd` — structured I/O and signal forwarding for TUI sessions

What remains:

* Credentials still in env vars (jackin-exec not yet present)
* No per-operation isolation
* Open egress

**Prerequisite**: Docker hardening's rootless DinD must validate successfully inside apple/container VMs (specifically: does `CAP_SYS_ADMIN` work inside apple/container for rootless DinD mount namespaces?). This is the Phase 0 gate.

See: [smolvm backend research](/reference/research/isolation/smolvm-backend/) (contains the Apple Container comparison and Phase 0 plan)

### Step 3: jackin-exec Credential Injection [#step-3-jackin-exec-credential-injection]

```
macOS ARM → apple/container VM (own kernel)
              → rootless DinD + role container + jackin-capsule
                → agent calls: jackin-exec ssh sentry
                  → jackin-capsule intercepts
                  → operator approves in TUI (optional)
                  → SSH key resolved from host vault at execution time
                  → command runs with injected key (temp file, /jackin/run/)
                  → output scanned for secret patterns, redacted
                  → sanitized output returned to agent
                  → temp key file deleted
```

What changes:

* Agent never receives raw credential values in env vars or files
* Operator gets TUI-native approval dialog for sensitive commands
* Workspace secret bindings map command patterns to host-side vaults (`op://`, `env:`, `file:`)
* Output filtering redacts PEM blocks, AWS key patterns, configured regexes

What remains:

* Agent's general tool calls (npm install, etc.) still unconstrained inside container
* Open egress for non-jackin-exec commands

See: [Process-level sandboxing](/reference/research/security/process-sandboxing/process-level-sandboxing/) (jackin-exec design), [Container credential exposure](/reference/research/security/credential-exposure/container-credential-exposure/), [Host bridge](/roadmap/host-bridge/)

### Step 4: Process-Level Sandboxing (zerobox) + Network Egress [#step-4-process-level-sandboxing-zerobox--network-egress]

```
macOS ARM → apple/container VM (own kernel)
              → rootless DinD + role container + jackin-capsule
                → every agent tool call:
                    → zerobox: filesystem policy (declared mounts only)
                               network policy (declared hosts only)
                               env policy (no leaked secrets)
                    → jackin-exec: credential injection for sensitive commands
                → session-level egress policy: allowlist enforced at VM boundary
```

What changes:

* Every subprocess wrapped by zerobox: reads/writes only declared mount paths, reaches only declared network hosts, cannot see env vars not explicitly passed
* Session-level network allowlist enforced at VM egress
* Full audit trail: every operation, every allow/deny decision, logged to diagnostics run file

This is the complete picture. No remaining open risks in the standard macOS ARM + trusted-operator threat model.

See: [Process-level sandboxing](/reference/research/security/process-sandboxing/process-level-sandboxing/), [Network egress policy](/roadmap/network-egress-policy/)

***

## Part 5: What Each Layer Costs [#part-5-what-each-layer-costs]

Understanding the cost of each layer prevents premature optimization and guides sequencing.

| Layer                            | Operator friction                                                  | Implementation complexity                                                | Prerequisites                                              |
| -------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------ | ---------------------------------------------------------- |
| Docker hardening contract        | Low — profiles are opt-in, `compat` preserves today                | Medium — profiles, capability policy, rootless DinD research             | None — in progress                                         |
| Apple Container VM boundary      | Zero on macOS 26 (built-in)                                        | High — new backend abstraction, lifecycle API, Phase 0 empirical testing | Docker hardening (rootless DinD) must validate first       |
| jackin-exec credential injection | Low — system prompt instructs agent; approval dialog is contextual | Medium — binary, vsock protocol to capsule, workspace bindings schema    | jackin-capsule vsock/Unix socket extension                 |
| zerobox per-operation sandboxing | Low — transparent to agent                                         | Medium — zerobox in construct image, policy derivation from mounts       | Depends on zerobox compatibility inside apple/container VM |
| Network egress policy            | Low — deny/allowlist declarative                                   | Medium — egress policy schema, enforcement at VM boundary                | Apple Container VM boundary (egress enforced at VM level)  |

***

## Part 6: What Remains Open [#part-6-what-remains-open]

### Phase 0 Gate (Must Resolve Before Apple Container Implementation) [#phase-0-gate-must-resolve-before-apple-container-implementation]

The most critical open question is whether rootless DinD can run inside an apple/container VM:

1. Does apple/container allow `--cap-add CAP_SYS_ADMIN`? (needed for mount namespaces in rootless DinD)
2. Does rootless DinD pass `docker build`, Compose, and Testcontainers inside the apple/container VM?
3. Does jackin-capsule run correctly as non-PID-1 (`JACKIN_CAPSULE_FORCE_DAEMON=1`) with proper SIGTERM propagation, exit-code visibility, and Ctrl+C passthrough?

If rootless DinD fails inside apple/container: smolvm is the fallback (documented Docker-in-VM path exists, though constrained). See [smolvm backend research](/reference/research/isolation/smolvm-backend/) for the full fallback plan.

### jackin-exec Design Decisions [#jackin-exec-design-decisions]

1. **Binary name**: `jackin-exec` proposed — needs final decision before baking into construct image (renaming later breaks existing role system prompts and MCP tool descriptions)
2. **MCP vs binary vs PATH-shadowing**: binary + MCP recommended; PATH-shadowing noted but not recommended (lacks transparency)
3. **Approval UX for high-frequency sessions**: "Approve All Similar" and "Always for Session" modes need TUI design — see [TUI design decisions](/reference/tui/)

### Known Apple Container Limitations (v0.11.0) [#known-apple-container-limitations-v0110]

| Limitation                                    | Status                       | Impact                                                                |
| --------------------------------------------- | ---------------------------- | --------------------------------------------------------------------- |
| `--privileged` not supported                  | By design (use `--cap-add`)  | Requires rootless DinD — the Phase 0 gate                             |
| Multi-container bridge networking rough edges | Upstream v0.11.0 known issue | Affects DinD inner container networking; monitor for fix              |
| DNS hiccuping after macOS sleep/wake          | Upstream v0.11.0 known issue | Operator must reconnect after sleep; jackin❯ should detect and prompt |
| No health checks (`--health-cmd`)             | Not implemented              | jackin-capsule liveness probes instead                                |
| Apple Silicon only                            | By design                    | Acceptable — jackin❯ is macOS ARM only                                |

***

## Part 7: The Threat Model This Architecture Addresses [#part-7-the-threat-model-this-architecture-addresses]

This architecture is designed for jackin❯s current threat model: a **trusted operator running semi-trusted AI agents against potentially untrusted external code** on a personal macOS ARM machine. It is explicitly NOT designed for:

* Hosted or multi-tenant workloads (strangers' code running on shared infrastructure)
* Enterprise regulatory compliance (HIPAA, PCI-DSS) where third-party audited attestations are required
* Adversarial operators trying to escape the sandbox themselves

For the current threat model, the four layers close the practical failure modes:

| Failure mode                                  | Closed by                                   |
| --------------------------------------------- | ------------------------------------------- |
| Agent exploits kernel CVE to escape container | Apple Container VM boundary                 |
| Agent reads secret injected as env var        | jackin-exec credential injection            |
| Agent writes to wrong mounted path            | zerobox per-operation policy                |
| Agent calls unexpected network endpoint       | zerobox + egress policy                     |
| Agent runs code that exhausts CPU/memory      | Docker hardening resource limits            |
| Agent exfiltrates data to unexpected host     | Egress policy session allowlist             |
| Agent remembers raw API key across prompts    | jackin-exec (key never in context)          |
| DinD privilege escalation to host kernel      | Apple Container VM boundary + rootless DinD |

***

## Part 8: Implementation Sequence [#part-8-implementation-sequence]

Work proceeds in this order. Each step is a prerequisite for the next where noted.

```
1. Docker runtime hardening contract (in progress, another agent)
   └─ Gate: rootless DinD must validate on macOS ARM + OrbStack
   └─ Also delivers: capability policy, read-only root, resource limits, session contract output
   └─ These improvements benefit operators immediately, regardless of backend

2. Apple Container Phase 0 (empirical, after rootless DinD validates)
   └─ Gate: does rootless DinD work inside apple/container VM?
   └─ Does jackin-capsule run as non-PID-1 with correct signal behavior?
   └─ Does interactive TUI session attach work via vminitd gRPC/vsock?
   └─ If PASS → Apple Container Phase 1-5 (backend adapter implementation)
   └─ If FAIL → smolvm Phase 0 (fallback, Docker-inside via documented TSI recipe)

3. jackin-exec (parallel with or after Apple Container Phase 0)
   └─ Can start before Apple Container lands — works on current Docker backend too
   └─ Requires jackin-capsule vsock/Unix extension for wrapper ↔ capsule communication
   └─ Delivers credential isolation for current operators immediately

4. Network egress policy (after Apple Container or smolvm backend lands)
   └─ Enforced at VM egress boundary — more reliable than Docker network tricks
   └─ See: [Network egress policy](/roadmap/network-egress-policy/)

5. zerobox per-operation sandboxing (after jackin-exec, parallel with egress)
   └─ Works inside current Docker backend too — no backend dependency
   └─ Compatibility testing needed: does zerobox work inside apple/container VM?
   └─ See: [Process-level sandboxing](/reference/research/security/process-sandboxing/process-level-sandboxing/)
```

***

## Related Files [#related-files]

The key source files an implementing agent reads before touching this architecture:

* <RepoFile path="crates/jackin-capsule/src/main.rs" /> — PID-1 detection and `JACKIN_CAPSULE_FORCE_DAEMON` dispatch for Apple Container
* <RepoFile path="crates/jackin-capsule/src/daemon.rs" /> — daemon control plane and jackin-exec picker dispatch
* <RepoFile path="crates/jackin-instance/src/manifest.rs" /> — `InstanceManifest`, `DockerResources`, and `BackendResources` with `AppleContainerResources`
* <RepoFile path="crates/jackin-runtime/src/runtime/launch.rs" /> — launch orchestration; backend split point
* <RepoFile path="crates/jackin-docker/src/docker_client.rs" /> — Docker lifecycle boundary; Apple Container gets a peer module
* <RepoFile path="docker/construct/Dockerfile" /> — role base image; install `jackin-exec` and `zerobox` here
* <RepoFile path="docker/runtime/entrypoint.sh" /> — capsule startup inside role container; inject `JACKIN_EXEC_BINDINGS` env var
* <RepoFile path="crates/jackin-config/src/schema.rs" /> — `AppConfig` + `WorkspaceConfig` runtime backend fields
* <RepoFile path="crates/jackin-core/src/env_value.rs" /> — `EnvValue::Extended` and `OpRef.on_demand` for jackin-exec

## Related Roadmap Items [#related-roadmap-items]

| Item                                                                                                             | Role in this architecture                                                                                                              |
| ---------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| [Docker runtime hardening contract](/roadmap/docker-runtime-hardening-contract/)                                 | Layer 1 — prerequisite for Apple Container (rootless DinD must validate). Independently valuable for current Docker backend operators. |
| [Apple Container backend](/roadmap/apple-container-backend/)                                                     | Layer 2 — dedicated item with Phase 0-4, `AppleContainerResources` struct, schema migration, `JACKIN_CAPSULE_FORCE_DAEMON` code task.  |
| [jackin-exec](/roadmap/jackin-exec/)                                                                             | Layer 3 — dedicated item with workspace secret bindings schema migration, implementation phases, MCP tool spec, operator approval UI.  |
| [Process-level sandboxing](/reference/research/security/process-sandboxing/process-level-sandboxing/)            | Cross-layer — zerobox per-operation filesystem/network sandboxing only (jackin-exec is separate).                                      |
| [Network egress policy](/roadmap/network-egress-policy/)                                                         | Layer 4 — session-level outbound policy, enforced at VM egress when Apple Container backend lands.                                     |
| [Container credential exposure](/reference/research/security/credential-exposure/container-credential-exposure/) | The problem that jackin-exec (Layer 3) solves.                                                                                         |
| [Host bridge — secrets and approved host actions](/roadmap/host-bridge/)                                         | Host-side resolver that jackin-exec calls for `op://` credentials.                                                                     |
| [Session contract and explain mode](/roadmap/session-contract-explain-mode/)                                     | How the operator sees which layers are active and what residual risks remain.                                                          |
| [Selectable sandbox backends](/reference/research/security/sandbox-backends/selectable-sandbox-backends/)        | Umbrella for Docker and Apple Container as the two runtime families; backend selection model, instance registry design.                |
| [smolvm backend research](/reference/research/isolation/smolvm-backend/)                                         | Deferred — fallback if Apple Container Phase 0 fails Docker-inside test.                                                               |
| [OrbStack isolated machine backend](/reference/research/isolation/orbstack-isolated-machines/)                   | Deferred — shared-kernel namespace, not hypervisor boundary. Historical research preserved.                                            |
