AI Security Architecture

Sandboxing AI Coding Agents: Filesystem, Process, Network, and Credential Isolation

A deeply technical architecture for isolating AI coding agents with disposable workspaces, kernel controls, brokered capabilities, and escape testing.

Code agents combine hostile input with execution

An AI coding agent consumes repository content, issue text, dependency metadata, compiler output, web pages, and tool results. Any of those inputs can be attacker-controlled. The agent then writes files, launches processes, installs packages, executes tests, opens network connections, and may interact with source control or deployment systems.

The correct security assumption is:

Everything inside the task workspace, including generated commands and repository instructions, may be hostile. The sandbox must enforce the task's authority without relying on the model to recognize malicious content.

A container is useful isolation, but “runs in a container” is not a complete design. A secure coding-agent runtime combines filesystem scoping, process isolation, kernel attack-surface reduction, resource limits, network mediation, credential brokering, artifact controls, and reliable teardown.

Define assets and attacker capabilities

Protect:

  • Host filesystem and other workspaces.
  • Source-control, cloud, package-registry, and model-provider credentials.
  • Other users' repositories and task data.
  • Build and deployment systems.
  • Internal network services and cloud metadata.
  • Signing keys and release artifacts.
  • Sandbox controller and policy service.
  • Security evidence and task provenance.

Assume the attacker can influence:

  • Source files, build scripts, tests, Makefiles, package hooks, and repository configuration.
  • Symlinks, hard links, submodules, archives, and generated paths.
  • Issue descriptions and agent instruction files.
  • Dependency names, packages, and registry responses.
  • Compiler, linter, test, and tool output.
  • Model proposals and retries.

Depending on the deployment, also assume the submitted repository may contain native code designed to attack the kernel or container runtime.

Separate the control plane from the execution plane

The sandbox controller should not run inside the environment it governs.

task request
  --> trusted controller + policy
       --> materialize immutable inputs
       --> create isolated execution environment
       --> issue narrow capabilities
       --> observe events and limits
       --> collect approved outputs
       --> destroy environment

model + tools run only inside execution environment

The execution environment cannot modify its policy, grant itself mounts, create more privileged sandboxes, or write to the controller's queue. Control messages use an authenticated channel with a narrow schema.

Do not mount the host container socket, orchestration API credential, or sandbox-manager socket. Access to a container runtime control socket is commonly equivalent to host-level authority.

Give every task a disposable identity and workspace

Create a fresh sandbox per task or per explicitly related task group. Bind:

  • Task and user identifier.
  • Repository and immutable input revision.
  • Allowed paths and write set.
  • Network policy.
  • Resource budget.
  • Toolchain image digest.
  • Credential capability set.
  • Start, expiry, and maximum lifetime.

Copy or snapshot input into a task-owned filesystem. Avoid sharing a writable Git working tree between tasks. On completion, export only declared artifacts, then destroy the environment and revoke all capabilities.

Persistent caches require separate trust decisions. Package caches and compiler caches can leak source content or carry poisoned artifacts between users. Partition by trust domain, verify content, make shared caches read-only to workers, and never store task credentials in them.

Design the filesystem boundary

Start with no host filesystem access. Add explicit mounts:

Path classModePurpose
Toolchain imageRead-onlyCompilers, interpreters, utilities
Repository snapshotCopy-on-writeTask source and generated changes
ScratchWritable, size-limitedBuilds and tests
Dependency cacheRead-only or brokeredVerified reusable artifacts
Export directoryWrite-only or mediatedDeclared final artifacts
Host home and secretsNot mountedNever ambient

Resolve paths beneath a trusted directory using APIs designed to prevent traversal and symlink races. Validate archive extraction against absolute paths, .., symlinks, hard links, devices, and decompression limits. A check-then-open sequence on a mutable path is vulnerable to time-of-check/time-of-use races.

Mount the root filesystem read-only when practical. Use a separate writable overlay with quotas. Deny device nodes, procfs writes, kernel interfaces, and sensitive pseudo-filesystems. Ensure cleanup handles open file descriptors and background processes.

Never bind-mount an operator's home directory for convenience.

Run without host root

Inside-container root can still exercise a large kernel and runtime attack surface. Use an unprivileged host UID and, where supported, user namespaces so container IDs map to non-privileged host IDs.

Apply:

  • No privileged mode.
  • No host PID, network, IPC, user, cgroup, or mount namespaces.
  • No host devices.
  • Drop all Linux capabilities, adding only a documented minimum.
  • no_new_privileges.
  • Non-root process user.
  • Restricted proc and sys mounts.
  • Read-only runtime configuration.

Docker rootless mode runs the daemon and containers without root privileges except for the narrow UID/GID mapping helpers it documents. Rootless operation reduces daemon compromise impact but does not replace application sandboxing, network policy, or kernel hardening.

For Kubernetes execution, use the Restricted Pod Security Standard as a baseline and isolate untrusted workloads from privileged node agents.

Reduce the syscall and kernel-object surface

Linux seccomp filters restrict system calls. The kernel seccomp documentation explicitly states that syscall filtering is not a complete sandbox; it reduces exposed kernel surface and must be combined with other controls.

Build profiles from the required toolchain, then remove capabilities rather than maintaining a blacklist of known-dangerous calls. Be careful with language runtimes, debuggers, sanitizers, and build tools that legitimately need complex behavior.

Test that the sandbox denies or mediates operations involving:

  • Mounting and namespace creation.
  • Kernel module and BPF operations.
  • Raw sockets and unusual network families.
  • Device access.
  • Process tracing outside the task.
  • Keyrings and privileged credential changes.
  • Reboot and system administration.

Check syscall architecture when defining filters. The kernel documentation warns that system-call numbers can differ across supported ABIs.

Use a Linux Security Module for object-level policy. Landlock can add unprivileged restrictions to filesystem and supported network access. AppArmor or SELinux can provide centrally managed mandatory policy. These mechanisms compose with discretionary permissions and seccomp; each protects a different boundary.

Use stronger isolation for hostile native code

Containers share the host kernel. For code from untrusted third parties or public repositories, consider a microVM, dedicated virtual machine, or sandboxed runtime that places another security boundary between guest code and the host kernel.

Choose based on risk:

WorkloadReasonable starting boundary
First-party code with no executionRestricted process and filesystem sandbox
First-party tests and buildsRootless container with kernel and network controls
External pull request with native buildStrongly isolated container runtime or microVM
Public arbitrary repositoryDisposable microVM or dedicated worker pool
Security research or exploit fixturesDedicated isolated hosts with no sensitive connectivity

Isolation technology has vulnerabilities. Patch kernels and runtimes, minimize host services, rotate worker images, and separate high-risk pools from production networks and credentials.

Do not silently fall back to a weaker boundary when a preferred sandbox is unavailable. Fail the task or require an explicit policy decision.

Bound resource consumption with cgroup v2

Generated code can fork, allocate, write, and compute without limit. Use cgroup v2 and filesystem quotas to bound:

  • CPU time and weight.
  • Memory high and hard maximum.
  • Process count.
  • I/O bandwidth and operations.
  • Task wall-clock time.
  • Scratch and output storage.
  • Network bytes and connections.
  • Model tokens and external API spend.

The kernel cgroup v2 documentation describes hierarchical CPU, memory, process, and I/O controls. Place the entire process tree in the task cgroup before execution so children inherit limits.

Termination should kill the cgroup, not one PID. Otherwise detached grandchildren and daemons can survive. Record which limit triggered and preserve bounded diagnostic evidence.

Protect the host from disk inode exhaustion, page-cache pressure, log floods, core dumps, and large sparse files in addition to ordinary byte quotas.

Deny network by default

Most local editing and static analysis does not need external network access. Begin with no network interface or a default-deny policy.

For tasks that need dependencies or tests:

  • Route package requests through an authenticated, caching broker.
  • Allow only approved registries and repository hosts.
  • Block private, loopback, link-local, metadata, and management ranges.
  • Revalidate DNS and redirects.
  • Restrict protocols, ports, bytes, time, and destinations.
  • Remove proxy credentials from the sandbox.
  • Record destination identity and artifact digest.

Do not grant broad internet access simply because a package manager may need it. Pre-resolve lockfiles and fetch dependencies in a separate supply-chain stage where possible.

Inbound network should be absent by default. When tests require listeners, keep them inside the sandbox network namespace and expose only to an instrumented test peer. Avoid publishing ports on the host.

DNS is both an egress path and a source of nondeterminism. Route it through policy and bound query volume.

Broker credentials instead of mounting secrets

The agent should not receive a general source-control token, cloud profile, SSH directory, signing key, or package-registry credential.

Use a broker that accepts a typed request and performs one operation:

{
  "capability": "read_repository_object",
  "task_id": "task-817",
  "repository_id": "repo-42",
  "object_id": "commit-sha",
  "purpose": "materialize authorized task input"
}

The broker authenticates the task sandbox, checks policy, executes outside it, and returns a bounded artifact. For write operations, require explicit approval bound to the exact diff, repository, branch, and base revision.

If an in-sandbox token is unavoidable, make it short-lived, audience-restricted, operation-scoped, non-refreshable, and unusable from other network destinations. Do not place it in environment variables visible to every subprocess if a narrow file descriptor or helper protocol can provide the capability.

Rotate and revoke on task completion. Scan exported logs and artifacts for credential canaries.

Control source-control writes

Separate editing from publishing:

  1. Agent edits a disposable workspace.
  2. Trusted controller computes and validates the diff.
  3. Security policy rejects changes outside allowed paths or generated artifacts.
  4. Tests run in a clean environment against the exact candidate tree.
  5. Human or workflow approval binds repository, base commit, diff digest, and target branch.
  6. A broker creates a branch or proposal using a narrow identity.

Do not let the agent rewrite protected history, alter branch protections, approve its own change, or push directly to production branches. Repository configuration, CI workflows, ownership files, dependency manifests, and security policy may require stronger approval than ordinary source files.

Symlinks and submodules can make a displayed diff misleading. Compute paths and content from a trusted repository implementation outside the hostile workspace.

Treat build and test output as hostile

Build systems execute repository-controlled code. Tests can print terminal escapes, forge familiar log prefixes, create hyperlinks, write artifacts, and emit prompt injection aimed at the agent or reviewer.

Controls include:

  • Structured result envelopes separating trusted status from raw output.
  • Output byte and line limits.
  • Terminal-control sanitization in UIs.
  • No interpretation of log text as policy or approval.
  • Artifact type, size, and path validation.
  • Malware and secret scanning for exported binaries and archives.
  • Provenance linking artifacts to source, toolchain, and sandbox image.

A passing test is a data point, not permission to publish. The controller decides which checks are required and validates their signed results.

Secure dependency installation

Package installation is arbitrary code execution in many ecosystems because lifecycle hooks, build backends, plugins, and compilers run during resolution or installation.

Prefer:

  • Lockfiles with exact versions and integrity.
  • Internal mirrors or verified upstream sources.
  • Download and verification outside the execution sandbox.
  • Installation with lifecycle scripts disabled when compatible.
  • Separate build sandbox for source packages.
  • Dependency provenance and bill of materials.
  • No repository credentials in package-manager configuration.

The sandbox still assumes dependencies may be malicious. Supply-chain validation and runtime containment are complementary.

Test dependency confusion with inert names in a private lab registry, not public namespaces. Verify registry selection, namespace ownership, lock enforcement, redirect handling, and cache partitioning.

Design output promotion as a trust transition

Nothing leaves the sandbox automatically. Define export types:

  • Text diff.
  • Source archive.
  • Test report.
  • Compiled artifact.
  • Coverage or analysis data.

For each type, enforce path, size, format, symlink, ownership, and content policy. Recreate archives using a trusted exporter rather than accepting an agent-built archive that may contain traversal paths or device nodes.

Rebuild release artifacts in a separate trusted pipeline from reviewed source. Do not promote a binary merely because the coding-agent sandbox produced it. Attach provenance and scan results to candidate artifacts.

Instrument the security boundary

Record:

  • Task, user, repository, and input revision.
  • Sandbox image, kernel, runtime, policy, and toolchain versions.
  • Mounts and filesystem grants.
  • Network and credential capability decisions.
  • Processes, resource-limit events, and sandbox denials.
  • Dependency artifacts and digests.
  • Exported diff and artifact digests.
  • Approval and source-control operations.
  • Teardown and revocation completion.

Avoid full command output collection by default when it may contain source or secrets. Store protected raw artifacts only for tasks whose retention policy permits it.

The model's reasoning transcript is not reliable security evidence. OS, broker, network, and source-control events are authoritative for effects.

Test the sandbox adversarially

Create a dedicated escape corpus with inert canaries outside each boundary:

  • Host and neighboring-workspace file canaries.
  • Read-only input mutation checks.
  • Symlink and archive traversal fixtures.
  • Process and namespace isolation checks.
  • Denied syscall and device probes.
  • Cgroup process, memory, CPU, disk, and timeout exhaustion.
  • Private network, metadata, DNS, and redirect canaries.
  • Credential-broker scope and replay tests.
  • Runtime-socket and orchestration-API denial.
  • Background-process survival after teardown.
  • Exported artifact path and format attacks.

Run tests at the OS boundary without an LLM first. Then add repository instructions and tool output designed to induce the agent to challenge the same controls. A secure result is a denied effect with complete evidence, even when the model repeatedly proposes it.

Test kernel and runtime upgrades before promotion. Sandbox security can regress when default seccomp profiles, user namespace support, network plugins, or mount behavior changes.

A secure coding-agent workflow

  1. Authenticate the user and authorize the repository and task purpose.
  2. Resolve an immutable source revision.
  3. Select a sandbox class based on code trust and execution need.
  4. Materialize inputs without credentials.
  5. Apply filesystem, process, kernel, network, and resource policy.
  6. Run the model and tools with brokered capabilities only.
  7. Capture authoritative effect telemetry and bounded output.
  8. Compute the candidate diff outside the hostile workspace.
  9. Run clean verification against the exact candidate tree.
  10. Bind approval to the diff and destination.
  11. Publish through a narrow source-control broker.
  12. Revoke capabilities, destroy the sandbox, and verify teardown.

This architecture applies the secure tool invocation boundary at the operating-system level. The AI pentesting harness uses similar separation between model planning, deterministic execution, evidence, and approval. Security architecture should select the isolation class based on the organization's actual code and credential exposure.

Sources and further reading

Turn research into assurance

Need a controlled security assessment?

AI-Adversary helps teams design, execute, and validate security testing for applications, AI systems, and automation workflows.