From 9a7ab7395227ae5999858a538e5ec5d5a11eb09f Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 22:09:38 -0500 Subject: [PATCH] =?UTF-8?q?docs(remediation):=20charter=20=E2=80=94=20Buil?= =?UTF-8?q?ds=201-2=20justified=20by=20two=20independent=20impossibility?= =?UTF-8?q?=20proofs;=20RM-60=20option=20analysis?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per Mos. The choke-point executor and PG spine are not a design preference — they are forced. Twice during the mission's own first deliveries, work stopped against a security property that cannot exist at the layer needing it: D-19 (audited party controls the manifest certifying it — artifact integrity) and D-25 (audited party controls the code entering the sandbox — execution integrity). Both reduce to self-verification by the audited party is not verification, and both resolve only via an authority outside its control. Neither proof was sought; both arrived while shipping something else, from different directions, at different layers. An architecture forced by two independent impossibility proofs is stronger evidence than one argued for. RM-60 records Mos's sharper option analysis: A (unprivileged userns) does NOT fix the vulnerability — it grants a capability and leaves the ORDERING defect untouched, so B is required regardless; A without B is kernel exposure bought for nothing. B is the correct primitive, generalises to RM-59 and the choke-point executor, and may not need A at all. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/MISSION.md | 25 +++++++++++++++++ docs/remediation/TASKS.md | 55 ++++++++++++++++++++++++++++--------- 2 files changed, 67 insertions(+), 13 deletions(-) diff --git a/docs/remediation/MISSION.md b/docs/remediation/MISSION.md index 65df03a3..9db7a63e 100644 --- a/docs/remediation/MISSION.md +++ b/docs/remediation/MISSION.md @@ -109,6 +109,31 @@ gate/program; the LLM handles only genuine judgment. | **4. Comms service** | AUTHORITY, INBOX (+ versioning roadmap) | Envelope (comms/v1) → sole-path service → PG/Redis → pluggable adapters (tmux→Matrix/Discord/Slack/Telegram). Version the protocol, not participants. | | **+ Hygiene & proof** | FLEET, WORKFLOW, CONFORMANCE | One roster-owned socket/host + stale GC; allowlist auto-sync; the conformance harness that fault-injects the failure classes and proves builds 1–4 hold. | +## Why Builds 1–2 are necessary — two independent impossibility proofs + +**The choke-point executor and PG spine are not a design preference. They are forced.** Twice during +the mission's own first deliveries, work stopped against a security property that **cannot exist** at +the layer that needed it — and both times the only resolution was an authority _outside_ the audited +party's control, which is precisely what Builds 1–2 provide. + +| | the audited party controls… | so what fails | found as | +| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------- | -------- | +| **Artifact integrity** | the manifest that certifies its own generated tree (same-UID write ⇒ regenerate manifest _and_ marker consistently, CWE-345) | tamper-evidence | **D-19** | +| **Execution integrity** | the code that enters the sandbox (PR-controlled config executes _before_ the boundary exists) | isolation | **D-25** | + +Both reduce to one sentence: + +> **Self-verification by the audited party is not verification.** + +And to one consequence: **the anchor must live outside the audited party's authority.** A local check +cannot defend against an actor who can rewrite the check; a repo cannot grant a capability to +PR-controlled config and simultaneously prevent that config from using it. + +**An architecture forced by two independent impossibility proofs is stronger evidence than one argued +for.** Neither proof was sought — both arrived while trying to ship something else, from different +directions (a symlink manifest; a CI sandbox), at different layers. RM-59 and RM-60 are the two tracked +dependencies this creates, and they are the same dependency in different clothes. + ## The finding that sets the cost **Built-but-unwired disease.** `@mosaicstack/macp` is stranded (nothing calls it); `packages/coord` primitives diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index f5100026..edb7868d 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -117,6 +117,35 @@ layer (D-25). Not deferred for cost or effort; deferred because it is **impossib **Unblocked by: RM-60.** Accepted by `mos-remediation`; independently ruled by `rev-974`. +### RM-60 — why option B, and why option A does not work even alone (Mos, 2026-08-01) + +Recorded because the reasoning is easy to get backwards, and getting it backwards buys standing kernel +exposure for nothing. + +- **A (runner enables unprivileged user namespaces / rootless sandbox) DOES NOT FIX THE VULNERABILITY.** + It makes a sandbox _possible_; it says nothing about **when** the boundary is established relative to + PR-controlled code. **The defect is an ORDERING defect** — PR config executes before the boundary + exists. A grants a capability and leaves the ordering untouched, so B would still be required to close + it. **A without B is kernel exposure bought for nothing.** +- **B (protected default-branch pipeline config, or an immutable trusted launcher) IS the missing + thing.** A launcher established from **protected** configuration, outside the PR author's control, + entering isolation _before_ any PR-controlled executable is evaluated — that is the pre-execution + trust boundary, and it is the same "authority outside the audited party" that **D-19 and D-25 both + prove mandatory**. It may not need A at all: a protected launcher can use whatever isolation the + runner already supports. +- **B generalises; A does not.** The protected-launcher pattern is what **RM-59** needs, and is a small + instance of the **choke-point executor** the spine needs. A buys one narrow capability at a standing + kernel-exposure cost. + +**Therefore B is not the cautious choice — it is the correct primitive.** A is a workaround that does +not work on its own. + +**Status:** on Jason's board for a morning decision, with this reasoning, alongside the queue-guard item +(D-23), cross-referenced to RM-59. **Deliberately not actioned overnight:** enabling runner namespace +exposure or changing provider protected-pipeline posture is a host security-posture change belonging to +infrastructure authority. Nothing is blocked meanwhile — RM-02's head is unprivileged and fail-closed, +the privileged experiment stays uncommitted and out of branch history. + ### D-25 — self-verification by the audited party, a second time, one layer down RM-02's per-commit replay needs isolation. Docker denied Bubblewrap namespace creation; the obvious fix @@ -1015,19 +1044,19 @@ spread is itself information, and X1 says we calibrate on real merged PRs. ### P5 — Retirements, hygiene, conformance -| id | task | src | depends_on | est (S/O) | tier | -| ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | -------------------------------------- | ---------------- | ------ | -| RM-50 | One roster-owned socket/host; quarantine unmanaged; **deterministic reaper for stale sessions AND dead-session disk scratch** (D-7) | O+S+live | RM-04 | 14K / 150K | sonnet | -| RM-51 | Auto-sync **allowlist** (never auto-stage unknown paths) + worktree/lease isolation | O+S | RM-02 | 8K / 110K | sonnet | -| RM-52 | Retire the Python controller + duplicate MACP islands (3 → 1) | O+S | RM-26, RM-27, RM-25, RM-28 | 14K / 110K | codex | -| RM-53 | Flat-file orchestration → DB hard cutover, with rehearsed rollback artifact | O+S | RM-27, RM-30, RM-34, RM-29 | (in S-10) / 200K | opus | -| RM-54 | Fleet-wide inert-gate audit against the RM-02 registry | O | RM-02 | — / 120K | sonnet | -| RM-55 | **Conformance harness:** fault-inject the live failure classes on real artifacts | O+S | RM-35, RM-41, RM-53 | 18K / 260K | opus | -| RM-56 | Retirement proof: CI asserts all three retirements are complete **and stay complete** | O | RM-52, RM-45, RM-53 | — / 90K | codex | -| RM-57 | Operator cutover docs + activation proof; map all 15 decisions to evidence | S | RM-04, RM-36, RM-45, RM-55 | 6K / — | codex | -| RM-60 | **External pre-execution trust boundary for CI** — protected default-branch pipeline config or an immutable trusted launcher that enters the sandbox **before** any PR-controlled executable/config is evaluated; unblocks isolated per-commit replay (RM02-REQ-10) | mos-remediation (D-25) | infra/provider authority (Mos + Jason) | 25K | opus | -| RM-59 | **Close the D-19 residual risk** — generated-state verification anchored **outside** the worktree's authority (executor/spine-side attestation), retiring the same-UID self-authentication gap | mos-remediation (D-19) | RM-12, RM-21, RM-25 | 20K | opus | -| RM-58 | **Mechanical pre-dispatch context reset** — the orchestrator resets a seat out-of-band and verifies it, rather than asking the agent to reset itself | mos-remediation (D-4) | RM-31, RM-50 | 8K | sonnet | +| id | task | src | depends_on | est (S/O) | tier | +| ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | -------------------------------------- | ---------------- | ------ | +| RM-50 | One roster-owned socket/host; quarantine unmanaged; **deterministic reaper for stale sessions AND dead-session disk scratch** (D-7) | O+S+live | RM-04 | 14K / 150K | sonnet | +| RM-51 | Auto-sync **allowlist** (never auto-stage unknown paths) + worktree/lease isolation | O+S | RM-02 | 8K / 110K | sonnet | +| RM-52 | Retire the Python controller + duplicate MACP islands (3 → 1) | O+S | RM-26, RM-27, RM-25, RM-28 | 14K / 110K | codex | +| RM-53 | Flat-file orchestration → DB hard cutover, with rehearsed rollback artifact | O+S | RM-27, RM-30, RM-34, RM-29 | (in S-10) / 200K | opus | +| RM-54 | Fleet-wide inert-gate audit against the RM-02 registry | O | RM-02 | — / 120K | sonnet | +| RM-55 | **Conformance harness:** fault-inject the live failure classes on real artifacts | O+S | RM-35, RM-41, RM-53 | 18K / 260K | opus | +| RM-56 | Retirement proof: CI asserts all three retirements are complete **and stay complete** | O | RM-52, RM-45, RM-53 | — / 90K | codex | +| RM-57 | Operator cutover docs + activation proof; map all 15 decisions to evidence | S | RM-04, RM-36, RM-45, RM-55 | 6K / — | codex | +| RM-60 | **External pre-execution trust boundary for CI (option B — the correct primitive, not the cautious one)** — protected default-branch pipeline config or an immutable trusted launcher that enters the sandbox **before** any PR-controlled executable/config is evaluated; unblocks isolated per-commit replay (RM02-REQ-10) | mos-remediation (D-25) | infra/provider authority (Mos + Jason) | 25K | opus | +| RM-59 | **Close the D-19 residual risk** — generated-state verification anchored **outside** the worktree's authority (executor/spine-side attestation), retiring the same-UID self-authentication gap | mos-remediation (D-19) | RM-12, RM-21, RM-25 | 20K | opus | +| RM-58 | **Mechanical pre-dispatch context reset** — the orchestrator resets a seat out-of-band and verifies it, rather than asking the agent to reset itself | mos-remediation (D-4) | RM-31, RM-50 | 8K | sonnet | **Critical path:** `RM-01 → RM-02 → RM-10 → RM-11 → RM-12 → RM-21 → RM-23 → RM-31 → RM-33 → RM-34 → RM-53 → RM-55`.