Skip to content
AI 知识地图 0.18 · 2026-07-30
关于与纠错文字目录 / Search
Understanding the principles

Code Execution and Sandboxing: Let the Model Compute, but Don’t Hand Over the Host to It

Understand where the generate–execute–observe loop’s capabilities come from, and the isolation boundary made up of processes, files, network, resources, credentials, and human authorization.

Core idea Code execution converts a language model’s intentions into repeatable, deterministic computation, but any generated code should be treated as untrusted input; a reliable system depends on temporary sandboxes, least privilege, resource limits, output validation, and high-risk approval, not on the model’s promise of safety.
After reading this, you should be able to:Explain why code tools improve reliability; draw the execution loop; list six types of isolation; distinguish sandboxes from virtual environments; securely handle dependencies, files, network, secrets, and output.
  1. Break tasks into minimal executable, revertible, auditable, and replayable steps.
  2. Configure isolation, permissions, and limits based on risk.
  3. Execute and capture complete state.
  4. On failure, provide only necessary feedback and limit the number of corrections.
  5. Accept artifacts using tests, hashes, or business rules.
  6. Re-authorize high-impact external actions outside the sandbox.

1What Kind of Capability Does the Code Tool Add?Intuition

A model can fluently explain an algorithm yet give a wrong answer when computing a large number; this is not accidental. Language models are good at restating goals as programs, while interpreters are good at precise, repeatable execution of explicit rules. The two solve different problems: the former is responsible for "expressing intent," and the latter for "putting rules into practice." Handing deterministic tasks such as computation, data transformation, plotting, and testing over to code is essentially substituting the result of one actual execution for "guessing the result with language," and then using this observable result to correct the next judgment.

Code execution is therefore a tool: it lets an interpreter run candidate programs and return observable evidence. Its inputs are the task, code, data, and runtime environment; its outputs are the run result, logs, and artifacts. Its working mode follows a loop of "generate—execute—observe—correct": first the model generates a candidate program, then the interpreter executes it, and the model observes the output and corrects its next step. The value of this loop is that it leaves behind the program, input, environment version, and output, allowing the entire process to be independently reviewed and deterministically replayed.

What must be strictly distinguished is that a single execution result can only indicate "what this program produced in this environment during this run"; it cannot automatically prove the program correct or safe, nor does it equal obtaining release authorization. Correctness requires separate verification, security requires separate isolation, and release authorization requires separate decision-making. What code execution adds is the capability of "deterministic computation and observable feedback," not a final endorsement of the conclusion.

2Minimal Execution LoopEngineering

For code to go from generation to being trusted, it must pass through these states in order: generation, boundary checking, isolated execution, observation and recording, feedback correction, and independent acceptance; each state is handled by a different party and cannot replace one another.

The inputs to the loop are candidate code, read-only data, an execution policy, and a completion predicate. The so-called completion predicate is a condition that can independently determine, outside execution, whether the task has truly succeeded, rather than whether the process has exited normally. After the model proposes the code, input, expected artifacts, and this completion predicate, the host first performs static checks: it checks tools, dependencies, permissions, and resource policy; if the policy is not satisfied, the host should refuse to execute rather than letting the code downgrade itself to accommodate. Subsequently, the read-only input is copied into a brand-new sandbox and run under an unprivileged identity; the host captures stdout, stderr, exit codes, signals, resource peaks, network attempts, and file differences. These observations return to the AI Agent; on failure, only necessary diagnostic information is exposed, and the number of corrections is limited to prevent infinite retries.

After execution comes independent acceptance: the host does not treat “successful process exit” as task success, and only exports artifacts that are permitted. Throughout the entire loop, the control plane is responsible for creating the environment, injecting the policy, and deciding what to export; the data plane only runs the candidate code. The candidate process can neither access the control plane's tokens nor modify its own limits; otherwise, the so-called sandbox is merely an agreement that the isolated object voluntarily complies with, and the boundary is effectively nonexistent.

The key to understanding this loop is that the host first sets boundaries, then executes, observes, and accepts; exit code 0 only means the process ended normally, not that the task is complete. Once control tokens are visible to the candidate process, or the completion predicate cannot be independently checked externally, the loop loses its real boundary.

3Why Code Must Be Assumed HarmfulThreat

The model has no malicious intent, yet the code it generates must still be treated as an attack payload, because the threat is determined not by the generator’s intent but by the code’s capabilities and the resources it can actually reach. Prompt injection, misspelled or misinstalled dependencies, snippets copied from web pages, and even ordinary programming errors can lead to deleting files, reading secrets, scanning the internal network, entering infinite loops, or exhausting resources. The fact that the author 'just wanted to compute an average' does not make these consequences any less real.

Therefore, the threat model should start from the 'worst reachable impact' rather than from 'whether the author is well-intentioned'. It is necessary to confirm one by one: which paths the code can read, which addresses it can connect to, what identity it runs as, how many child processes it can create, and whether its output will trigger downstream parsers. Even if the main task is only to compute an average, as long as the runtime inherits cloud credentials and internal network access, it also possesses a huge attack surface unrelated to the task. The principle of least privilege requires first removing unneeded capabilities, not politely asking the code in a prompt 'not to use them'.

eval is not a safe alternative to exec: both can execute untrusted expressions, and the security boundary must be built on an independent execution environment, not obtained by choosing a particular interpreter function.

The inputs to this threat model are the capabilities the code can invoke, the files and networks it can reach, the identity it runs under, and downstream parsers; the outputs are the worst reachable impact and the permissions that should be removed. It addresses the misconception of 'whether it is safe if the author has no malicious intent'. The conclusions it produces are used to configure defenses, rather than to predict that a particular attack will definitely occur; unknown vulnerabilities and configuration errors may still penetrate known boundaries, so defense conclusions are the starting point for continuous tightening, not a once-and-for-all guarantee.

4What Resources Must the Sandbox Isolate?Security

Spawning a single new process is far from enough, because threats come from multiple orthogonal dimensions, and losing control of any single dimension can cause damage. The sandbox must establish boundaries on five categories of resources simultaneously and record the control evidence corresponding to each category.

For files, use a temporary workspace and read-only input, prohibit access to host paths and devices, and record the mount list and final file differences. For network, default to network off or a target/protocol allowlist, block internal network metadata, and record DNS queries and connection attempts. For resources, set limits on CPU, memory, disk, process count, and wall-clock time, and record peak values, termination reason, and exceeded items. For identity, use a non-privileged user, carry no host credentials, restrict system calls, and record the effective uid, capability, and policy version. For lifecycle, rebuild the environment for each task, destroy it after use, clean up artifacts, and record the environment id and creation/destruction time.

These controls must coexist: limiting only CPU cannot prevent secrets from being exfiltrated, disconnecting only the network cannot prevent overwriting host files, and using only a temporary directory cannot prevent a fork bomb. Output channels are also part of the boundary—stdout, images, archives, and spreadsheets must all have limits on size, type, and parsing method, otherwise the attack is simply shifted from the executor to the viewer.

When using this isolation table, the inputs are the resources the task genuinely needs and the acceptable loss, and the outputs are the five categories of isolation policies and the corresponding audit records. The host sets limits on files, network, resources, identity, and lifecycle separately, then performs a joint check. Logs showing no boundary violations can only explain the behavior observed this time; they cannot prove that the shared kernel or the viewer has no unknown vulnerabilities.

BoundaryControlEvidence to record
FilesTemporary workspace, read-only input, prohibit host paths and devicesMount list and final file differences
NetworkDefault network off or target/protocol allowlist, block internal network metadataDNS and connection attempts
ResourcesCPU, memory, disk, process count, and wall-clock limitsPeak values, termination reason, and exceeded items
IdentityNon-privileged user, no host credentials, minimal system callsEffective uid, capability, and policy version
LifecycleRebuild per task, destroy after use, and clean up artifactsEnvironment id, creation/destruction time

5Virtual environments are not the same as security sandboxesDisambiguation

Python's venv or dependency containers do not automatically isolate the host. venv primarily isolates package versions; it does not restrict file access, network, or system calls. Containers provide namespaces and resource control, but incorrect mounts, privileged mode, or vulnerabilities in the shared kernel can still break isolation. In high-risk scenarios, you need a stronger combination: unprivileged containers, a read-only root filesystem, system call filtering, micro virtual machines, and external network policies.

“Reproducibility” and “isolation” are not the same thing either. Lock files, fixed runtimes, and deterministic random seeds help replay results but do not restrict permissions; micro virtual machines strengthen boundaries but may still produce different results because dependencies are not locked. Reliable execution must answer two independent questions simultaneously: whether the program can escape or damage the environment, and whether the same input can be computed again to yield the same result.

When making a choice, the inputs are reproducibility requirements, attack risk, and the capabilities that need to be exposed to the host; the output is a combination of dependency environments, containers, or micro virtual machines. venv solves package version conflicts, while sandboxing solves privilege escalation and blast radius—the two have different goals. A container itself is not a security conclusion; privileged mode, dangerous mounts, or overly broad outbound network permissions can all defeat isolation.

6Dependencies and Results Are Also UntrustworthySupply Chain

Even if the code itself looks safe, risks can still enter through two paths: dependencies and artifacts. On the dependency side, an installation package may be typosquatted—using a package with a similar name but different content to impersonate the target package—or may execute arbitrary scripts during installation. On the artifact side, generated files may contain macros, formula injection, or huge amounts of data. The response is to constrain dependencies with allowlists, pinned versions, and internal mirrors, while scanning artifacts and limiting their type and size; only verified results are copied out of the sandbox.

The input to the supply chain check is dependency name, version, source, and files to export; the output is an allow or deny decision and scan evidence. It blocks the risk of dependency and artifact smuggling through pinned versions, trusted mirrors, and type and size checks.

It is important to remain clear that scanning only means that no known rules matched and cannot guarantee absolute safety; unknown malicious packages, macros, and parser vulnerabilities still exist, so least privilege and safe viewing must still be retained. Pinned versions and trusted mirrors reduce the probability that dependencies are replaced, while type and size limits reduce the probability that artifacts trigger risks in viewers; only together do they form an effective constraint on this hidden supply chain path.

7Budgets must be computable, not written as “appropriate amount”Derivation

With a per-turn time limit of 30 s and up to 3 retries, users may still wait two minutes, because end-to-end wait time is not the per-turn limit but the upper bound of the entire correction loop. The worst-case wall-clock time can be expressed as:

T_worst ≤ (1 + N_retries) × T_turn + T_queue_and_startup

The formula takes three inputs: N_retries is the maximum number of additional executions after the first failure, T_turn is the maximum wall-clock time allowed per turn, and T_queue_and_startup is the extra budget for waiting for resources and creating the sandbox; the output T_worst is the upper bound on the user's end-to-end wait. Here the “maximum retry count” does not include the initial execution. If each turn is 30 s, up to 3 additional attempts are allowed after failure, and queueing plus startup reserve a total of 12 s, then the worst-case end-to-end budget is (1+3)×30+12 = 132 s, not 30 s.

Outputs must also be computable. If up to 20 files are allowed and each file is 5MB, file exports alone could theoretically reach 20×5 = 100MB; therefore an additional aggregate artifact limit is needed to prevent many small files from bypassing the per-file limit.

Budgets need hard limits along multiple axes, with specified actions on limit violations. For compute, set 2 CPU, 512MB, 30 s; on limit violation, terminate the entire process group and record the exceeded item. For concurrency, set 64 processes or threads; refuse further creation to prevent fork bombs. For storage, set a 1GB temporary disk and a 40MB aggregate export; on limit violation, stop writing and do not export partial artifacts. For feedback, set stdout+stderr to 2MB total; on limit violation, truncate and preserve the hash and tail diagnostics. For attempts, set the initial attempt plus 3 corrections; on limit violation, stop the automatic loop and hand off to an external policy.

Budgets should be two-layered: sandbox-internal limits constrain a single execution, while the controller’s end-to-end budget constrains the entire correction loop; missing either layer can lead to resource runaway. This upper bound depends on configuration assumptions; it is a constraining upper bound, not a prediction of actual elapsed time, and it does not cover time for external human approval.

Budget axisExample hard limitAction on limit violation
Compute2 CPU, 512MB, 30 sTerminate the entire process group and record the exceeded item
Concurrency64 processes/threadsRefuse further creation, prevent fork bombs
StorageTemporary disk 1GB, aggregate export 40MBStop writing; do not export partial artifacts
Feedbackstdout+stderr 2MBTruncate and preserve hash and tail diagnostics
AttemptsInitial attempt + 3 correctionsStop the automatic loop, hand off to an external policy for decision
Tworst(1+Nretries)·Tround+Tqueue and startup

8From Intent to Trustworthy ResultsSynthesis

Making execution feedback improve capability rather than expand the blast radius relies on a chain that progressively tightens intent into trustworthy results. The first step is to decompose the task into minimally executable, revertible, auditable, and replayable steps; the second step is to configure isolation, permissions, and limits according to the risk level; the third step is to execute and capture the complete state; the fourth step is to provide only the necessary feedback on failure and limit the number of corrections; the fifth step is to accept the artifact using tests, hashes, or business rules; the sixth step, high-impact external actions must be re-authorized outside the sandbox.

The inputs to this synthesis chain are the task intent, risk level, candidate code, and completion predicate; the outputs are a bounded artifact that passes acceptance, or a stopped result with evidence. Each step narrows the scope of actions while making the next step verifiable: decomposition bounds the damage surface of a single step, configuration bounds the capabilities of execution, capture bounds the traceable state, feedback bounds the scale of retries, acceptance bounds the exportable artifact, and re-authorization keeps truly dangerous actions outside the sandbox's trust boundary.

Passing sandbox acceptance only means that the artifact meets the declared rules; it does not mean that it is allowed to be published, transferred, or written to production. Publishing, transferring, and writing to production are all high-impact external actions and must be re-authorized. What execution feedback improves is the model's ability to progressively correct its intent, while the blast radius is jointly constrained by the boundaries at each step and the final re-authorization.

9How a Cache Fix Is Proven in the SandboxRunning Example

After a model proposes a fix with a composite cache key, you cannot write the patch directly into the production repository and declare it done, because between “proposing a solution” and “the solution has been proven viable” lies an entire verification chain. The patch must first pass through a host policy gate, enter a temporary sandbox for execution, and only after the artifacts pass validation is it up to the host to decide whether to export. The security boundary is configured by the host before execution and reviewed after execution; processes inside the sandbox cannot expand network, file, or credential permissions on their own.

Observed evidence and what it can prove must be distinguished item by item. An exit code of 0 only proves that the test process terminated normally, not that the test coverage is complete or the business objective is correct. Tests passing 4/4 only proves that the declared isolation and hit behavior passed, not that hidden concurrency issues or cross-version issues do not exist. A resource peak of 310MB / 6.2s only proves that this run was below the 512MB / 30s limit, not that any input scale is safe. File differences showing 2 allowed files only proves that no out-of-bounds writes were observed this time, not that the code has no other security defects.

Resource limits are not only for “defending against bad actors”: a single erroneous recursion can exhaust memory. In this example, allowing 3 corrections means at most 4 rounds of execution; the upper bound for the task execution part is 4×30 = 120 s; adding queueing and startup gives the complete budget.

The failure boundary is: the sandbox reduces the blast radius, but it does not turn malicious code into safe code. Shared kernel vulnerabilities, incorrect mounts, overly broad outbound network permissions, and host proxy interfaces can all break through the boundary. High-risk systems need layered isolation, timely patching, and external policy checks rather than relying on a single sandbox to give absolute guarantees.

Candidate PatchComposite Cache Key+ Regression TestHost Policy GateRead-only Input CopyDisconnected · No Credentials2 CPU / 512MB / 30sTemporary SandboxApply Patch → Run TestsCapture exit/stdout/stderrRecord file diff / resource peakTerminate and destroy immediately if limit exceededIndependent AcceptanceIsolation 2/2Hit 2/2No Out-of-Bounds FilesFailure evidence is only returned to the correction loop; passing artifacts only export the patch, without carrying sandbox secrets and temporary files.

Scroll horizontally to view the full diagram on small screens.

Figure 1 The security boundary is configured by the host before execution and reviewed after execution; processes inside the sandbox cannot expand network, file, or credential permissions on their own.
ObservationValueWhat it can proveWhat it cannot prove
Exit code0Test process terminated normallyTest coverage complete, business objective correct
Tests4/4Declared isolation and hit behavior passedHidden concurrency or cross-version issues do not exist
Resource peak310MB / 6.2sThis run is below 512MB / 30sSafe for any input scale
File differences2 allowed filesNo out-of-bounds writes observed this timeCode has no other security defects

10How to Prove the Policy Really WorksEvaluation

Writing “network disconnected” in the config is not itself evidence; to prove the policy really works, tests should actively attempt to cross the boundary and observe results from outside the sandbox. Adversarial tests verify item by item whether isolation truly works. Each type of test corresponds to an expected observed result, and the location to check first when it fails.

When reading the host secret decoy, expect the path to be invisible and no content leakage in audit logs; if it fails, first check mounts, environment variables, and proxy credential injection. When accessing public internet and cloud metadata addresses, expect connections to be rejected by the host network policy and leave traces; if it fails, first check DNS, IPv6, proxies, and side-channel interfaces. When a fork bomb or infinite loop occurs, expect the process count or wall clock to exceed limits and the whole process group to be cleaned up; if it fails, first check cgroup/job object and child process reclamation. When the disk is full or stdout is huge, expect quotas to be triggered and host services to remain available; if it fails, first check temporary disk, logs, and total export limits. When a symbolic link or archive path traversal occurs, expect the exporter to refuse targets outside the sandbox; if it fails, first check path normalization and unpacker. When correct programs are combined with business counterexamples, expect security tests to pass but incorrect artifacts to be intercepted by business predicates; if it fails, first check acceptance coverage rather than the isolation layer.

This means there are two separate report cards that must be looked at separately: security evaluation asks “whether crossing the boundary is blocked,” while task evaluation asks “whether the result is correct.” A perfect score on one cannot substitute for the other. Adversarial testing can only add evidence for the tested policy; it cannot prove that no unknown escapes exist. Passing security tests does not mean the task is done correctly, and vice versa. The two report cards answer two different questions; both must hold at the same time for the policy to truly take effect.

Adversarial testExpected observationIf failed, where to check first
Read host secret decoyPath invisible, no content leakage in audit logsMounts, environment variables, proxy credential injection
Access public internet and cloud metadata addressesConnection rejected by host network policy and leaves a traceDNS, IPv6, proxies, and side-channel interfaces
fork bomb / infinite loopProcess count or wall clock exceeds limit, whole process group cleaned upcgroup/job object, child process reclamation
Fill disk / huge stdoutQuota triggered and host service remains availableTemporary disk, logs, and total export limits
Symbolic link or archive path traversalExporter refuses targets outside the sandboxPath normalization and unpacker
Correct programs and business counterexamplesSecurity tests pass, but incorrect artifacts are intercepted by business predicatesAcceptance coverage rather than isolation layer
Source and adaptation notes
  • NIST SP 800-190: Application container security risks and controls.
  • Agache et al., Firecracker: Isolation design and engineering trade-offs of micro virtual machines.
  • ToolEmu: Risk simulation and evaluation of tool-using language models.
  • ReAct: Reasoning, action, and environment observation loop.
Date accessed: 2026-07-23