name: ai-coding-agents-safety-envelope
description: "Designs approval and sandbox policy for local coding agents: permission modes, isolation, network and destructive-command guards. Use when setting approvals. Not cloud sandboxes."
compatibility: Portable core. Works on Claude Code and Codex.
version: "2.0"
last_validated: 2026-10-09
AI Coding Agents Safety Envelope
Use this skill to design or review the two layers that bound what a coding agent may do: the approval system (who decides: permission modes, rule sources, plan-mode transitions, prompt routing, leader-worker handoff) and the execution sandbox (what is reachable: process isolation, filesystem mounts, network policy, environment exposure, destructive-command controls).
Approval policy decides who decides; the sandbox decides what is reachable. Neither substitutes for the other, and both are defined here so their interaction (auto-allow inside the boundary, escalation at its edge, worker envelopes) is designed once.
This skill does not own remote execution or managed cloud sandboxes (ai-coding-agents-cloud-sandboxes), hook automation (../agents-hooks/SKILL.md), full settings-source layering and managed policy (../ai-coding-agents-settings-policy/SKILL.md), plugin trust (../ai-coding-agents-plugins/SKILL.md), or the tool execution pipeline (../ai-coding-agents-runtime-core/SKILL.md).
Quick Reference
| Question | Read | Outcome |
|---|
| How should permission state live in the runtime? | references/permission-runtime-model.md | Central permission context, mode handling, plan-mode restore, host-owned rules |
| How do local, remote, and worker approvals differ? | references/permission-routing-local-remote-and-worker.md | Approval flows for REPL, remote sessions, and leader-worker teams |
| Which vendor modes, rule syntax, and precedence traps does an audit check first? | references/reference-runtime-permission-modes-and-rule-syntax.md | Mode ladder, protected paths, deny > ask > allow, path anchors, symlinks, hook limits |
How does OpenAI Codex model split filesystem policy and request_permissions? | references/openai-codex-request-permissions-and-split-policy.md | Read/write/deny entries, protected metadata, scoped grants |
| How does OpenAI Codex structure exec policy and network egress? | references/openai-codex-execpolicy-and-network-proxy.md | Prefix rules, strictest-decision wins, network deny precedence |
| How should process, filesystem, and workspace isolation work? | references/sandbox-process-and-filesystem-model.md | Execution modes, mounts, working directories, write boundaries |
| How should network, approvals, and destructive actions be controlled? | references/network-approval-and-destructive-action-guards.md | Outbound policy, command classes, escalation triggers |
| What sandbox mode names and backend split does Codex use? | references/openai-codex-sandbox-guardrails-may-2026.md | Mode names, platform backends, fail-closed translation, telemetry |
| What does a shipping subprocess sandbox enforce, and where does its scope end? | references/claude-code-bash-sandbox-mechanics.md | Read/write asymmetry, credential deny-vs-mask, TLS-blind allowlists, tool-scope limits |
| What is the canonical sandbox policy format? | references/sandbox-policy-format.md | Runtime-agnostic policy fields, traps, translation notes |
| How do I verify the permission boundary and sandbox before shipping? | references/hostile-path-test-checklist.md, references/escape-path-test-matrix.md | Path, symlink, interpreter-wrapper, env-injection, package-manager escape tests |
| Identity-aware or ACP-bridged approvals, build-time gates, distro allowlists? | references/goose-approval-and-distribution-layer-patterns.md | Cross-platform patterns beyond the local REPL |
A JSON schema for the permission context is in assets/templates/permission-context.schema.json.
When To Use
- Design a permission model, approval prompts, ask/allow/deny rules, or sandbox escalation
- Model plan-mode entry and exit as a permission transition
- Route worker or remote approvals through a lead agent or bridge; decide what background agents auto-deny
- Define execution modes, mounts, network policy, env-var exposure, or destructive-command classes
- Review how worker or teammate sandboxes inherit or narrow the launcher's envelope
- Audit an over-permissive local setup, or verify a sandbox holds before shipping it
Use Other Skills
Approval Policy vs Sandbox
Sandbox mode is not approval mode: they are related but not identical, and each needs its own enum.
- Look up the current approval values in the vendor config reference before writing config; a retired value can prevent startup. Write explicit current values, never branch code on a backward-compatible alias as if it were its own policy, and never invent a parallel enum.
- A per-category (granular) approval setting may auto-reject a category rather than prompt for it; check what each category does when it is not enabled.
- An approval prompt is not isolation; a sandbox is not consent. Keep a prompt from being read as a boundary and a boundary from being read as authorization.
- Move a command class that is over prompt budget into the sandbox (auto-allow inside the boundary) instead of widening allow rules.
Approval Workflow
- Model permission as runtime state. One host-owned permission context with mode, rule sources, and special-case flags, not scattered booleans.
- Separate policy layers: always-allow, always-deny, always-ask, org policy, session-local overrides. Preserve source class through evaluation; shared and personal sources may need different sanitization.
- Define promptability. Background workers, headless sessions, and remote viewers need auto-deny or delegated approval instead of local dialogs. Auto-deny only when no controller exists; otherwise surface the request in the parent session, labeled with the subagent.
- Treat plan mode as a reversible permission transition that preserves the prior mode.
- Route approvals by topology (local REPL, remote, swarm worker, ACP-delegated) with shared semantics but separate transport.
- Keep pending approvals as first-class objects with prompt ID, tool-use ID, cancellation state, and exactly one terminal outcome (approved, denied, cancelled, expired). "Prompt shown" is not an outcome.
- Bridge unknown remote tools into local renderables (synthetic messages or stubs) so the user can still see what is being approved. Tools describe requests; the host decides enforcement and persistence.
- Lint and scrub persisted rules. Detect unreachable or shadowed allows, refuse over-broad shell prefixes, and reject any rule that matches a secret shape (an "always allow" click can persist auth headers); rotate any token found in a rules file.
- Preserve authorization scope. Bind a decision to the concrete action, target, actor, and session or policy scope. An agent-to-agent message is not consent, and do not discard still-applicable user authorization merely because time passed unless policy defines expiry.
- Budget prompts. Track prompts per session and the share approved within seconds; prompt fatigue drives users to bypass modes.
- Audit the mode before the rules. In
bypassPermissions mode allow rules have no effect and the mode is the approval gate; deny rules still block and explicit ask rules still prompt, and a blanket allow that matches before classification switches the classifier off for that surface. Deny beats allow at every scope; see the rule-syntax reference.
Sandbox Workflow
- Define execution modes (read-only, workspace-write, unrestricted, remote-bridged, worker-reduced) with trust levels.
- Set the mount model: readable, writable, hidden, remapped. Canonical path and symlink resolution are part of the boundary; permission-rule path semantics and substrate mount semantics are separate resolvers.
- Control process spawning with allowlists enforced by a mechanism that can see paths (an LSM such as Landlock, AppArmor, or Seatbelt, seccomp user-notify, ptrace, or a
noexec mount plus one executable bin root). Plain seccomp filters cannot allowlist executables by path.
- Separate network policy from filesystem policy. A hostname allowlist is connectivity policy, not content inspection, unless the proxy terminates TLS; otherwise domain fronting is an exfiltration path.
- Make environment and secret exposure opt-in. A sandbox that restricts only writes and still reads
~/.ssh or cloud credentials is not a secrets boundary.
- Classify destructive actions (delete, reset, force-push, privileged) with stricter rules, evaluated against the subprocess tree, not the top-level command.
- Protect privileged config surfaces (settings, policy, skill directories, repository metadata) even when the workspace is writable.
- Compute the worker envelope: intersect the launcher envelope, worker policy, runtime defaults, mounted roots, network policy, and any fresh approval. A narrower worker definition does not by itself narrow child capability; compare with the launcher's envelope before dispatch and block or surface any widening.
- Scope the sandbox to the tool classes it covers. Shipping subprocess sandboxes restrict subprocess execution but leave file-edit, fetch, and computer-use calls to the permission system; "the agent is sandboxed" is a category error unless it names the tool surface.
- A declared policy is not an enforced policy. Record which component enforces each field (kernel backend, proxy, or nothing) and keep a fail-closed test that proves the backend applied it. Domain rules with no active proxy, or a missing backend dependency that falls back to unsandboxed execution, are the same failure.
- Test escape paths: symlinks, traversal, shell expansion, wrapper binaries, env indirection, package-manager helpers.
Host Rules
- The host owns allow, deny, ask, and persistence policy; one canonical permission context per session.
- Apply policy before execution, not after output returns; the boundary must exist in the execution substrate, not in prompts.
- Filesystem, network, and environment are separate control planes. Default to a conservative sandbox and escalate only when justified.
- Prompts need stable request IDs and explicit cancellation. Record why a request was allowed, denied, or never prompted. Remote and worker flows return structured results, not implicit UI side effects.
- Non-interactive actors never hang waiting for a prompt they cannot answer.
- Await automated checks (classifier, hook output) before showing dialogs when coordinator workers depend on them.
- A deny from any scope blocks the action; do not assume "higher scope wins" applies to allow-versus-deny conflicts.
- Registering a compatibility escape hatch (Apple Events, a weaker-isolation flag, an unelevated backend) must record what guarantee it removes for every later command in the session. A Unix domain socket exception such as a container runtime control socket can equal full host access.
Unfamiliar Repositories
- A headless
claude -p run shows neither the workspace-trust dialog nor the approval prompt for a project's .mcp.json servers (Claude Code security docs, "Trust verification"). Read the repository's committed config and .mcp.json before the first headless run, or pass --strict-mcp-config with your own --mcp-config so only servers you named load.
--bare skips auto-discovery of hooks and MCP servers, so it removes your own guard hooks along with the repository's. Do not use it as a trust measure unless the guard lives somewhere the flag does not skip.
- For a repository you do not trust, run the agent in a container with no network and only that repository mounted. A host mount of anything else, or a container runtime socket, defeats the boundary.
Source idea: ECC the-security-guide.md (MIT), adapted.
Build Order
- One canonical permission context; modes and rule sources explicit.
- Request IDs, approval results, cancellation and expiry semantics.
- Execution modes, canonical path resolution, and mount policy.
- Process and interpreter allowlists; network policy and exceptions; env and secret filtering.
- Protected config surfaces and destructive-command classification with escalation hooks.
- Approval routing by topology; worker-envelope computation.
- Persistence or session-local memory for approved rules, with sanitization, shadow detection, and source-aware handling.
- Escape-path and hostile-path tests before shipping.
Core Invariants
- Tools describe requests; the host decides. Every prompt ends in exactly one terminal outcome.
- Plan mode is a reversible transition, not a separate permission system.
- No persisted rule contains a credential; persisted rules are linted for reachability and breadth before activation.
- Worker capability is the computed effective envelope; inheritance defaults are runtime-specific and must be verified.
- Destructive capability is never implied by tool name or user intent alone.
- Privileged config surfaces stay protected even when ordinary workspace edits are allowed.
Failure Modes
- Prompt IDs that cannot be matched to cancellations or late results; workers blocking on a prompt they cannot answer; plan-mode exit not restoring prior state.
- Remote approvals for unknown tools that become unrenderable; approval state inferred independently by runtime, UI, and stored policy.
- Persisted shell rules broader than intended; allow rules shadowed by an earlier ask or deny.
- Symlink or traversal writes escaping the workspace; wrapper tools or package-manager helpers bypassing interpreter and network policy.
- Child workers silently inheriting a parent's unrestricted mode; secrets leaking through inherited environments.
- Workspace-write modes that allow mutation of policy or skill roots; approval prompts treated as the sandbox.
- Package installs, build tools, and test runners writing outside obvious workspace paths because mounts and temp policy were not explicit.
- Tools or plugins owning their own approval policy and bypassing central auditability.
Minimal Viable Version
- One session-owned permission context with explicit ask, allow, and deny modes; stable IDs; auto-deny for non-interactive workers.
- One conservative default sandbox mode with canonical readable and writable roots, one subprocess allowlist, one network policy, one protected-config list.
- One lint pass over persisted rules and one escalation path for destructive or restricted actions, with approval metadata that explains outcomes.
What Strong Implementations Add
- Policy layering across org, repo, session, and ephemeral overrides; source-aware shared-versus-personal handling.
- Worker-specific narrowed envelopes, host-specific mount remapping and temp-space policy.
- Automated checks before prompting; synthetic rendering for remote prompts; cancellation, expiry, and retry-safe bookkeeping.
- Auditable destructive-command classes with justifications; package-manager exception handling.
- Escape-path tests for symlinks, shell expansion, wrapper binaries, and env indirection; identity-aware approvals for external side effects.
Navigation
References
All files under references/ are listed in the Quick Reference table above.
Templates
Data
data/sources.json — Primary documentation and source references for approval and sandbox design
Related Skills
Learnings Loop
When prior decisions or pitfalls are relevant, consult learnings.consolidated.md if present; use learnings.md only for needed history or as the available fallback. Otherwise skip both.
After applying it, if you encountered a pattern worth remembering, a mistake worth preventing, or a domain fact that surprised you, append one dated bullet to learnings.md via agents-skills-feedback-loop/scripts/append_learning.py. Do not modify SKILL.md itself.