- Published on
Containing AI Agents: Filesystem, Secrets, and Egress Boundaries
- Authors

- Name
- Jared Chung
Introduction
An agent that can edit code, run commands, and call APIs is useful because it can affect real systems. Those same capabilities create its blast radius: the maximum damage possible when the user, model, tool output, or surrounding software makes a mistake.
Permission prompts help, but frequent prompts train people to approve them quickly. Model-based classifiers help, but probabilistic controls can miss unusual actions. The strongest boundary is deterministic: do not give the execution environment access it does not need.
The examples use synthetic files, credentials, and services to demonstrate containment principles without claiming complete isolation.
Containment explorer
Open gates
Start With a Capability Inventory
Before choosing a container or virtual machine, describe the work in terms of capabilities.
| Capability | Example requirement | Safer boundary |
|---|---|---|
| Filesystem read | Inspect one repository | Read-only mount of that path |
| Filesystem write | Modify source files | Writable workspace, no home directory |
| Process execution | Run tests | Restricted user and resource limits |
| Network | Fetch package metadata | Explicit destinations and methods |
| Credentials | Create a draft issue | Narrow broker for one operation |
| Persistence | Save final artifacts | Dedicated output directory |
The inventory should include deletion. “Read-write” often implies that files can be removed, so a no-delete mode may be a meaningful separate capability.
Match the boundary to the user's ability to review actions. A developer who understands a shell command can evaluate different prompts from someone using an agent through a document interface. Both still benefit from containment.
Make Filesystem Boundaries Real
Checking whether a requested path starts with an approved string is unsafe. Relative paths and symbolic links can point somewhere else. Resolve the real path before deciding whether it sits inside the allowed root.
from pathlib import Path
def require_inside(requested: Path, allowed_root: Path) -> Path:
root = allowed_root.resolve(strict=True)
target = requested.resolve(strict=False)
if not target.is_relative_to(root):
raise PermissionError(f"Path escapes workspace: {target}")
return target
This application check is useful, but enforcement should also exist below the agent process. Mount only the required directories. Use read-only mounts for references and a dedicated writable directory for changes. Run the agent as an unprivileged user and limit processes, memory, and execution time.
Test the normal case and the escape attempts:
def test_symlink_cannot_escape(tmp_path):
workspace = tmp_path / "workspace"
workspace.mkdir()
outside = tmp_path / "private.txt"
outside.write_text("synthetic secret")
(workspace / "shortcut").symlink_to(outside)
try:
require_inside(workspace / "shortcut", workspace)
assert False, "escape should be denied"
except PermissionError:
pass
A test is not a proof that the container runtime has no vulnerabilities. It verifies that the policy you intended is actually applied to representative paths.
Keep Credentials Outside the Workspace
If a general API key is present in the environment, a process that can read its environment can use every permission attached to that key. Prefer short-lived, scoped credentials or a broker that performs one narrow action after checking policy.
def create_draft_issue(request, actor):
if request.repository not in actor.allowed_repositories:
raise PermissionError("repository is outside approved scope")
if request.mode != "draft":
raise PermissionError("only draft issues are allowed")
return issue_service.create_draft(
repository=request.repository,
title=request.title,
body=request.body,
identity=actor.service_identity,
)
The agent receives a tool for creating a draft issue, not a token that can call the entire provider API. Record the user, approved scope, payload hash, and resulting external identifier outside the agent-writable workspace.
Treat Egress as a Capability Grant
A hostname allowlist answers only “where can traffic go?” It does not answer “what can it do?” One allowed domain can expose file uploads, messaging, administration, and multiple accounts.
Anthropic described a case in which traffic to an allowed API domain carried files using an attacker-controlled key. The destination check worked as designed, but the allowed destination exposed a broader capability than intended.
A stronger proxy can bind destination, action, and identity:
def allow_request(destination, method, path, credential_owner):
return (
destination == "issues.example.test"
and method == "POST"
and path == "/drafts"
and credential_owner == "workspace-service"
)
Use a mock service when testing this pattern. Verify that an approved draft succeeds, an upload path fails, and an attacker-supplied credential is rejected.
Preserve Observability Outside the Boundary
Isolation can reduce visibility. A sealed environment may prevent host security tools from inspecting its processes. Plan audit access alongside isolation rather than discovering later that the sandbox is opaque.
Keep policy decisions and execution events outside the agent's writable boundary. Useful events include:
- workspace mounts and modes;
- denied filesystem paths;
- destination, method, and policy decision for network requests;
- credential-broker operations;
- process start, termination, and resource-limit events.
Logs are evidence, not prevention. A successful-looking API call may already represent exfiltration. Enforce limits first, then use logs for investigation and improvement.
Conclusion
Agent security begins by deciding what the agent can reach. Give it the smallest useful filesystem, network, process, and credential capabilities, then test both legitimate work and escape attempts.
Human review and model-level safeguards still matter. They work best inside deterministic boundaries that cap the outcome when judgment fails.
References
- How we contain Claude across products, Anthropic, 25 May 2026
- Keeping your data safe when an AI agent clicks a link, OpenAI, 28 January 2026