The simulation is a local tool. A malicious process running as the same operating-system user can read that user's private connection files, invoke their commands and act as the user. This package does not claim operating-system isolation from such a process. Put mutually untrusted hosts in separate accounts/sandboxes and pass only the intended connection capability.
The shared hub binds to 127.0.0.1 on an ephemeral port. It rejects Origin-bearing requests, foreign Host headers and calls without a random 256-bit per-launch connection capability. The capability selects a fixed role, agent and robot; tool arguments never select a different identity. Existing run roots are refused unless owned by the hub user with mode 0700. Connection files are created exclusively with mode 0600. The shim opens without following symlinks, validates descriptor owner/mode, and rejects a writable or foreign-owned parent. These checks require POSIX ownership support. For a separate-account agent, the operator must deliberately copy only its connection file into a private directory owned by that account; the copy must be owned by that account with mode 0600. Do not share the coordinator file with robot hosts. Each root has one writer lease, and logs use exclusively created run directories. Stale leases after a crash require deliberate local recovery, not automatic takeover.
Simulation time advances only through a coordinator step with an explicit tick budget. In live mode the launcher owns that step and commits only after all active robots submit or the wall-clock budget expires. Round tokens reject delayed commands; deadline holds are explicit recorded actions. Schemas reject unknown fields, nonfinite/out-of-range numbers, unknown scene objects, invalid ownership and oversized arrays. Motion/grasp/reassignment tools have no paths, URLs, shell commands or provider settings. The maximum input frame is 256 KiB, each stdio queue is limited to 32 requests and the hub to four in-flight requests per authenticated capability, including incomplete bodies; the run budget is at most 36,000 fixed ticks and command submissions are bounded between ticks.
Screen capture, upload, publishing, arbitrary file export, undo and human dashboard actions are not available as MCP tools. The simulation hub has no routes to start or stop capture, start a renderer or upload data. The replay asset server is GET-only with a fixed path allowlist under a random 256-bit per-launch capability URL. Every asset and the trajectory require that capability; no-referrer and nosniff headers are set. Keep the printed URL private. Its browser uses a private context and blocks requests outside that ephemeral loopback origin. tools/capture.mjs is a local CLI invoked by the operator and reads a supplied run directory. It records simulated frames, not the user's desktop.
There are no human-only HTTP action routes or interactive dashboard sessions in this package. If a future dashboard adds human-only controls, those actions must require the dashboard session: a one-time secret in a launch URL fragment, exchanged by POST with the correct Origin for a per-launch token kept in origin-scoped sessionStorage. Every human control must require that token in a custom header, plus Origin, Host and JSON validation. A cookie alone, or correct Origin and JSON alone, must never authorize such routes. No GET may expose a control or session token. Current tests explicitly reject local Origin+JSON requests and fail if capture/upload/human-only names appear in any MCP catalog.
Inputs and Fleet work-record content are data. Importing a task or ledger ID does not establish an external permission or prove that a Fleet server accepted it. The optional isolated Fleet proof records actual task-store and ledger transitions; normal imported work records remain the launcher's responsibility. Logs contain assignments and actions, so treat them as private operational data. Connection capabilities and claim tokens are excluded from exported simulation artifacts.
The hash chain is tamper-evident only relative to a trusted terminal hash; anyone able to rewrite a whole file can compute a new chain. Full physics replay additionally checks that the recorded actions generate the recorded states. Neither mechanism is a digital signature.
The renderer launches an isolated Chromium profile with Chromium sandboxing disabled for compatibility with the supplied portable sandbox runtime. Keep it local and feed it only validated scene/log data. It loads only package-owned scripts; no arbitrary website or script execution is exposed. Portable browser updates require re-qualifying frame hashes.
Live robot commands and submissions are accepted only from the capability bound to that robot. The coordinator cannot send them. Version 2 journals record caller role/agent ID beside the target robot ID(s), including submissions; live audit rows do the same. Automatic holds/steps identify the launcher. Captions use the actual command caller, and use a driver label only when that caller matches the assigned robot agent. Separate profiles/projects organize configuration; they do not isolate same-user processes. Use the account boundary described in SECURITY.md for mutually untrusted hosts.
Plugin configuration joins an existing hub through an absolute SIM_CONNECTION path. Claude passes its connection-file option through the environment; Codex uses the host environment. Capability contents never belong in argv, settings or prompts. Local project install scope does not isolate simultaneous hosts or same-user file tools. Never use connection files or host logs to acquire another agent’s authority. Sim has no dashboard/session link or MCP reissue route; the human owns local capture/replay and normal hub recovery. See docs/CLAUDE-INSTALL.md for host diagnostics and the POSIX prerequisite.