Security

A3S Code exposes security controls at session creation time and through session lifecycle hooks. Treat direct host calls such as session.tool() and session.bash() as privileged host operations: the application that calls them is responsible for deciding whether to expose that power to a user.

Delegated child runs intersect their local permissions with the parent permission checker and inherit the parent process sandbox. A child can narrow its capabilities but cannot replace the host boundary. Child-local approval behavior applies only to an Ask introduced by the child policy; a parent Ask, or a tool-owned escalation after both policies allow, remains under the parent confirmation provider. Missing providers fail closed before a HITL request is emitted. Keep high-risk release or publish commands behind explicit policy.

A permission prompt should explain the operation, reason, scope, and risk—not just present two buttons.

Enforced Execution Boundary

Permission policy decides whether an operation is allowed, denied, or needs approval. It does not, by itself, confine a process. Hosts that expose model Bash should attach a concrete BashSandbox; otherwise an approved command runs through the host workspace runner.

The Code TUI uses an SRT-backed local process sandbox from a verified user-wide installation or the support tree shipped in the CLI release. It checks the exact package graph, registry lock, file types, size bounds, complete normalized tree digest, Node.js 20.11-or-newer executable, and Core capability handshake. Official archives, Homebrew, and standalone self-update preserve that payload. Source and Cargo installs may use a fixed npm development bootstrap with lifecycle scripts disabled. A global srt installation is neither required nor selected.

Package verification is necessary but not sufficient for readiness. macOS requires sandbox-exec and ripgrep; Linux requires bubblewrap, socat, ripgrep, and permitted unprivileged user namespaces. Homebrew declares those dependencies, while direct-archive users provide them. Windows requires its one-time elevated machine sandbox setup. The TUI runs a bounded command through the actual OS boundary before attaching it. Failure leaves the sandbox absent, so Default can request one exact host invocation and Auto denies Bash.

The adapter fails closed and never silently retries on the host. It denies network egress, local binding, and Unix sockets; limits writes to the workspace and a private scratch directory; protects .git, .a3s, .agents, .codex, .claude, .vscode, .idea, and control files; masks common credential stores; and scrubs ambient secrets. Delegated tasks, Skills, and workflow steps retain the same handle.

Because built-in file tools execute in-process, the TUI separately enables Core's local workspace credential policy. It covers direct and range reads, writes, edits, patches, and both manifest-backed and fallback grep. Explicit sensitive paths fail closed, broad grep omits protected candidates, and source-tree hardlink aliases are denied before mutation. Ordinary package-store hardlinks remain usable unless they alias a discovered credential inode. Read-only Git diff regenerates output only for allowed changed paths, option-like revisions cannot become Git flags, and displayed remotes omit embedded HTTP credentials and query tokens.

The release gate exercises the exact generated support tree on macOS and Linux. It proves normal workspace writes and offline toolchain commands remain usable, while outside and symlink writes, protected metadata mutations, credential reads, network egress, local listeners, and Unix sockets remain blocked.

The terminal execution modes apply this boundary as follows:

ModeProcess behaviorApproval behavior
DefaultOrdinary Bash runs in the installed sandbox.Only an explicit host escape, missing sandbox, protected metadata mutation, mutating Git call, or annotated external side effect asks.
PlanBash and mutations are unavailable.Boundary crossings are denied, not queued for later execution.
AutoOrdinary Bash runs only in the installed sandbox.HITL is disabled; any operation that cannot stay inside the boundary is denied.

Threat Model

The protected assets are host files outside the active workspace, repository and agent-control metadata, credential stores, host network and listener capabilities, process lifetime, and the user's authority to approve a specific operation. Model output, repository content, command output, fetched content, Skill instructions, and MCP results are untrusted inputs. A malicious dependency or child process is assumed able to close output pipes early, fork descendants, create symlinks, inspect its environment, and attempt filesystem, socket, or network escapes.

The trusted computing base is the running CLI/Core binary, the verified release support tree, the exact resolved Node executable, the selected sandbox provider and operating-system enforcement, and host code that invokes direct SDK helpers. A configured MCP server or native integration is a separately trusted extension; missing or unsafe behavior annotations cause confirmation rather than granting read-only status.

Trust does not waive process ownership. Each local stdio MCP server leads a dedicated Unix process group. Closing or dropping its transport stops pipe tasks, clears pending requests, reaps the leader, and terminates descendants. The stderr pipe is drained independently so diagnostics cannot stall protocol traffic.

This local boundary does not claim kernel-level protection against a compromised sandbox provider, Node runtime, CLI binary, or operating system. It also does not turn the privileged host-direct SDK into end-user authorization. Use a stronger workload provider for hostile multi-tenant code, kernel attack resistance, or OCI-level isolation.

Invocation Ingress

Every session-owned path enters one scoped invocation kernel:

IngressEffective originTrust handling
Model tool callAgentMode policy, permission, tool-owned escalation, and HITL apply.
Model-owned batch, program, workflow, or public custom nestingGoverned nestedRe-enters the same policy for every child.
Direct host call to an ordinary custom toolHost direct at the top levelThe selected top-level call is trusted; public nested calls become governed nested calls.
Direct host call to built-in batch, program, or dynamic workflowHost direct, then trusted host-direct nestedOnly host-selected built-in children retain control-plane authority.
Skill, Task, worker, or other model sub-run created from host contextAgent in the childAmbient host-direct authority is removed before model dispatch.
Delegated child permission or confirmationGoverned nested/AgentChild policy intersects the parent; parent Ask and tool-owned escalation stay with the parent provider.
Tool behavior metadataEscalation on the current originIt can require confirmation but cannot weaken Ask or Deny.

Low-level ToolRegistry and standalone ProgramExecutor APIs are deliberately ungoverned building blocks for hosts that own the registry. AgentSession and the TUI do not use those APIs as a fallback.

Complete TUI Decision Matrix

The cells below are the terminal outcomes for model and ordinary governed nested invocations. “Deny” means no confirmation event is created. “Confirm once” means one exact invocation ID is pending; cancelling or expiring it cannot settle another prompt.

ModeSandboxOrdinary BashExplicit host BashProtected metadata mutationTool-owned confirmationAnnotated external side effect
DefaultReadyExecute in sandboxConfirm exact call once; execute on host only if approvedConfirm exact mutation onceConfirm onceConfirm once
DefaultUnavailableConfirm exact call once; execute on host only if approvedConfirm exact call once; execute on host only if approvedConfirm exact mutation onceConfirm onceConfirm once
PlanReadyDenyDenyDenyDenyDeny
PlanUnavailableDenyDenyDenyDenyDeny
AutoReadyExecute in sandboxDenyDenyDenyDeny
AutoUnavailableDenyDenyDenyDenyDeny

Origin modifies that matrix only as follows:

Origin/call shapeMatrix relationship
Agent or ordinary governed nestedUses the matrix exactly.
Direct host call to a custom toolThe selected top-level call skips model-facing permission/HITL; every public nested call returns to the matrix.
Trusted built-in host-direct nestedSkips model-facing permission/HITL because the host supplied the built-in orchestration and its children. Hooks, budget, timeout, cancellation, recursion checks, sandbox selection, and sanitization still apply.
Model sub-run born inside any host-direct callReturns to the Agent row and uses the matrix exactly.

Decision precedence is fail-closed: active-Skill restrictions and hard guardrails first, then hook blocks, origin authority, mode/permission policy, tool-owned escalation, confirmation availability, and finally execution. Terminal policies always use TimeoutAction::Reject; Core's generic AutoApprove option is not accepted by the TUI.

Treat the current SRT integration as a local enforcement provider, not as the stack-wide execution contract. A3S Code owns agent policy and its BashSandbox interface. A3S Runtime owns durable, provider-neutral Task and Service lifecycle and placement. A3S Box owns OCI and stronger isolation. A release-owned support payload keeps those boundaries and leaves the existing capability/version handshake and Core contract unchanged. A3S Observer and A3S Sentry can add execution evidence and adaptive runtime enforcement as defense in depth; they do not replace the deterministic per-process sandbox boundary.

Permission Policy

permissions.tsTypeScript
const session = agent.session('/repo', {
permissionPolicy: {
deny: ['bash(rm -rf*)', 'write(**/.env*)'],
ask: ['bash(git push*)', 'bash(npm publish*)'],
allow: ['read(*)', 'grep(*)', 'glob(*)', 'bash(cargo test*)'],
defaultDecision: 'ask',
enabled: true,
},
});

Avoid permissive defaults for release or production sessions. Make dangerous commands explicit and auditable.

Hooks

Hooks are registered on a session with an event type, matcher, optional config, and handler:

TypeScript
session.registerHook(
'observe-secret-read',
'pre_tool_use',
{ pathPattern: '**/.env*' },
{ priority: 100 },
() => ({ action: 'continue' }),
);
console.log(session.hookCount());
session.unregisterHook('observe-secret-read');

Verification

Verification reports and summaries are available from the session and selected result fields. Release workflows should require tests, package checks, CI checks, and provider evidence.