Agent isolation layer contracts and open questions
Defines layer contracts, residual risks, validation gates, threat scope, code touchpoints, and owning research or roadmap work.
Summary
Each layer has an independent contract, technical dependencies, and residual risks; the architecture remains bounded to a trusted-operator, semi-trusted-agent threat model.
Question and scope
What does each layer change, what remains open, which failure modes are covered, and where are the relevant implementation seams?
Method
This chapter derives constraints from the threat evidence and four-layer model while leaving delivery state to Roadmap.
Findings
Each layer independently narrows a different risk class; the full model composes their contracts.
Docker baseline
macOS ARM → OrbStack Linux VM → Docker daemon → --privileged DinD + role containerRisks:
- 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
Docker hardening contract
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 hardenedprofile:--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
Per-session VM boundary
macOS ARM → apple/container VM (own kernel, Virtualization.framework)
→ rootless DinD + role container + jackin-capsuleWhat 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 an empirical compatibility gate.
See: smolvm backend research (contains the Apple Container comparison and compatibility constraints)
On-demand 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 deletedWhat 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 (jackin-exec design), Container credential exposure, Host bridge
Process sandboxing and 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 boundaryWhat 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
Together these layers address the enumerated failure modes for a trusted operator running semi-trusted agents; the limitations below remain explicit.
See: Process-level sandboxing, Network egress policy
Analysis
The operator cost, engineering scope, and technical dependencies differ by layer.
| Layer | Operator friction | Engineering scope | Design dependencies |
|---|---|---|---|
| Docker hardening contract | Low — profiles are opt-in, compat preserves today | Medium — profiles, capability policy, rootless DinD validation | None |
| Apple Container VM boundary | Zero on macOS 26 (built-in) | High — new backend abstraction, lifecycle API, empirical compatibility 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) |
Threat model
This architecture is designed for jackin❯'s 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 |
Code touchpoints
The key implementation seams for this architecture are:
crates/jackin-capsule/src/main.rs— PID-1 detection andJACKIN_CAPSULE_FORCE_DAEMONdispatch for Apple Containercrates/jackin-capsule/src/daemon.rs— daemon control plane and jackin-exec picker dispatchcrates/jackin-instance/src/manifest.rs—InstanceManifest,DockerResources, andBackendResourceswithAppleContainerResourcescrates/jackin-runtime/src/runtime/launch.rs— launch orchestration; backend split pointcrates/jackin-docker/src/docker_client.rs— Docker lifecycle boundary; Apple Container gets a peer moduledocker/construct/Dockerfile— role base image; installjackin-execandzeroboxheredocker/runtime/entrypoint.sh— capsule startup inside role container; injectJACKIN_EXEC_BINDINGSenv varcrates/jackin-config/src/schema.rs—AppConfig+WorkspaceConfigruntime backend fieldscrates/jackin-core/src/env_value.rs—EnvValue::ExtendedandOpRef.on_demandfor jackin-exec
Implications for jackin❯
Keep roadmap delivery state separate from this architecture. Validate compatibility gates empirically and expose active layers and residual risk through the session contract.
Limitations and unknowns
Apple Container compatibility gate
The most critical open question is whether rootless DinD can run inside an apple/container VM:
- Does apple/container allow
--cap-add CAP_SYS_ADMIN? (needed for mount namespaces in rootless DinD) - Does rootless DinD pass
docker build, Compose, and Testcontainers inside the apple/container VM? - 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 for the full fallback plan.
jackin-exec design decisions
- Binary name:
jackin-execproposed — needs final decision before baking into construct image (renaming later breaks existing role system prompts and MCP tool descriptions) - MCP vs binary vs PATH-shadowing: binary + MCP recommended; PATH-shadowing noted but not recommended (lacks transparency)
- Approval UX for high-frequency sessions: "Approve All Similar" and "Always for Session" modes need TUI design — see TUI design decisions
Apple Container limitations at the cutoff
| Limitation | Current constraint | Impact |
|---|---|---|
--privileged not supported | By design (use --cap-add) | Requires rootless DinD — the compatibility 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 |
Sources
Related work
| Item | Role in this architecture |
|---|---|
| Docker runtime hardening contract | Layer 1 — prerequisite for Apple Container (rootless DinD must validate). Independently valuable for current Docker backend operators. |
| Apple Container backend | Layer 2 — dedicated item owns the VM-backend contract, AppleContainerResources, schema work, and JACKIN_CAPSULE_FORCE_DAEMON behavior. |
| jackin-exec | Layer 3 — owns workspace secret bindings, the MCP/tool contract, and operator approval UI. |
| Process-level sandboxing | Cross-layer — zerobox per-operation filesystem/network sandboxing only (jackin-exec is separate). |
| Network egress policy | Layer 4 — session-level outbound policy, enforced at VM egress when Apple Container backend lands. |
| Container credential exposure | The problem that jackin-exec (Layer 3) solves. |
| Host bridge — secrets and approved host actions | Host-side resolver that jackin-exec calls for op:// credentials. |
| Session contract and explain mode | How the operator sees which layers are active and what residual risks remain. |
| Selectable sandbox backends | Umbrella for Docker and Apple Container as the two runtime families; backend selection model, instance registry design. |
| smolvm backend research | Open fallback candidate if Apple Container fails Docker-inside compatibility. |
| OrbStack isolated machine backend | Shared-kernel comparison that explains why namespace isolation is not a hypervisor boundary. |