An AI agent that writes Python, invokes a shell or opens a downloaded file is not merely producing content. It is proposing instructions to a runtime that can read, change, consume and transmit real resources. A well-worded system prompt may reduce unwanted behaviour, but it cannot revoke a kernel call, hide a credential already present in the environment or stop a process that has exhausted the host.
The release decision is therefore concrete: what must remain impossible even when the generated code, its inputs and every package it loads are treated as hostile? The answer should determine the execution boundary, not the convenience of the orchestration framework.
The UK National Cyber Security Centre's August 2026 agentic AI risk guidance recommends sandboxing that controls local and network resources, with stronger isolation as consequence rises. This field guide turns that direction into an operating contract. Source documentation establishes the properties of the mechanisms; the selection framework and release gates below are AIEngine analysis.
Start with the consequence, not the container
Generated code can be wrong without being malicious. It can recurse through a large directory, follow a symbolic link, import a package with installation hooks, print secrets from environment variables, make an unexpected HTTP request, create too many processes or leave a file that a later job trusts. Prompt injection adds another path: an untrusted document can influence the model that writes the commands.
OWASP's Improper Output Handling entry treats model output as untrusted input to downstream components. It identifies shell execution, generated SQL, paths and interpreted browser content as separate injection surfaces. Sandboxing is needed when arbitrary computation is useful; it does not replace context-specific validation before a model output becomes a command, query, path or published artefact. The five validation gates for safe action still apply at the boundary where an effect is committed.
Name the unacceptable outcomes before selecting a runtime:
- reading another customer, repository, job or host file;
- reaching an unapproved service, metadata endpoint or internet destination;
- acquiring a reusable credential or impersonating the orchestrator;
- changing the base image, policy, launcher or evidence collector;
- consuming enough CPU, memory, processes, disk, I/O or time to harm neighbours;
- persisting executable state into the next task; and
- producing an artefact that escapes review because it came from a “safe” sandbox.
A boundary is useful only if it prevents the named outcome independently of the model's cooperation.
Write the sandbox contract before choosing technology
“Runs in a sandbox” is not a testable requirement. Write one profile for each workload class. A read-only calculator, a spreadsheet-analysis job, a software-build agent and an autonomous security tester do not need the same permissions.
| Contract dimension | State explicitly | Evidence at release |
|---|---|---|
| Code | Interpreters, native execution, child processes, package installation | Allowed executable digest and blocked-call tests |
| Filesystem | Read-only inputs, writable scratch, output path, devices and host mounts | Mount manifest plus traversal and link tests |
| Network | Protocol, destination, port, DNS path, redirects and inbound reachability | Egress policy and denied-flow logs |
| Identity | Sandbox identity, brokered service actions and credential lifetime | Token audience, scope and issuance record |
| Resources | Wall time, CPU, memory, process count, disk, I/O and output size | Enforced limits and exhaustion results |
| Lifetime | One task, one user, reset method, cache rules and deletion point | Fresh-instance proof and residue test |
| Evidence | Events recorded outside the guest and data excluded from logs | Immutable audit sample and retention rule |
For every row, distinguish not mounted, not reachable, denied by policy and merely absent in the happy path. Only the first three can support a containment claim. An empty environment variable is not proof that a future launcher will not inject it.
Isolation layers stop different failures
The NCSC's current maturity model separates no compute isolation, same-host kernel controls such as properly configured OCI containers, same-host virtualisation, and dedicated hardware. It explicitly notes residual kernel-breakout risk at the container level. NIST's Application Container Security Guide likewise treats container security as an architecture spanning images, registries, orchestrators, containers and hosts rather than a property created by packaging alone.
| Execution boundary | Useful fit | Important residual |
|---|---|---|
| Restricted process | Trusted code with narrowly reduced rights | Shares the host kernel, process context and configuration mistakes |
| Hardened container | Known application code and lower-consequence generated work | Shares the host kernel; dangerous mounts, capabilities or sockets can erase isolation |
| Userspace application kernel | Host-kernel exposure must be reduced without a full guest VM | Compatibility and I/O costs; surrounding network and credential paths still matter |
| MicroVM or VM | Arbitrary native code, stronger tenant separation or higher consequence | Guest, VMM, host, firmware, devices and side channels still require patching and policy |
| Dedicated worker | Highest consequence or incompatible multi-tenant risk | More cost and slower utilisation; network and identity can still bridge the boundary |
gVisor's security model illustrates the userspace-kernel approach: workload system calls are intercepted by its Sentry rather than sent directly to the host system API. Its documentation also warns that a sandbox is not a substitute for secure architecture; an exposed host service or other API path can bypass the intended isolation without a kernel escape.
Firecracker's production host recommendations show the same defence-in-depth principle for microVMs. KVM supplies a virtualisation boundary, while the jailer adds namespaces, cgroups and dropped privileges, and Firecracker applies restrictive seccomp filters. The guide still requires patched host and guest kernels, current microcode, resource controls and a tenant model. “MicroVM” is a stronger primitive, not a complete policy.
Deny ambient authority inside every boundary
Start a job with a minimal immutable base, a unique unprivileged identity and no inherited session. Mount only verified inputs read-only. Give it a new writable scratch volume and a separate bounded output volume. Do not mount the container runtime socket, host home directory, source-control credentials, cloud metadata path or another job's cache. Drop capabilities and prevent privilege gain.
Linux mechanisms are composable rather than interchangeable:
- The kernel's seccomp documentation says system-call filtering reduces exposed kernel surface but is not itself a sandbox; logical behaviour and information flow need other controls.
- Landlock lets a process restrict its own ambient filesystem and network rights with stackable rules. Its ABI and documented limitations must be checked on the actual host instead of assumed from a development laptop.
- Control groups v2 organise processes hierarchically and enforce controllers such as CPU bandwidth, hard memory ceilings and I/O limits. A timeout alone cannot stop memory, fork or disk pressure that damages the host before the clock expires.
These controls should fail closed when the required enforcement feature is missing. A launcher that silently drops Landlock, a seccomp profile or a memory controller for compatibility has changed the release boundary.
Keep credentials outside the workload wherever possible. A broker can validate a structured request, attach a destination-bound short-lived token and return only the permitted result. The sandbox never needs to see the reusable secret. The delegated credential guide explains why workload identity, user delegation and action authorisation should remain separate.
Make network and package access explicit
Default-deny egress changes the problem from “spot every malicious destination” to “name the few services this task requires”. The NCSC recommends denying inbound and outbound traffic by default, progressing from domain allowlists towards model-only access or a fully disconnected local model as consequence rises. Where a task needs an API, route it through a service-aware proxy that checks method, path, tenant, payload size, redirects and rate—not just a hostname.
Treat DNS, IPv6, raw sockets, proxies, link-local addresses and cloud metadata as part of the route. A permitted URL that redirects to a private address must not become a tunnel. The complete region and subprocess path also belongs in the AI data-residency map.
Do not give a live analysis job unrestricted package-manager access. Resolve and scan dependencies in a separate build path, pin digests, retain provenance and promote an immutable environment. If dynamic installation is genuinely the product capability, isolate that builder more strongly, use a controlled registry mirror and prevent its cache or artefacts from becoming trusted automatically. Connect the approved runtime to the ML-BOM and incident inventory, including interpreter, base image, native libraries and sandbox policy.
Use one fresh lifetime for one bounded task
Persistence can turn a contained first task into an uncontained second one. A package, shell profile, compiled binary, notebook state or poisoned cache may survive even when the original prompt is gone. Prefer one fresh sandbox per task and security principal. Destroy its writable layer after promoting only validated outputs.
If warm pools are necessary, restore from a signed clean snapshot rather than a previous user's stopped instance. Prove that memory, disk, temporary directories, process namespaces, credentials and network connections are reset. Partition caches by the equivalence and authority they actually preserve; never use a shared writable dependency cache as an informal data channel.
Collect control-plane evidence outside the sandbox: instance identity, policy digest, image digest, mounted inputs, denied calls, network decisions, resource peaks, exit reason and promoted output digests. Logs are themselves a boundary. Bound their volume, remove unnecessary sensitive content and prevent the workload from editing or deleting them. The privacy-safe incident replay guide shows how to preserve causal evidence without turning telemetry into another uncontrolled dataset.
Worked design: a spreadsheet-analysis agent
Consider a support team that uploads customer spreadsheets and asks an agent to write Python for cleaning, joining and charting them. The product needs arbitrary data-frame operations, but it does not need arbitrary organisational access.
The release profile could require:
- The upload service scans and normalises file types before placing content in a per-job input volume.
- A fresh microVM or evaluated userspace-kernel sandbox starts from a pinned image containing the approved interpreter and libraries.
- Inputs are read-only; only scratch and an output directory are writable; no host or cross-job path is present.
- The workload has no credential files or environment secrets. Model calls go through a broker that knows the job and maximum budget.
- Network access is limited to that broker. Package installation, inbound connections and direct internet egress are denied.
- CPU, memory, process, disk, I/O, log, output and wall-time ceilings are enforced by the launcher.
- The job emits a data summary, chart and transformation record into quarantine. Deterministic checks and a reviewer decide what may be downloaded.
- The sandbox is terminated and its writable state erased whether it succeeds, fails or times out.
This is not a claim that the generated analysis is correct. It is a narrower claim: the job can perform the intended computation without acquiring authority over unrelated systems, and its artefacts cannot bypass review merely because execution completed.
Test the boundary where it is supposed to break
Happy-path success proves compatibility, not containment. Build release tests from the contract and run them after changes to the kernel, runtime, base image, proxy, model, orchestrator or host configuration.
Attempt at least:
- parent traversal, symbolic and hard links, device access and sensitive process files;
- environment, metadata-service, credential-file and neighbouring-workload discovery;
- direct IP, DNS rebinding, redirects, alternate protocols, IPv6 and proxy bypass;
- fork, thread, memory, disk, file-descriptor, I/O, log and output exhaustion;
- child-process and native-code paths outside the interpreter's normal behaviour;
- writes to the base, launcher, policy, evidence collector and another job;
- persistence through snapshots, caches, temporary files and failed cleanup; and
- termination during download, execution, upload and output promotion.
Track denied escape attempts, unexpected egress, resource-limit enforcement, cross-job residue, cleanup completion, promoted-output rejections and false blocks on valid work. A useful service measure combines containment with completion: the share of eligible jobs that finish inside the approved profile without boundary violation or manual rescue.
The final gate is straightforward: can the team demonstrate that hostile code can do the intended work, cannot reach the named forbidden resources, cannot outlive its authority and leaves evidence the workload cannot rewrite? If not, narrow the task, remove connectivity, strengthen isolation or keep execution under direct review. A sandbox is a measured reduction in blast radius—not a label attached to a process that happened to run somewhere else.



