Skip to content

Commit dad4445

Browse files
Yambrclaude
andcommitted
docs(architecture): SEC-44 — clean-before-stop primary; fix SEC-38/39 source refs
A snapshot image is a verbatim copy of guest RAM + disk, so a secret live at snapshot time is frozen into a file that can be copied and booted where the resume hook never runs. Host-side revocation makes such a token useless but not absent from the image — two different controls the prior text conflated. Flip SEC-44's primacy: the load-bearing, testable control is that no session-scoped secret is present at snapshot-create time (image taken at minimal-init, session material hot-swapped at restore; verified by offline extraction finding none). Resume-side re-auth + VMGenID reseed + N-fork uniqueness become defence-in-depth. Public anchors: Firecracker snapshot docs, VMGenID spec, arXiv 2102.12892, NIST SP 800-190 §4.5. Also fix the SEC-38/SEC-39 Source cells: "this PR" was a placeholder that broke once #163 merged; repoint to #163 (their origin). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent e3eb6b4 commit dad4445

1 file changed

Lines changed: 3 additions & 3 deletions

File tree

docs/architecture/manifesto/02-nfrs.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,13 @@ Scope: determinism, replay, and reproducibility properties of the agent loop. Fu
158158
| NFR-SEC-35 | Host kernel floor + microVM kernel cmdline hardening | EoP, kernel CVEs | Host kernel ≥5.10. KVM presence is a precondition for the microVM tier only (post-v1, [`arch/microvm-tier-v1.1`](https://github.com/Wide-Moat/open-computer-use/issues/161)); when present, microVM-tier templates boot with `init_on_free=1`, `nomodule`, `random.trust_cpu=1`, `panic=1`. KVM absence is not a deployment block; the deployment selects the highest tier the host substrate supports | Helm pre-install probe runs in ≤2 s and emits a clear error naming the missing capability when `runtime: microVM` is configured on a host without `/dev/kvm`; CI test on a KVM-absent runner asserts the probe error path; image-spec audit covers the microVM-tier kernel cmdline | [`04-layer2-runtimes.md`](../../future-architecture/architecture/04-layer2-runtimes.md) §kernel |
159159
| NFR-SEC-36 | Guest control-plane port unreachable from guest workload code (block-local-connections equivalent on the L1 agent) | EoP, lateral | enforced at L1 listener config + iptables/nftables guest-egress rule | integration test | [`05-layer1-guest-agent.md`](../../future-architecture/architecture/05-layer1-guest-agent.md) §listener |
160160
| NFR-SEC-37 | Inter-component traffic between Wide-Moat components is encrypted in transit | Information Disclosure, lateral | zero plaintext between named components per release. Documented exceptions (decrypted traffic exists by design and is re-encrypted on the upstream leg): (a) the Egress trust-edge inspection point when MITM-inspecting mode is active (NFR-FLEX-15) — disabled in transparent-pass-through mode; (b) the DLP-ICAP hook (NFR-COMP-28). Substrate-specific enforcement is a component-spec choice | tcpdump probe on every named inter-component pair captures zero plaintext payload bytes outside (a)/(b); CI gate fails on any plaintext byte outside the carve-out | [`07-security.md`](../../future-architecture/architecture/07-security.md) §intra-platform TLS |
161-
| NFR-SEC-38 | Workload-trust profile declared at deployment time; admission validates the configured runtime tier against the profile. Allowed pairings: `trusted_operator` → runc / gVisor / microVM; `internal_workforce` → gVisor / microVM; `untrusted` → microVM only. Mismatch is a hard error. Picking the tier by data classification is forbidden separately by AP-13 | Spoofing, Tampering | admission-time validation against a 9-cell pairing matrix. 6 cells valid by pairing rules (3 require the post-v1 microVM tier per [#161](https://github.com/Wide-Moat/open-computer-use/issues/161)); 3 cells rejected by pairing rules. v1 GA deployable: 3 cells (`trusted_operator`×runc, `trusted_operator`×gVisor, `internal_workforce`×gVisor); v1 GA rejected: 6 cells (3 pairing-rejected + 3 microVM-not-shipped). Commitment; implementation lands with control-plane code | per-release admission test fixture | this PR |
162-
| NFR-SEC-39 | Tier-downgrade alarm — a deployment reconfigured from gVisor or microVM to a weaker tier, OR `workload_trust_profile` downgraded with active sessions present | Tampering, Repudiation | audit event `config.trust_profile.downgraded` within ≤30 s; SIEM-bridge HIGH; SOAR webhook per NFR-COMP-27 (one instance of the NFR-SEC-45 enumerated privileged-action set; this row adds the ≤30 s SLA and the active-sessions trigger). Commitment; implementation lands with audit pipeline + SOAR integration | integration test against the audit pipeline | this PR |
161+
| NFR-SEC-38 | Workload-trust profile declared at deployment time; admission validates the configured runtime tier against the profile. Allowed pairings: `trusted_operator` → runc / gVisor / microVM; `internal_workforce` → gVisor / microVM; `untrusted` → microVM only. Mismatch is a hard error. Picking the tier by data classification is forbidden separately by AP-13 | Spoofing, Tampering | admission-time validation against a 9-cell pairing matrix. 6 cells valid by pairing rules (3 require the post-v1 microVM tier per [#161](https://github.com/Wide-Moat/open-computer-use/issues/161)); 3 cells rejected by pairing rules. v1 GA deployable: 3 cells (`trusted_operator`×runc, `trusted_operator`×gVisor, `internal_workforce`×gVisor); v1 GA rejected: 6 cells (3 pairing-rejected + 3 microVM-not-shipped). Commitment; implementation lands with control-plane code | per-release admission test fixture | [#163](https://github.com/Wide-Moat/open-computer-use/issues/163) |
162+
| NFR-SEC-39 | Tier-downgrade alarm — a deployment reconfigured from gVisor or microVM to a weaker tier, OR `workload_trust_profile` downgraded with active sessions present | Tampering, Repudiation | audit event `config.trust_profile.downgraded` within ≤30 s; SIEM-bridge HIGH; SOAR webhook per NFR-COMP-27 (one instance of the NFR-SEC-45 enumerated privileged-action set; this row adds the ≤30 s SLA and the active-sessions trigger). Commitment; implementation lands with audit pipeline + SOAR integration | integration test against the audit pipeline | [#163](https://github.com/Wide-Moat/open-computer-use/issues/163) |
163163
| NFR-SEC-40 | Session idle / inactivity timeout — a session with no activity for the idle window forces re-authentication | Replay, hijack of an unattended session | idle window ≤15 min (configurable down, not up on the full shelf); on expiry the session is terminated and the next call requires re-auth | idle-timeout integration test | PCI-DSS 4.0 Req 8.2.8 + NIST SP 800-63B-4 §2.3.3 (AAL3) |
164164
| NFR-SEC-41 | Absolute session lifetime — total session duration is capped regardless of activity, forcing periodic re-authentication | Long-lived-session compromise | absolute cap ≤12 h; on expiry the session ends and re-auth is required even if active. Default off on the minimal shelf (solo); on and customer-tunable on the full shelf | session-lifetime integration test | NIST SP 800-63B-4 §2.3.3 (AAL3 SHALL ≤12 h) |
165165
| NFR-SEC-42 | **[v2 — `status: tbd`]** Skill-registry supply chain (pairs with the `SkillProvider` of NFR-SEC-24). An author-uploaded skill is signed server-side at ingest; provenance (author, time, who enabled it) is a first-class audit record; the signature is verified at attach, so content cannot change between sign and mount; a signature binds the skill to its author (accountability). Post-sign substitution is rejected | Tampering, supply-chain, Repudiation | commitment for the SkillProvider component spec; not GA in v1. When in scope: server-side signature at upload, signature-verified attach (reject on mismatch), provenance audit event per upload + per enablement | architectural review on the `SkillProvider` ADR | [#179](https://github.com/Wide-Moat/open-computer-use/issues/179) |
166166
| NFR-SEC-43 | Control / exec channel stays off any guest-reachable network: the host opens it, the guest listens, over vsock (microVM) or a host-side unix socket (`gVisor` / `runc`); a TCP listener rejects loopback + own-interface sources. Every host-facing guest call (Control plane, Storage broker) is attributed by a host-derived identity — hypervisor context id, kernel peer credentials of the per-session sandbox principal, or a per-session socket path the guest cannot enumerate — never a session/tenant id the guest supplies. A guest-out reverse dial is a fallback only where a host-reachable guest listener is unavailable; the bridge then holds no credential, runs unprivileged + syscall-confined, and authenticates the session before any privileged action | Spoofing, Elevation of Privilege | guest-originated code cannot reach the control channel via its own network stack; a guest with in-sandbox root cannot present another session's identity; guest-supplied identity is rejected as authoritative | integration test (guest-stack dial to control listener fails; forge-another-session attempt fails) + bridge privilege/seccomp review | [`02-trust-boundaries.md`](../02-trust-boundaries.md) §4 |
167-
| NFR-SEC-44 | Snapshot/hibernation excludes live credential material — on snapshot the Session JWT, custody/storage lease, and any in-memory session signing key are revoked host-side and unrecoverable from the image; on resume the sandbox re-authenticates for fresh host-attested tokens (NFR-SEC-43) and the guest CSPRNG is re-seeded (VMGenID-equivalent) | Tampering, EoP, Repudiation (replay) | 100% of session-bound tokens in a resumed snapshot fail validation; zero token reuse across resume; the pre-snapshot Session JWT is invalid at resume by construction (re-auth required), and the custody/storage lease additionally cannot be replayed beyond ≤1 min (NFR-SEC-29 high-value revoke) | red-team: snapshot a live session, attempt token reuse on resume + offline image extraction → must fail; CI asserts pre-snapshot JWT/lease invalid post-resume | NIST SP 800-190 §4.5; [#184](https://github.com/Wide-Moat/open-computer-use/issues/184) |
167+
| NFR-SEC-44 | A snapshot/hibernation image is a verbatim copy of guest RAM + disk: any session secret live at snapshot time is frozen into a file that can be copied and booted where the resume hook never runs. **Primary:** no session-scoped secret is present in guest RAM or disk at snapshot-create time — the image is taken at minimal-init (generic template) before session identity/rootfs is layered, and session material is hot-swapped only at restore. **Secondary (defence-in-depth, not the proof):** on resume the kernel CSPRNG is reseeded (VMGenID) with no session crypto before the generation-ID change is observed, the guest re-authenticates for fresh host-attested identity (NFR-SEC-43), and userspace identity/nonce/RNG reset; no two guests restored from one image present the same token, nonce, or RNG stream | Information Disclosure, Spoofing, EoP (multi-resume replay) | offline extraction of the memory file + disk backing scanning for token/key/lease byte patterns finds none; booting one image N× yields a distinct host-attested identity and distinct `getrandom()` stream per guest; a token recovered from a stubbed-resume offline boot is rejected by the broker (host-side revoke) | offline image-extraction scan gate; N-fork uniqueness test; negative test (stub resume hook, boot a copied image, attempt token reuse → rejected) | Firecracker `snapshot-support.md` §snapshot-security + `random-for-clones.md`; UAPI VMGenID spec; arXiv 2102.12892; NIST SP 800-190 §4.5; [#184](https://github.com/Wide-Moat/open-computer-use/issues/184) |
168168
| NFR-SEC-45 | Mandatory audit of every privileged control-plane action (enumerated set, not only tier-downgrade): force-kill, denylist edit, quota override, retention-policy change, custody access, forced lease mint/rotate/scope-change, any state-mutating operator or SOAR call (trust-profile downgrade is covered with its ≤30 s SLA by NFR-SEC-39). Each emits an OCSF event into the hash-chained pipeline (NFR-SEC-03) under host-attested operator identity (NFR-SEC-09), fail-closed (action denied if audit write fails) | Repudiation, Tampering | 100% of enumerated privileged actions emit a chain-linked OCSF event before acknowledgement; zero successful privileged action with no record; enumerated set is a versioned fixture | per-release integration test drives every enumerated action + asserts a matching record; negative test asserts deny on audit-sink failure | NYDFS §500.6, DORA Art.10, EU AI Act Art.12/14; [#186](https://github.com/Wide-Moat/open-computer-use/issues/186) |
169169
| NFR-SEC-46 | Per-sandbox resource-exhaustion containment beyond the PID/CPU/mem ceiling (NFR-SEC-14): disk quota on scratch + broker mount/prefix bytes; deterministic OOM scoping (`memory.oom.group=1`, the breaching sandbox is the victim); the Storage broker and Egress edge each rate-limit per host-attested session (file-ops/s, in-flight bytes, fd; new-conn/s, concurrent-conn) | DoS (noisy-neighbour) | a flood from one sandbox keeps co-resident sandboxes, the shared broker, and the shared edge within ≤10% p99-latency regression against the NFR-PERF baseline; the offender is the deterministic OOM/quota victim; each breach emits an audit event keyed to the host-attested session | red-team noisy-neighbour suite (disk-fill, fork+fd, broker file-op flood, egress conn flood) per tier asserting co-tenant SLO held + offender contained | EU AI Act Art.15(4), DORA Art.6/28, CCM IVS-06/09; [#188](https://github.com/Wide-Moat/open-computer-use/issues/188) |
170170
| NFR-SEC-47 | Out-of-band audit source for in-sandbox actions — the guest is never the authoritative author of its own audit events; in-sandbox tool calls/results are recorded by the host-side mediation layer that issues the call, and for tier-2+ a runtime-monitor trace session (gVisor seccheck remote sink / microVM behavioral capture) established at sandbox init before guest code runs and not disableable from inside the guest | Repudiation | 100% of mediated tool invocations have a host-authored record independent of any guest-emitted event; runtime-monitor session present from container start in 100% of sessions; a hostile PID-1 cannot suppress/forge the host-authored record (zero red-team pass per tier per release) | red-team suppression test + audit-completeness diff (host-authored vs guest-emitted) + session-init presence check in CI | OCSF, NIST SP 800-92; [#181](https://github.com/Wide-Moat/open-computer-use/issues/181) |

0 commit comments

Comments
 (0)