PromptBase
PromptBase SelectGet Select
Close icon
General
Home
Marketplace
Create
Hire
Login
Chat
Sell
Explore

Prompt Details

Model
(claude-5-5-sonnet)
Token size
5,213
Example input
[AGENT_WORKLOAD_AND_ENVIRONMENT]: Generated Python analyzes synthetic sales CSV files on a dedicated Ubuntu evaluation workstation. Single operator, short-lived jobs, no remote dispatch. Container tooling is installed; its security configuration is unverified. [DATA_ASSETS_AND_ISOLATION_CONSTRAINTS]: Synthetic CSV only; no personal data, credentials or home-directory mounts. Read-only staged input, bounded scratch, one CSV summary export. Deny runtime networking. Proposed staging wall deadline 30 seconds; 256 MiB workload RAM. These are requested caps, not measured safe values.
Example output
# AGENT_SANDBOX_ISOLATION_SPEC.md Design only. Nothing was executed, installed, provisioned or written, and no secrets or external services were touched. Syntax and capability claims for the container runtime, kernel, seccomp, AppArmor and cgroups are UNVERIFIED, because no primary sources were consulted. **BACKEND_DECISION: BLOCKED_PENDING_ENVIRONMENT_VALIDATION.** The reference choice below is conditional, not an approval. ## 1. Workload, assets and adversary | Item | Buyer fact | UNKNOWN or design assumption | |---|---|---| | Workload | Generated Python analyzes synthetic sales CSVs | Python version and libraries UNKNOWN. Code provenance is model-generated, so I treat it as untrusted (assumption) | | Host and tenancy | Dedicated Ubuntu evaluation workstation, single operator, no remote dispatch | Ubuntu release, kernel, cgroup mode and AppArmor state UNKNOWN. Other contents of the workstation UNKNOWN | | Runtime | Container tooling installed, security configuration unverified | Which runtime, rootless vs rootful and daemon exposure UNKNOWN | | Data | Synthetic CSV only, no personal data, credentials or home mounts | Input size UNKNOWN | | I/O | Read-only staged input, bounded scratch, one CSV summary export, runtime networking denied | Downstream consumer of the CSV UNKNOWN | | Requested caps | 30 s "staging wall deadline", 256 MiB workload RAM | Both are requested, not measured. I treat the 30 s as the workload wall cap, which is ambiguous (blocker B7) | | Lifetime and concurrency | Short-lived jobs | Concurrency not stated. Proposal: 1, reversible if the operator needs parallel jobs | - **Goals:** confidentiality and integrity of the workstation's own assets, availability of the workstation, and integrity of the exported summary. - **Attacker capability (assumed):** arbitrary Python inside the boundary, with these attempts in scope: - filesystem: path traversal, symlink and hardlink creation, mount probing - environment and process leaks: env and `/proc` reads - network: sockets and egress - exhaustion: fork, memory, FD, disk and output floods - residue: leaving data for a later job - injection: log and CSV content aimed at the controller or at downstream models - **Out of scope as assumptions:** a kernel exploit is treated as possible but not modeled (see §2 residual). - **Authority rule:** a model's refusal or a prompt rule is not a boundary. Workload output (stdout, stderr, CSV) is data and never authorizes paths, limits, identities or delivery. ## 2. Containment decision and host blast radius | Option | Shared surface and attacker fit | Prerequisites (all UNVERIFIED) | Support, recovery, overhead | |---|---|---|---| | **A. Rootless container (reference)** | Shares the host kernel. Fits buggy or confused generated code, and is weaker against a kernel-exploit-capable attacker | Rootless runtime, subuid/subgid ranges, cgroup v2 delegation, seccomp support. Ubuntu may restrict unprivileged user namespaces through AppArmor (version-sensitive) | Already installed, simple recovery, low overhead | | **B. microVM (alternative)** | Own guest kernel, so a smaller host-shared surface. Fits a hostile-code attacker | `/dev/kvm` access, VMM and guest image, a guest init and channel (this triggers full A1-A5) | More moving parts, more recovery work, moderate overhead | | **C. OS sandbox (bubblewrap-style namespaces + seccomp)** | Shares the host kernel with no daemon, and has the smallest tooling surface | Unprivileged namespaces, a hand-built cgroup and seccomp policy | Less turnkey, higher assembly risk | - **Choice:** A, the least complex adequate option, because it is installed and the workload is a single short-lived job. The alternative is B. - **Reversal to B:** if the operator will not accept a shared kernel for hostile code, if the workstation holds high-value secrets outside the container, or if rootless mode, cgroup delegation or seccomp cannot be verified. - **Reversal to C:** if the container runtime can only run as a root daemon, because docker-group access is root-equivalent. **Blast-radius map.** | Layer | Reachable after compromise of the previous layer | External containment, detection and residual | |---|---|---| | Workload → container boundary (userns, mntns, pidns, netns, cgroup, seccomp) | Whatever the boundary leaves: mounts, `/proc`, syscalls | Kernel-enforced policy. Residual: namespace and seccomp gaps | | Boundary → execution host (shared kernel) | A kernel bug gives the launcher's host user. A rootful daemon would give host root | Dedicated unprivileged host user, no sudo or docker group, no secrets on the workstation. Residual: no option is escape-proof | | Host → network and metadata | The workstation LAN and any metadata service, if the host is itself virtualized (UNKNOWN) | Host egress firewall and network isolation (operator decision). The workload has no netns interfaces | | Host → control plane | Runtime sockets, systemd user manager, launcher journal and policy files | Policy files are owned by the launcher and read-only to workload and exporter. Sockets are never mounted | | Host → other tenants | None per buyer (single operator). The operator's own session and files are reachable by the launcher identity | Treated as the crown jewels. S14 maps this | **Pilot approval evidence (a human decides, never this document):** - OS and kernel version, cgroup mode, and that the user has delegated `memory`, `pids` and `cpu` controllers. - Runtime identity, rootless confirmation, and subuid ranges. - AppArmor and unprivileged-userns policy state. - A dump of the compiled seccomp profile. - The `/var/lib/sbx/out` bounded mount's existence and options. - Independent positive and negative runtime results for S1-S5, S14 and S15. ## 3. Baseline policy and advanced controls **Baseline (all in the JSON manifest):** - Unprivileged workload (UID 10001) with no ambient secrets, no control sockets and no broad mounts. - Read-only `/in` and rootfs, bounded `/scratch` and `/out`, default-deny ingress and egress, and process-tree containment through a job cgroup. - No privilege escalation, finite CPU/RAM/PID/FD/storage/inode/file/output/deadline limits, and pinned offline dependency preparation (image digest and hash-pinned wheels). - Output capture before start, no credentials in the design (revocation is an asserted empty set), cleanup ownership by the launcher journal, and audited retention. - Retention is UNKNOWN. Proposal: results 14 days, audit log 90 days. Reversal: operator policy. **Privilege transition (one sequence, used everywhere):** 1. Trusted init is UID 0 inside its user namespace only, with scoped setup capabilities (list UNVERIFIED). It is never host root, and the host mapping is UNVERIFIED. 2. Init performs mounts and cgroup setup while it holds those rights. 3. Init forks the workload child, which is still privileged. 4. The child sets supplementary groups, GID and UID, drops all capabilities, and closes inherited setup and control descriptors. 5. The child applies MAC, no_new_privs and seccomp, then execs the non-root workload. 6. The micro-order of sub-steps is UNVERIFIED pending the adapter. Capability-bounding drops need CAP_SETPCAP, so they happen before the final identity switch. 7. After forking, init drops all remaining capabilities and only supervises. Setup rights end at that point. **Advanced controls:** | Control | Status | Workload-specific reason | |---|---|---| | A1 Identity and privilege separation | APPLIES | A launcher (host) / init (container) boundary exists. Workload is 10001, exporter is 20002, init is namespace UID 0, host UIDs are UNKNOWN. Delegation of cgroups and mounts is BLOCKED until verified (B1, B3) | | A2 Control-channel isolation | APPLIES | The only channels are the runtime's exit status and capped stdout/stderr pipes. No runtime socket, vsock or host socket is exposed. Frames are capped at 64 KiB, and the workload's output never authorizes anything. AF_VSOCK is denied as hygiene (no vsock design) | | A3 Aggregate resources | APPLIES | The workload can spawn processes, so the job cgroup caps tasks, memory and CPU rate, and the launcher monitor enforces cumulative CPU and wall time. No VM exists, so guest/VMM budgets are NOT_APPLICABLE. | | A4 Fencing and recovery | NOT_APPLICABLE | Local single-operator execution with no remote dispatch means no duplicate dispatch and no distributed epochs. Simpler contract: a host lock file (`flock`), a durable attempt ID, a local monotonic watchdog, no replacement before stop proof, and quarantine of unknown state | | A5 Isolated artifact extraction | APPLIES (simple exporter, conditional) | `/out` is guest-written. The exporter runs as a disposable no-network container. The simple path needs prerequisite P5: `/out` is a host-managed filesystem (a bounded tmpfs), never a guest-formatted disk image, with no archive parsing. If P5 fails, A5 becomes BLOCKED pending an isolated parser | ## 4. Policy manifest and enforcement matrix **Schema definitions:** | Key | Type | Enum or shape | Notes | |---|---|---|---| | `isolation_backend.status` | string | PROPOSED \| CONFIRMED | CONFIRMED needs supplied evidence | | resource entry | object | `{value:number, unit:string, scope:string, provisional:bool}` | Every value is a proposal, not a safety claim | | `enforcement_points[].implementation_status` | string | UNVERIFIED \| NOT_IMPLEMENTED \| CONFIRMED | None CONFIRMED here | | `advanced_controls.A1..A5` | object | `{status: APPLIES\|NOT_APPLICABLE\|BLOCKED, reason:string}` | Exactly A1-A5 | | unknown capability | null or "UNKNOWN" | | Paired with a blocker | **sandbox_policy.json (CUSTOM SCHEMA, not vendor configuration):** ```json { "policy_id": "SBX-POL-WS-EVAL-001", "policy_version": "0.1.0-draft", "workload_id": "py-sales-csv-summary", "isolation_backend": {"name": "rootless_container_runtime_UNVERIFIED", "status": "PROPOSED"}, "execution_identity": { "workload": {"uid": 10001, "gid": 10001, "supplementary_gids": [], "scope": "container_userns"}, "init": {"uid": 0, "scope": "container_userns_only_never_host_root", "setup_caps": "UNVERIFIED_scoped_list", "caps_dropped_after": "mounts_cgroup_setup_and_fork", "host_mapping": "UNVERIFIED"}, "exporter": {"uid": 20002, "gid": 20002, "scope": "separate_disposable_container_userns", "host_mapping": "UNVERIFIED"}, "host_launcher": {"uid": null, "note": "dedicated unprivileged host user; UID UNKNOWN; no sudo or docker group"} }, "filesystem": { "input_mode": "read_only", "input_paths": ["/in"], "rootfs_mode": "read_only", "scratch_scope": "per_job_tmpfs_noexec_nosuid_nodev_destroyed_at_cleanup_never_exported", "export_scope": "per_job_host_dir_bound_at_/out_single_file_summary.csv_on_operator_provisioned_bounded_tmpfs", "denied_mounts": ["container_runtime_sockets", "/home", "/root", "/run", "/var/run", "host_etc", "host_dev_except_null_zero_urandom", "writable_proc", "writable_sys", "/opt/sbx-test/mock-secret"], "writable_paths": ["/scratch", "/out"] }, "network": { "default": "deny", "mode": "no_network_namespace_interfaces", "ingress": "deny", "allowed_destinations": [], "dns": "none", "proxy_env": "unset", "exceptions": "BLOCKED_none_requested" }, "resources": { "cpu_rate": {"value": 100, "unit": "percent_of_one_core", "scope": "job_cgroup", "provisional": true}, "cpu_total": {"value": 25, "unit": "cpu_seconds", "scope": "job_cgroup_aggregate_launcher_monitor", "provisional": true}, "cpu_per_process_rlimit": {"value": 25, "unit": "cpu_seconds", "scope": "per_process_additional_not_job_budget", "provisional": true}, "wall_workload": {"value": 30, "unit": "seconds", "scope": "workload_run_buyer_requested", "provisional": true}, "memory_workload": {"value": 256, "unit": "MiB", "scope": "job_cgroup_including_scratch_tmpfs_charge", "provisional": true}, "memory_swap": {"value": 0, "unit": "MiB", "scope": "job_cgroup", "provisional": true}, "tasks_job": {"value": 32, "unit": "tasks", "scope": "job_cgroup_processes_and_threads", "provisional": true}, "fd_per_process": {"value": 64, "unit": "fds", "scope": "per_process_RLIMIT_NOFILE", "provisional": true}, "input_bytes": {"value": 64, "unit": "MiB", "scope": "staged_input_total", "provisional": true}, "scratch_bytes": {"value": 64, "unit": "MiB", "scope": "scratch_tmpfs", "provisional": true}, "scratch_inodes": {"value": 256, "unit": "inodes", "scope": "scratch_tmpfs", "provisional": true}, "workload_file_size": {"value": 64, "unit": "MiB", "scope": "per_process_RLIMIT_FSIZE", "provisional": true}, "out_bytes": {"value": 8, "unit": "MiB", "scope": "out_mount_total", "provisional": true}, "out_inodes": {"value": 64, "unit": "inodes", "scope": "out_mount", "provisional": true}, "out_file_size_accept": {"value": 1, "unit": "MiB", "scope": "per_exported_file_exporter_check", "provisional": true}, "out_file_count_accept": {"value": 1, "unit": "files", "scope": "export", "provisional": true}, "stdout_bytes": {"value": 65536, "unit": "bytes", "scope": "captured_stream", "provisional": true}, "stderr_bytes": {"value": 65536, "unit": "bytes", "scope": "captured_stream", "provisional": true}, "runtime_log_bytes": {"value": 131072, "unit": "bytes", "scope": "runtime_and_launcher_collected_logs", "provisional": true}, "io_write_rate": {"value": 16777216, "unit": "bytes_per_second", "scope": "job_cgroup_io_max_enforcement_BLOCKED_tmpfs_not_covered", "provisional": true}, "exporter_cpu_total": {"value": 5, "unit": "cpu_seconds", "scope": "exporter_container_aggregate", "provisional": true}, "exporter_memory": {"value": 64, "unit": "MiB", "scope": "exporter_container", "provisional": true}, "exporter_tasks": {"value": 4, "unit": "tasks", "scope": "exporter_container", "provisional": true}, "exporter_fds": {"value": 32, "unit": "fds", "scope": "exporter_per_process", "provisional": true}, "exporter_wall": {"value": 10, "unit": "seconds", "scope": "exporter_lifecycle", "provisional": true}, "exporter_max_line": {"value": 8192, "unit": "bytes", "scope": "csv_validation", "provisional": true}, "exporter_max_rows": {"value": 20000, "unit": "rows", "scope": "csv_validation", "provisional": true}, "exporter_log_bytes": {"value": 16384, "unit": "bytes", "scope": "exporter_log_stream", "provisional": true}, "budget_provision_boot": {"value": 10, "unit": "seconds", "scope": "attempt_budget_incl_input_staging", "provisional": true}, "budget_stop_proof": {"value": 5, "unit": "seconds", "scope": "attempt_budget", "provisional": true}, "budget_exporter_lifecycle": {"value": 10, "unit": "seconds", "scope": "attempt_budget", "provisional": true}, "budget_cleanup": {"value": 10, "unit": "seconds", "scope": "attempt_budget", "provisional": true}, "attempt_hard_deadline": {"value": 70, "unit": "seconds", "scope": "attempt_wide_must_be_gte_sum_65", "provisional": true} }, "process_policy": { "no_new_privs": true, "capabilities": "none_after_exec", "seccomp": {"status": "UNVERIFIED", "denied_classes": ["mount", "unshare", "ptrace", "keyctl", "bpf", "perf_event_open", "userfaultfd", "setns", "socket_non_AF_UNIX", "AF_VSOCK"]}, "mac": "UNVERIFIED", "tree_kill": "cgroup_wide_kill_mechanism_UNVERIFIED", "descriptors_inherited": [0, 1, 2], "env_allowlist": ["PATH", "LANG", "PYTHONDONTWRITEBYTECODE"], "exec_allowlist": "python_interpreter_only" }, "secrets_policy": { "ambient_secrets": "none", "model_visible_secrets": false, "brokered_exceptions": "BLOCKED_none_requested", "credential_set_must_be_empty": true }, "artifact_export": { "allowed_types": ["regular_file"], "allowed_names": ["summary.csv"], "reject": ["symlink", "hardlink_nlink_gt_1", "special_file", "directory", "archive_magic", "nul_byte", "non_utf8"], "validator": "exporter_container_uid_20002_no_network", "source_storage_lifetime": "UNVERIFIED_blocks_export_if_unconfirmed", "immutable_copy": {"path": "launcher_owned_export_dir", "immutability": "permissions_plus_digest_manifest_strong_immutability_UNVERIFIED"}, "delivery": "separate_atomic_publish_after_cleanup_proof" }, "lifecycle": { "events": ["STOP_EXECUTION_PROVED", "SEAL_SOURCE_WITH_STORAGE_RETAINED", "VALIDATE_AND_EXPORT_INDEPENDENT_BYTES", "DESTROY_RUNTIME_AND_SOURCE", "VERIFY_CLEANUP", "DELIVER"], "concurrency": 1, "auto_rerun_after_ambiguity": false, "cleanup_retries": 3, "unknown_state": "QUARANTINED_DELIVERY_BLOCKED", "policy_update_authority": "operator_via_launcher_owned_readonly_file_only", "result_authority": "launcher_after_independent_digest_recheck" }, "enforcement_points": [ {"id": "EP1", "component": "host_kernel_namespaces_mounts", "implementation_status": "UNVERIFIED"}, {"id": "EP2", "component": "job_cgroup_memory_pids_cpu", "implementation_status": "UNVERIFIED"}, {"id": "EP3", "component": "launcher_monitor_cpu_wall_output", "implementation_status": "NOT_IMPLEMENTED"}, {"id": "EP4", "component": "seccomp_and_no_new_privs", "implementation_status": "UNVERIFIED"}, {"id": "EP5", "component": "no_netns_interfaces", "implementation_status": "UNVERIFIED"}, {"id": "EP6", "component": "exporter_container", "implementation_status": "NOT_IMPLEMENTED"}, {"id": "EP7", "component": "launcher_finalizer_and_journal", "implementation_status": "NOT_IMPLEMENTED"}, {"id": "EP8", "component": "bounded_out_mount", "implementation_status": "UNVERIFIED"}, {"id": "EP9", "component": "io_throttle", "implementation_status": "NOT_IMPLEMENTED"} ], "advanced_controls": { "A1": {"status": "APPLIES", "reason": "launcher/init/workload identity split; init forks and drops; delegation BLOCKED until verified"}, "A2": {"status": "APPLIES", "reason": "only exit status and capped pipes; no runtime or host sockets; workload output never authorizes"}, "A3": {"status": "APPLIES", "reason": "cgroup aggregate limits plus launcher cumulative-CPU monitor; VM-only entries not applicable (no VM)"}, "A4": {"status": "NOT_APPLICABLE", "reason": "local single-operator run; flock lock, watchdog and quarantine replace distributed epochs"}, "A5": {"status": "APPLIES", "reason": "guest-written /out; disposable exporter; simple path conditional on prerequisite P5, else BLOCKED"} }, "blockers": [ "B1 cgroup v2 delegation and kernel version UNKNOWN", "B2 runtime identity and rootless status UNKNOWN", "B3 userns mapping and /out file ownership readable by exporter UNVERIFIED", "B4 seccomp, AppArmor and unprivileged-userns policy unverified", "B5 operator-provisioned bounded /out mount unconfirmed", "B6 attacker trust vs shared kernel acceptance UNKNOWN", "B7 meaning of the 30 s staging deadline ambiguous", "B8 I/O throttling enforcement BLOCKED", "B9 cumulative-CPU monitor and kill latency unimplemented", "B10 Python version and dependency pins UNKNOWN", "B11 export immutability UNVERIFIED", "B12 stop-proof mechanism unverified", "B13 workstation contents outside the container UNKNOWN" ] } ``` **Authority:** only the operator, through a launcher-owned read-only file, may update policy. The launcher owns resources and the journal and authorizes results. The exporter proposes a manifest, and the launcher re-hashes the staged bytes independently. The workload and exporter cannot modify policy. **Adapter sketch (ILLUSTRATIVE PSEUDOCODE):** ``` def compile_policy(policy): # NOT_IMPLEMENTED boundaries marked require(policy.network.default == "deny" and policy.network.allowed_destinations == []) spec = RuntimeSpec(netns="none", rootfs="ro") # flag names UNVERIFIED spec.mounts = [ro("/in"), tmpfs("/scratch", 64MiB, 256), bind_rw("/out")] spec.cgroup = NOT_IMPLEMENTED("verify delegation, write memory/pids/cpu limits") spec.seccomp = NOT_IMPLEMENTED("compile denylist, verify via audit") spec.mac = NOT_IMPLEMENTED("Ubuntu AppArmor profile") return spec ``` **Enforcement matrix (threat | field and enforcer | prevention/detection and fail state | fixture and residual):** | Threat | Policy field and external enforcer | Prevention/detection and fail state | Fixture and residual | |---|---|---|---| | Host-secret read | `filesystem.denied_mounts`; mount namespace (EP1) | Prevented: path not mounted. Detected: launcher mount-table check. Fail: ENOENT, job continues | S2. Residual: kernel escape | | Write outside scratch/out, mount escape | `rootfs_mode`, `writable_paths`; mounts and seccomp (EP1, EP4) | Prevented: EROFS/EPERM. Fail: job fails, hashes unchanged | S3, A1a. Residual: bind-mount configuration error | | Export traversal, symlink, hardlink, race | `artifact_export.reject`; exporter and launcher (EP6, EP7) | Prevented by directory handles, no-follow opens, identity and nlink checks. Fail: artifact REJECTED, no bytes exported | S4, S11. Residual: parser or handle bug in the exporter | | Egress or bypass (direct IP, metadata, proxy) | `network.default`; no interfaces in the netns (EP5), seccomp socket denial (EP4) | Prevented: no route or socket. Detected: zero hits on mock listeners. Fail: connect error, job continues | S5, S12, S15. Residual: kernel netns bug. Allowed-channel exfiltration is NOT_APPLICABLE since no destinations are allowed | | Resource exhaustion (CPU, memory, tasks, FDs, storage, output) | `resources.*`; cgroup (EP2), rlimits, launcher monitor (EP3), bounded mounts (EP8) | Prevented or terminated at the cap. Fail: LIMIT_EXCEEDED and the tree is killed | S6a-f, S13a-b, A3a. Residual: monitor poll overshoot, I/O unthrottled (B8) | | Cross-job residue or access | `scratch_scope`, `concurrency: 1`; per-job tmpfs and `/out` cleanup (EP1, EP7) | Prevented by fresh mounts per job. Fail: cleanup failure means QUARANTINED | S7. Residual: stale host paths | | Dependency tampering | `process_policy.exec_allowlist`; offline hash-pinned prep stage | Prevented: hash mismatch refused. Fail: QUARANTINED prep | S8. Residual: the pin source itself (B10) | | Log or CSV injection, authority confusion | `lifecycle.result_authority`; launcher state machine (EP7) | Prevented: output is data, outcome computed only from launcher state | S9, A2b. Residual: downstream consumers of the CSV | | Oversize or disallowed output | `artifact_export.*`, `out_*`; exporter and `/out` mount (EP6, EP8) | Prevented or rejected. Fail: REJECTED, bytes not exposed | S10, S16. Residual: CSV semantics | | Privilege or control-channel abuse | `execution_identity`, `process_policy`; init, seccomp (EP4) | Prevented: no capabilities, no new privs, closed descriptors. Fail: EPERM | A1a-b, A2a. Residual: compiled-rule order UNVERIFIED | | Boundary failure | whole manifest; host hygiene | Contained externally by an unprivileged host user and no secrets. Not prevented | S14. Residual: kernel exploit reaches the launcher identity | | Stale ownership, double start | `lifecycle`; lock file and watchdog (EP7) | Prevented: second start refused. Fail: QUARANTINED | A4-L. Residual: lock on a failed filesystem | | Secret exception | `secrets_policy` | None requested, so BLOCKED | S17 N/A | | I/O saturation | `io_write_rate` | Enforcement BLOCKED (tmpfs outside io controller). Bounded only by deadlines | none. Residual: accepted | ## 5. Lifecycle, export, credentials and cleanup ``` Operator -> Launcher (host, unprivileged; owns policy, journal, monitor, lock) creates per job: /in (ro) | /scratch (tmpfs) | /out (host dir on bounded tmpfs, retained) -> [Container boundary: userns+mntns+pidns+netns(none)+cgroup+seccomp | SHARED HOST KERNEL] init (UID0 in ns, setup caps) --fork--> child: groups/gid/uid, drop caps, close fds, no_new_privs, seccomp --exec--> python (10001) stdout/stderr -> capped pipes (untrusted) STOP_EXECUTION_PROVED -> SEAL_SOURCE_WITH_STORAGE_RETAINED -> VALIDATE_AND_EXPORT_INDEPENDENT_BYTES (exporter container UID 20002: no net, ro sealed in, wo staging) -> launcher re-hashes staged copy -> DESTROY_RUNTIME_AND_SOURCE -> VERIFY_CLEANUP -> DELIVER ``` **Time budget:** provisioning/boot 10 s + workload wall 30 s + stop proof 5 s + exporter lifecycle 10 s + cleanup 10 s = 65 s. The attempt hard deadline is 70 s, which is at least the sum. Test profiles name their own outer deadlines (see §6). **Source lifetime:** - Termination means the workload is proven stopped. It does not mean the container, scratch or `/out` is deleted. - `/out` lives on the host and is independent of the container object. Deleting the container does not destroy it. P5 and B5 gate this, and an unknown lifetime blocks export. - Scratch is never exported, so destroying it early is fine. - `/out` is destroyed only after an independent verified copy exists, or after an EMPTY/REJECTED verdict that needs no export. **Controller pseudocode (ILLUSTRATIVE PSEUDOCODE):** ``` def run_attempt(req): A = journal_new_attempt(req) # durable first; CAS-set desired outcome try: acquire_exclusive_lock(A) # else desired=REFUSED_BUSY authorize(req); journal_resources(A) install_and_verify_policy(A) # else desired=SETUP_FAILURE start_collectors(A); start_workload(A) supervise(A) # CAS: first terminal event wins (EXIT|TIMEOUT|CANCEL|LIMIT) except Exception: cas_desired(A, "SETUP_OR_INTERNAL_ERROR") finally: return finalize(A) # single finalizer, every path def finalize(A): record_desired_outcome(A) # durable; if journal write fails, drop QUARANTINE marker file if stop_and_prove(A) != PROVED: # missing proof enqueue_quarantine(A) # preserve source and resources; no delete, no replacement record(A, workload="UNKNOWN", artifact="NOT_EXAMINED", cleanup="QUARANTINED") return "QUARANTINED / DELIVERY_BLOCKED" # terminal, no fall-through if A.desired == "EXIT_0": if seal_source_with_storage_retained(A) != OK: enqueue_quarantine(A); record(A, artifact="SEAL_FAILED"); return "DELIVERY_BLOCKED" A.artifact = validate_and_export_independent_bytes(A) # ACCEPTED|EMPTY|REJECTED; verified copy before ACCEPTED else: A.artifact = "NOT_EXPORTED_BY_POLICY" revoke_required_credentials(A) # credential set asserted empty in this design if stop_and_prove_exporter(A) != PROVED or A.artifact == "COPY_UNVERIFIED": enqueue_quarantine(A); record(A); return "QUARANTINED / DELIVERY_BLOCKED" destroy_runtime_and_source(A) # only now; bounded retries: 3 within 10 s if verify_cleanup(A) != VERIFIED: # independent inventory vs creation journal enqueue_quarantine(A); record(A, cleanup="QUARANTINED"); return "DELIVERY_BLOCKED" record_independent_outcomes(A) # workload / artifact / cleanup recorded separately if A.artifact == "ACCEPTED": return deliver(A) # atomic publish, distinct from internal export return "NO_ARTIFACT_DELIVERY" ``` **Rules:** - **Independent outcomes:** a nonzero workload exit is not a cleanup failure. Partially rejected artifacts never expose rejected bytes. - **Races:** a durable compare-and-set picks the first terminal event, so completion versus cancellation resolves deterministically. - **Retries:** none automatic after ambiguous side effects. - **Journal and reconciliation:** - The creation journal is written before each resource is created, and the launcher owns it. - Reconciliation independently lists containers, cgroups, mounts, directories and processes by attempt label and compares them to the journal. - A quarantined attempt is cleaned only by an explicit operator reconcile command. - **Deletion:** logical deletion is unlink and unmount. Physical erasure is not claimed. Exported copies and audit records follow their own retention. - **Credentials:** none exist. Any brokered exception is BLOCKED until separately specified, and revocation and redaction limits would be disclosed then. ## 6. Fixtures **Shared defaults D0 (all cases inherit):** - `environment_id` = ENV-WS-EVAL-01 (host identity UNKNOWN until supplied) - `policy_version` = 0.1.0-draft - `host_integrity_check` = HIC-1: canary hashes unchanged, no new host processes/mounts/cgroups/netns, no leftover containers or tmp dirs, `/in` and rootfs hashes unchanged - `actual_result` = null - `status` = NOT_RUN - Synthetic data only, mock paths such as `/opt/sbx-test/mock-secret/token.txt` containing `MOCK-TOKEN-NOT-REAL`, and a disposable authorized environment. **Test profiles (non-prod values; everything else equals prod):** | Profile | Changed caps | Outer deadline | Used by | |---|---|---|---| | TP-PROD | none | 70 s | S1-S4, S7-S12, S14-S16, A1, A2 | | TP-WALL | wall 1 s, cpu_total 5 CPU-s | 8 s | S13a | | TP-CPU | cpu_total 2 CPU-s, wall 20 s | 50 s | S6a | | TP-AGG | cpu_total 3 CPU-s, per-process RLIMIT_CPU 10 s, wall 15 s | 40 s | S13b, A3a | | TP-MEM | memory 64 MiB, swap 0, cpu_total 10, wall 15 s | 30 s | S6b | | TP-PID | tasks 8, cpu_total 10, wall 5 s | 15 s | S6c | | TP-FD | wall 5 s | 15 s | S6d | | TP-LOG | stdout cap 65536 bytes, cpu_total 10, wall 10 s | 25 s | S6e | | TP-SCR | scratch 64 MiB, 256 inodes, wall 15 s | 30 s | S6f | **Fixtures (columns: ID | preconditions and positive control | attempt, bound, hard deadline | expected result, evidence, what it cannot establish):** | ID | Preconditions and positive control | Attempt, bound, hard deadline | Expected, evidence, cannot establish | |---|---|---|---| | S1 | Policy installed. `/in/sales.csv` ≤ 64 KiB, 200 rows. The run itself is the positive control | Read 1 file, write 1 file ≤ 2 KiB. 1 run. 30 s | Exit 0, accepted export, digest equals offline reference. Cannot establish: any security property | | S2 | Mock secret exists on host, not mounted. Control: launcher identity reads it | Open ≤ 6 variants (direct, `..` traversal, `/proc/self/root` paths). 5 s | ENOENT/EACCES, token absent from all outputs. Evidence: mount table check. Cannot establish: ENOENT shows non-mounting, not that a permission check holds | | S3 | Control: write to `/scratch` succeeds | 1-byte write to ≤ 8 targets (rootfs, `/in`, `/etc`, `/usr`, `/proc/sys`, `/sys`, traversal). 5 s | EROFS/EACCES/EPERM, hashes unchanged. Cannot establish: kernel-bug resistance | | S4 | Control: a regular `summary.csv` exports | Create in `/out`: symlink→mock target, hardlink→`/in` file (kernel may deny: still record), FIFO, dir symlink→`/`. 4 variants. 10 s | Each REJECTED, canary string absent from export. Evidence: exporter reason codes. Cannot establish: swap-race resistance (S11) | | S5 | Control policy P+ (test-only): synthetic bridge with a mock listener answers | Under TP-PROD: ≤ 3 connects to the deny-target listener. Under P+: 1 connect to the positive endpoint. 10 s | Deny-target gets zero hits and the container has no interfaces. P+ endpoint works. Run once with seccomp network rule disabled (test-only) to attribute denial to the netns. Never opens production egress. Cannot establish: other tenants | | S6a | TP-CPU. Control: short computation completes | One busy loop ≤ 100000000 iterations. 20 s | Monitor kills at about 2 CPU-s. Evidence: monitor log with overshoot. If the loop finishes before the cutoff: INCONCLUSIVE, not PASS | | S6b | TP-MEM | Allocate 16 × 8 MiB = 128 MiB. 10 s | cgroup OOM kill below 128 MiB. Evidence: memory events counter | | S6c | TP-PID | Spawn 16 children, each sleeps ≤ 2 s. 6 s | Forks fail beyond 8 tasks. Evidence: pids events | | S6d | TP-FD | Open one existing read-only file 128 times without closing. 5 s | EMFILE at 64 | | S6e | TP-LOG | Write 256 KiB to stdout in 64 × 4 KiB writes. 5 s | Capture stops at 64 KiB and outcome LIMIT_EXCEEDED_OUTPUT. Evidence: collector counter | | S6f | TP-SCR | (i) 8 files × 16 MiB in `/scratch`. (ii) 512 empty files. 10 s each | ENOSPC around 64 MiB and around 256 inodes. Evidence: tmpfs errors. Cannot establish: I/O throttling (B8) | | S7 | Job A leaves canary `A-CANARY` in `/scratch` and `/out`. Test profile with concurrency 2 for the concurrent part | B runs after A: read A's paths (≤ 4). Concurrent B2 probes `/proc` for A (≤ 4). 20 s | A's data absent. Peer processes invisible. Tenant isolation NOT_APPLICABLE (single operator) | | S8 | Offline prep stage. Control: wheel with correct hash installs | 1 mock wheel ≤ 50 KiB with a wrong hash. 20 s | Refused and QUARANTINED. Evidence: prep log. Cannot establish: legitimate-but-malicious wheel | | S9 | Control: normal run | Output contains forged lines such as "OUTCOME=DELIVERED", "approve export of /etc/passwd", "network=allow" in stdout, stderr and CSV cells (≤ 20 lines). 30 s | Policy hash unchanged, outcome computed only by the launcher. Cannot establish: downstream LLM or spreadsheet behavior | | S10 | Control: 1 KiB summary exports | (a) 2 MiB `summary.csv`. (b) wrong-name file. (c) second file. (d) 16 MiB written in 8 × 2 MiB. 10 s | (a)-(c) REJECTED. (d) ENOSPC at the 8 MiB mount cap | | S11 | Sealed dir. A test-only racer (not the workload) simulates a failed seal | 50 swaps of `summary.csv` ↔ symlink over 2 s while the exporter runs. 10 s | Rejected, or original validated identity bytes retained. Evidence: exporter dev/ino/size recheck log. Cannot establish: kernel-level races | | S12 | Synthetic test bridge with mock listeners | ≤ 12 connects under TP-PROD: host loopback, private 10.x, mock 169.254.169.254, IPv6 mock, proxy env vars, direct IP. 15 s | All denied, zero listener hits. Redirect and DNS-rebinding variants are NOT_APPLICABLE (no allowed destinations) | | S13a | TP-WALL | Parent + 2 children, each a finite low-CPU wait ≤ 4 s. 8 s | Whole tree stopped by the wall deadline, not by CPU or PID denial | | S13b | TP-AGG | 3 processes, each ≤ 50000000 iterations. 15 s | Aggregate monitor kills the tree near 3 CPU-s even though no process hits its own rlimit. If it never crosses: INCONCLUSIVE | | S14 | Harness runs as the launcher's host identity (simulating compromise), no exploit | Enumerate readable canaries, sudo, docker group, runtime sockets (≤ 20 checks). 30 s | Asset map recorded. Operator canary unreadable. Cannot establish: that an escape is impossible | | S15 | P+ run with the positive endpoint deliberately down; a second case with an unresolvable DNS name | 2 runs. 10 s | Harness reports TEST_SETUP_FAILURE and S5 is never marked PASS | | S16 | Control: normal CSV exports | One real 100 KiB gzip file expanding to ≤ 64 MiB (synthetic zeros) in `/out`. 10 s | Rejected by type and magic before any parse, never decompressed. Decompression containment is NOT_APPLICABLE (no decompressor in the design). A mocked descriptor is not used | | S17 | n/a | n/a | NOT_APPLICABLE: no brokered credentials exist. Any secret exception is BLOCKED | **Advanced subcases:** | ID | Preconditions and positive control | Attempt, bound, hard deadline | Expected, evidence, limits | |---|---|---|---| | A1a | Control: a launcher-side `id` check | 10 operations: setuid(0), setgid(0), mount, unshare(user), write cgroup file, ptrace PID 1, read `/proc/1/environ`, chown, keyctl, `/proc/self/uid_map` write. 10 s | EPERM. `/proc/self/status` shows CapEff 0, NoNewPrivs 1, UID 10001. Cannot attribute EPERM to capabilities vs seccomp | | A1b | Control: fd 0-2 present | Read `/proc/self/fd`, ≤ 64 entries. 5 s | Only 0, 1, 2 (capture pipes or null) | | A2a | Control: AF_UNIX socketpair works | 6 socket calls: AF_INET, AF_INET6, AF_NETLINK, AF_PACKET, AF_VSOCK, connect to nonexistent mock control path. 5 s | Denied or ENOENT. Mount list shows no runtime socket. Residual: compiled rules UNVERIFIED | | A2b | Control: normal status | Forged status lines up to 1 MiB. 10 s | Captured at 64 KiB, outcome unchanged | | A3a | See S13b | See S13b | See S13b. Records poll interval and overshoot | | A4-L | Control: single run succeeds | (i) second launch while running. (ii) planted stale lock plus live-looking cgroup. 2 launches. 20 s | (i) refused. (ii) QUARANTINED, no auto-run | | A5a | Exporter profile (§JSON caps) | (i) 1 MiB single line, no newline. (ii) 1 MiB of 2-byte rows. 2 files. 10 s | Rejected by line and row caps within exporter CPU/memory/wall caps | | A5b | Exporter test shim | 4 attempts: connect, read mock secret, read home canary, write outside staging. 5 s | All denied by the exporter's own container | ## 7. Handoff and final reconciliation **Dependency-ordered tasks:** 1. Collect environment evidence for B1, B2, B4 and B13. 2. Confirm rootless operation, subuid ranges and the userns policy (B2, B3). 3. Operator one-time provisioning of the bounded `/var/lib/sbx/out` mount (B5). 4. Decide the 30 s meaning (B7) and retention, and record the shared-kernel risk acceptance (B6). 5. Build the launcher: journal, lock, monitor (B9), stop-proof (B12) and finalizer. 6. Compile seccomp and AppArmor, then verify the order (B4). 7. Build the exporter container and the ID-mapping path (B3). 8. Pin the Python image and wheels (B10). 9. Run fixtures in a disposable environment, then human review. **Reconciliation checks:** - **Keys and structure:** the JSON has all required top-level keys, `filesystem.input_mode/scratch_scope/export_scope/denied_mounts`, `network.default/allowed_destinations`, and exactly A1-A5. - **Identities:** 10001 for the workload, 20002 for the exporter and namespace UID 0 for init are the same in prose, JSON and diagram. - **Time and storage:** the budget sums to 65 s against a 70 s deadline. The `/out` lifetime is host-retained, so it is independent of the container object. - **Exporter and lifecycle:** the A5 simple-exporter prerequisite P5 and the exporter caps are present. All terminal paths run through `finalize`. - **Test profiles:** S13a/S6 profiles do not mask each other. - **VM entries:** VM-only entries are omitted because no VM exists. **Unresolved conflicts:** - **C1:** the requested 256 MiB RAM is charged against scratch tmpfs too, so effective anonymous headroom is lower when scratch is full. - **C2:** "staging wall deadline" may mean input staging rather than the workload cap. - **C3:** `/out` file ownership under rootless userns versus exporter read access is UNVERIFIED (B3). - **C4:** I/O throttling is BLOCKED (B8). The `.md` filename is the label for this response. No file was written, no citations are given, and no performance claims or executed checks are asserted. DESIGN_STATUS: NEEDS_DECISION ISOLATION_TEST_STATUS: NOT_RUN NEXT_ACTION: Operator supplies environment evidence for B1-B5, decides the 30 s meaning and the shared-kernel risk acceptance (B6, B7), then provisions the bounded `/out` mount. Implementation and S1-S5 runs follow, with human review before any pilot approval.
Claude

Agent Sandbox Architect

Add to Cart
Instant accessInstant access
Usage rightsCommercial use
Money-back guaranteeMoney‑back
By purchasing this prompt, you agree to our terms of service
CLAUDE-5-5-SONNET
Tested icon
Guide icon
4 examples icon
Free credits icon
Turn an agent workload into a risk-based sandbox design, isolation policy and bounded security-test plan. Compare up to three containment options, map enforcement points and identify deployment blockers. Two inputs; advanced controls apply only when relevant. Produces design documentation, not a deployed or security-certified sandbox.
...more
Added 1 day ago
Report
Browse Marketplace