Sections in this lesson
Sandbox, Egress & Execution Isolation
Avoid exposing shell, arbitrary file access and generic network execution when the task does not need them.
Reviewed: · Content owner: Interview Preparator
What you will learn
- A missing tool is a useful boundary
- Enforce outside the process
- Test the actual runtime boundary
Before you start
The flow
- 1.Identify scope
- 2.Inspect evidence
- 3.Apply host control
- 4.Run negative cases
- 5.Compare benign behavior
- 6.Review remaining risks
A missing tool is a useful boundary
Avoid exposing shell, arbitrary file access and generic network execution when the task does not need them. The teaching host has only two fixed plan operations, reducing the ways an injected proposal can affect the environment.
A policy allowlist is not a sandbox for arbitrary untrusted code. If code execution is required, use an isolated worker with constrained identity, filesystem, network and resources.
Enforce outside the process
Node permission features, container flags and application URL checks have different threat models. A malicious process with broad OS credentials cannot be contained by an instruction saying not to read a file.
Real egress controls must consider DNS/IP changes, redirects, proxies and allowed destinations. A hostname predicate illustrates only one layer; the fixture performs no external fetch and claims no network containment test.
Test the actual runtime boundary
Use controlled denied-resource probes and positive authorized probes in the deployed isolation environment. Verify what happens on timeout, worker crash and cleanup, and keep host credentials outside the worker.
This curriculum supplies the control design and narrow-host regression, not a production sandbox deployment. Do not label the lab safe for arbitrary user code or substitute cooperative cancellation for isolation.
Try it
import { authorize, payloadDigest } from './policy.mjs';// Teaching host: no shell, network, or arbitrary-file tools are exposed.export class TeachingHost { constructor({ scope, resource, grant, maxCalls = 3, maxTokens = 100, deadline = 1000, epoch = 1 }) { if (!Number.isSafeInteger(maxCalls) || maxCalls < 1 || !Number.isSafeInteger(maxTokens) || maxTokens < 1 || !Number.isFinite(deadline)) throw new Error('Invalid budget'); this.scope = Object.freeze({ ...scope }); this.resource = structuredClone(resource); this.grant = grant ? structuredClone(grant) : null; this.maxCalls = maxCalls; this.maxTokens = maxTokens; this.deadline = deadline; this.epoch = epoch; this.calls = 0; this.tokens = 0; this.mutations = 0; this.receipts = new Map(); this.trace = []; } execute(call, callId, reservedTokens, now) { if (!Number.isSafeInteger(reservedTokens) || reservedTokens < 1 || !Number.isFinite(now) || !/^[a-z0-9-]{1,80}$/.test(callId)) throw new Error('Invalid operation'); if (now >= this.deadline) return this.record('TIMEOUT'); const permission = authorize(this.scope,call,this.resource,this.grant,now,this.epoch); if (permission !== 'ALLOW') return this.record(permission); const digest = payloadDigest(call); const cached = this.receipts.get(callId); if (cached) return this.record(cached.digest === digest ? 'REPLAY' : 'PAYLOAD_MISMATCH'); if (this.calls >= this.maxCalls || reservedTokens > this.maxTokens - this.tokens) return this.record('BUDGET_EXCEEDED'); this.calls++; this.tokens += reservedTokens; if (call.action === 'completePlan') this.mutations++; this.receipts.set(callId,{ digest }); return this.record('EXECUTED'); } record(status) { this.trace.push({ status, calls:this.calls, tokens:this.tokens, mutations:this.mutations }); return status; } stopAndRevoke() { this.epoch++; this.grant = null; }}// Cache keys include authorization scope and corpus version; cache values still// require current authorization at read time (revocation/deletion can change).export function cacheKey(scope, corpusVersion, question) { return JSON.stringify([scope.tenant,scope.user,corpusVersion,question]); }export function memoryRead(record, scope, version) { return record.tenant === scope.tenant && record.user === scope.user && record.conversation === scope.conversation && record.trusted === true && record.version === version ? record.text : null;}Run npm run examples:security and npm run eval:security. This source is a deterministic teaching fixture; it does not prove live model safety, NLI, production auth or OS/network isolation.
Interview questions
What boundary matters in Sandbox, Egress & Execution Isolation?
A policy allowlist is not a sandbox for arbitrary untrusted code. If code execution is required, use an isolated worker with constrained identity, filesystem, network and resources.
What does the executable fixture demonstrate?
Real egress controls must consider DNS/IP changes, redirects, proxies and allowed destinations. A hostname predicate illustrates only one layer; the fixture performs no external fetch and claims no network containment test.
What remains a production integration responsibility?
This curriculum supplies the control design and narrow-host regression, not a production sandbox deployment. Do not label the lab safe for arbitrary user code or substitute cooperative cancellation for isolation.
Practice
Extend one negative scenario and its authorized positive counterexample for Sandbox, Egress & Execution Isolation.
Check your solution
- State the trusted input and effect boundary.
- Assert the expected status and observed effect.
- Report coverage and limitations without claiming production readiness.
Official references
Continue learning
Category sequence
AI Security
Lesson 12 / 14
Was this lesson useful?
Change notes: 2026-10-31: security/reliability curriculum and source-bound fixture.