Skip to content

Security Model

jackin’ provides a container boundary, not a microVM boundary.

That distinction matters.

jackin’ is useful when you trust the agent runtime itself but want to limit what it can touch on your machine. It is not the right tool to claim hypervisor-level isolation or to contain a fully hostile workload.

If you need the hardest local isolation boundary available today, a microVM-based tool such as Docker Sandboxes is stronger by design.

jackin’s security model is built on several layers that stack together:

Each agent runs in its own Docker container with:

  • a separate filesystem
  • a separate process space
  • a separate Docker network

The agent cannot see arbitrary host files unless you mount them.

The agent can only access host paths you explicitly mount.

Terminal window
# Agent can read/write ~/Projects/my-app
# Agent can read but not write ~/reference
# Agent cannot see ~/.ssh, ~/.aws, ~/Documents, or other host paths
jackin load agent-smith ~/Projects/my-app --mount ~/reference:/reference:ro

This is the core blast-radius control in jackin’.

Mounts marked :ro are enforced by Docker and the kernel. The agent cannot write to those paths, regardless of Claude Code permissions.

Each runtime gets its own Docker network. The agent container and its DinD sidecar share that network, but different agents do not share a network by default.

This reduces accidental cross-agent interference.

Inside their boundary, agents have broad autonomy:

  • execute arbitrary shell commands
  • install packages with apt, npm, pip, and similar tools
  • build and run containers through their DinD sidecar
  • modify files inside writable mounts
  • access the internet
  • use gh if authenticated inside the runtime
  • access files that are not mounted
  • modify files on read-only mounts
  • directly access your host Docker daemon
  • directly see another agent’s container or persisted state

These guarantees are useful, but they are not absolute in the face of a kernel escape or Docker escape vulnerability.

jackin’ remaps the container user to your host UID and GID. That means:

  • files created in mounted directories are owned by your host user
  • you avoid common permission conflicts after the agent edits files
  • the main runtime process does not run as root

jackin’ persists state at ~/.jackin/data/<container-name>/. Today that includes:

  • .claude/
  • .claude.json
  • .config/gh/
  • plugins.json

That means Claude conversation state and gh state can survive across sessions.

But several important things do not persist:

  • the mutable root filesystem of the runtime container
  • packages installed interactively into the running container
  • DinD images and containers created during that session

This is a deliberate trade-off. jackin’ is biased toward reproducible agent images and explicit workspace mounts, not long-lived mutable sandboxes.

These are the parts of the security story that should be stated bluntly.

jackin’ launches a privileged docker:dind sidecar per agent. The agent talks to it over plain TCP inside the per-agent network.

That keeps the agent away from your host Docker daemon, which is good. But it is still a privileged sidecar, and DinD TLS is not implemented yet.

jackin’ does not currently provide per-agent allowlists, denylists, private-network blocking, or request logs for outbound traffic.

If an agent can read a mounted secret and the network path is open, jackin’ cannot stop exfiltration.

Mounted files are live host files. If the agent edits a mounted path, the host file changes immediately. There is no snapshot or rollback layer between the runtime and the mount.

Credentials obtained inside the runtime remain inside the runtime

Section titled “Credentials obtained inside the runtime remain inside the runtime”

jackin’ does not mount host credentials by default, which is good.

But if you authenticate a tool like gh inside the runtime, that credential becomes readable by that runtime and persists in jackin’ state until you purge it.

jackin’ is designed to reduce the most common operator risks:

ThreatMitigationResidual risk
Agent reads unrelated host filesOnly mounted paths are visibleSensitive data inside mounted paths is still readable
Agent edits system filesRuntime filesystem is isolatedWritable host mounts still change immediately
Agent reaches host Docker daemonAgent uses its own DinD sidecarDinD sidecar itself is privileged
Agent interferes with another agentSeparate containers, networks, and stateShared host kernel remains a common lower layer
Agent persists random system changesRuntime root filesystem is ephemeralPersisted tool state and mounted files still survive
  • Container escape vulnerabilities — containers share the host kernel
  • Kernel-level exploits — there is no hypervisor boundary
  • Network exfiltration — outbound access is open by default
  • Credentials stored inside the runtime — if you log in inside the container, the agent can potentially read what that tool stores
  • Host-file mistakes inside writable mounts — if you give an agent write access to a project, it can delete or rewrite that project
  1. Mount the minimum necessary. Smaller visibility is the biggest win.
  2. Prefer read-only mounts. If the agent only needs to inspect something, mount it as :ro.
  3. Do not mount credential directories. Avoid ~/.ssh, ~/.aws, ~/.gnupg, and similar paths.
  4. Treat runtime login as sensitive. If you authenticate inside the runtime, assume the agent can read that state.
  5. Review agent repos before loading. The Dockerfile defines what the runtime contains.
  6. Split agent classes by scope. Keep frontend, backend, infra, and review workflows in separate environments when appropriate.
  7. Use jackin purge when a runtime no longer needs its persisted state.
  8. Keep Docker updated. Container isolation is only as strong as the Docker runtime underneath it.