Bounded rootless OCI whole-worker isolation proof for #53 (#78) #81

Merged
kilo merged 3 commits from issue-78-worker-isolation into develop 2026-10-08 21:35:37 +00:00
Member

Refs #78 (gate: #53). Research delivery; no merge authority. Issue #78 stays open; #53 stays gated.

Status

  • Independent whole-PR review ordinal 2: APPROVE, findings: 4 P3 (non-blocking) at frozen HEAD 494e623dff6f42bdbb87b93a37aa0f5a45488124 / base 19775b9679cf04f071e4fe5f2542fe230272ea36; fresh isolated GLM-5.3 reviewer each ordinal, no implementation context, all gates and the native receipt independently re-run; the disclosed clone-with-namespace-flags seccomp residual was independently re-derived and confirmed real (documented limitation). Ordinal 1 (APPROVE, 4 P3) on 3b9affa remediated by 494e623; review counter 2/10.
  • Canonical CI: SUCCESS on exact HEAD (494e623, run https://forgejo.creatidy.com/Creatidy/creatidy-kernel/actions/runs/142; also SUCCESS on 3b9affa).
  • Known non-blocking residuals recorded by ordinal 2 (kept as documented P3s, safe-direction imprecision only): harness.container_state returns "running" for any existing container (callers treat it as exists/absent); the decision record's "no configured addressing" should read "no non-loopback addressing" (::1/128 autoconfigures on lo); loopback connect denials are ECONNREFUSED (no listener) while the namespace-enforcement facts are the lo-only inventory and empty /proc/net/route.

Received Scope

Owner-authorized bounded research: determine whether maintained rootless OCI (Podman+crun) can confine an entire synthetic coding-agent worker — native file/terminal/subprocess paths included — independently of harness approval callbacks, and whether that boundary can serve the #53 universal executor enforcement decision (comment 15606).

Prior work preserved: branch created earlier from verified base 19775b9679cf04f071e4fe5f2542fe230272ea36 (no prior commits/PR/ordinals; reflog-verified), plus the earlier session's user-owned pinned toolroot at /tmp/kilo/kernel78-tooling (podman 6.1.3 pinned-commit build, crun 1.30.1 signature-verified release, conmon 2.2.1, provenance.json) — adopted as the proof's toolchain. Noble podman 4.9.3 was evaluated and rejected (EOL upstream, sandbox-relevant unfixed CVEs, root-owned policy.json blocks image creation unprivileged).

Delivered

  • tools/oci_worker_poc/: synthetic worker (reads approved read-only sources, modifies a disposable workspace, runs busybox shell + host-closure Python 3.12.3, spawns child/setsid descendants whose shell AND grandchild carry the settlement marker, handles SIGTERM cancellation and self-deadline); controller-owned profile (dedicated rootless user namespace per Attempt, single-UID documented podman mapping, --network=none, --cap-drop=all, no-new-privileges, custom seccomp deny-list incl. unshare/setns/mount/ptrace/io_uring/clone3, read-only rootfs, enumerated mounts with forbidden-prefix refusal, private tmpfs HOME/tmp, systemd cgroup memory/pids limits with fail-closed refusal of the cgroupfs fallback); harness (disposable per-Attempt sandboxes, launch/stop/settlement-by-host-/proc-scan, evidence records); SETUP.md (toolroot provenance incl. explicit netavark/busybox SHA-256 pins, single-UID rationale, reproduction).
  • Authority seam: controller-owned Unix-socket external-effect relay. Grants are Attempt+operation-bound, single-use, expiring; refused classes observed natively: unknown_grant, grant_expired, grant_revoked (revoked mid-run), grant_already_consumed, grant_op_mismatch; dropped replies recorded as uncertain effects (executed ≠ acknowledged ≠ cancelled ≠ rolled back); the relay receipt log, not worker belief, is reconciliation truth.
  • tests/test_oci_worker_isolation.py (18 native items): the issue's matrix — approved workspace access, host filesystem/credential denials (env canaries + host paths), native commands, child settlement with bystander survival, IPv4/IPv6/DNS/Unix/control/abstract-socket denials, observed privileges (CapEff=0, NoNewPrivs=1, Seccomp=2, single-line uid_map, mount allowlist, unshare→EPERM, in-container pids.max=8 with fork-flood denial), read-only-root and symlink escape denial, relay authority during execution, lost-reply uncertainty, hold-FD persistence (not revoked), deadline expiry, monitor-death→unknown→reconciled. Every negative is an observed fact; missing toolroot ⇒ honest skip (UNPROVED).
  • tests/test_oci_worker_authority.py (8 closed-environment items) + tests/conftest.py.
  • docs/architecture/whole-worker-isolation.md: FEASIBLE bounded verdict; candidate comparison (podman+crun primary; bwrap stays verification-only; approval callbacks rejected by 15606); advisory table; static containment vs new-operation authorization vs dynamic revocation vs settlement vs in-flight uncertainty distinctions (writable binds and retained FDs are NOT dynamically revocable — recorded, no AC4 reinterpretation); Runtime/Workspace/authority integration proposal (planned, not implemented); limitations and residual threats.
  • Makefile: make oci-worker-proof (requires CREATIDY_TEST_OCI_TOOLROOT).

Exact Review Subjects

Base/mergebase: 19775b9679cf04f071e4fe5f2542fe230272ea36
HEAD: 494e623dff6f42bdbb87b93a37aa0f5a45488124 (3b9affa implementation + 494e623 evidence-accuracy remediation; no rebase/amend/force)
14 files, +2389/−5. No src/ changes; no dependency/lockfile changes; no production behavior change.

Validation (closed environment, no live inference/network effects)

  • uv sync --locked: PASS.
  • Final make check package-check audit && git diff --check: PASS — 1405 tests + 81 subtests, 71 honest native skips (53 #50 bwrap + 18 #78 without toolroot); format/lint/basedpyright(strict)/import boundaries/secret scan/reproducible packaging/installed CLI smoke/advisory audit all PASS. Independently re-run by both review ordinals.
  • Native receipt CREATIDY_TEST_OCI_TOOLROOT=/tmp/kilo/kernel78-tooling make oci-worker-proof: 26 passed, 0 failed, 0 native skips (18 isolation + 8 authority/profile), ~252s; independently re-run by both ordinals.
  • Platform: Ubuntu 24.04, Linux 6.18.33.2-microsoft-standard-WSL2 x86-64, unprivileged user; podman 6.1.3, crun 1.30.1, conmon 2.2.1, netavark 1.4.0, busybox 1:1.36.1-6ubuntu3.1 (pins and hashes in the toolroot provenance.json and SETUP.md; binary SHA-256s verified by reviewers).

ADR 0008's bubblewrap 0.11.0 pin is inside the affected range of GHSA-pxhw-h44j-8pfx / CVE-2026-87766 (setup-time same-privilege path traversal; no known privilege escalation for the unprivileged #50 profile). Recorded as #80; no remediation changes in this PR; #50 scope untouched. Advisory substance independently corroborated by both reviewers.

Limits

Synthetic worker only — not Codex/Kilo/ZCode AC4 conformance; #53 remains gated on real-harness executor closure (comment 15612). Single-UID mapping only (no setuid newuidmap; privileged installation out of authorization) — multi-UID confinement is a recorded deployment prerequisite. No adversarial penetration testing (out of scope). No merge/release/deploy/live inference authority; issue #78 stays open pending owner disposition.

Refs #78 (gate: #53). Research delivery; no merge authority. Issue #78 stays open; #53 stays gated. ## Status - Independent whole-PR review ordinal 2: **APPROVE, findings: 4 P3 (non-blocking)** at frozen HEAD `494e623dff6f42bdbb87b93a37aa0f5a45488124` / base `19775b9679cf04f071e4fe5f2542fe230272ea36`; fresh isolated GLM-5.3 reviewer each ordinal, no implementation context, all gates and the native receipt independently re-run; the disclosed clone-with-namespace-flags seccomp residual was independently re-derived and confirmed real (documented limitation). Ordinal 1 (APPROVE, 4 P3) on `3b9affa` remediated by `494e623`; review counter 2/10. - Canonical CI: SUCCESS on exact HEAD (`494e623`, run https://forgejo.creatidy.com/Creatidy/creatidy-kernel/actions/runs/142; also SUCCESS on `3b9affa`). - Known non-blocking residuals recorded by ordinal 2 (kept as documented P3s, safe-direction imprecision only): `harness.container_state` returns "running" for any existing container (callers treat it as exists/absent); the decision record's "no configured addressing" should read "no non-loopback addressing" (::1/128 autoconfigures on lo); loopback connect denials are ECONNREFUSED (no listener) while the namespace-enforcement facts are the lo-only inventory and empty /proc/net/route. ## Received Scope Owner-authorized bounded research: determine whether maintained rootless OCI (Podman+crun) can confine an entire synthetic coding-agent worker — native file/terminal/subprocess paths included — independently of harness approval callbacks, and whether that boundary can serve the [#53](https://forgejo.creatidy.com/Creatidy/creatidy-kernel/issues/53) universal executor enforcement decision (comment 15606). Prior work preserved: branch created earlier from verified base `19775b9679cf04f071e4fe5f2542fe230272ea36` (no prior commits/PR/ordinals; reflog-verified), plus the earlier session's user-owned pinned toolroot at `/tmp/kilo/kernel78-tooling` (podman 6.1.3 pinned-commit build, crun 1.30.1 signature-verified release, conmon 2.2.1, `provenance.json`) — adopted as the proof's toolchain. Noble podman 4.9.3 was evaluated and rejected (EOL upstream, sandbox-relevant unfixed CVEs, root-owned policy.json blocks image creation unprivileged). ## Delivered - `tools/oci_worker_poc/`: synthetic worker (reads approved read-only sources, modifies a disposable workspace, runs busybox shell + host-closure Python 3.12.3, spawns child/`setsid` descendants whose shell AND grandchild carry the settlement marker, handles SIGTERM cancellation and self-deadline); controller-owned profile (dedicated rootless user namespace per Attempt, single-UID documented podman mapping, `--network=none`, `--cap-drop=all`, no-new-privileges, custom seccomp deny-list incl. unshare/setns/mount/ptrace/io_uring/clone3, read-only rootfs, enumerated mounts with forbidden-prefix refusal, private tmpfs HOME/tmp, systemd cgroup memory/pids limits with fail-closed refusal of the cgroupfs fallback); harness (disposable per-Attempt sandboxes, launch/stop/settlement-by-host-`/proc`-scan, evidence records); `SETUP.md` (toolroot provenance incl. explicit netavark/busybox SHA-256 pins, single-UID rationale, reproduction). - Authority seam: controller-owned Unix-socket external-effect relay. Grants are Attempt+operation-bound, single-use, expiring; refused classes observed natively: `unknown_grant`, `grant_expired`, `grant_revoked` (revoked mid-run), `grant_already_consumed`, `grant_op_mismatch`; dropped replies recorded as **uncertain effects** (executed ≠ acknowledged ≠ cancelled ≠ rolled back); the relay receipt log, not worker belief, is reconciliation truth. - `tests/test_oci_worker_isolation.py` (18 native items): the issue's matrix — approved workspace access, host filesystem/credential denials (env canaries + host paths), native commands, child settlement with bystander survival, IPv4/IPv6/DNS/Unix/control/abstract-socket denials, observed privileges (`CapEff=0`, `NoNewPrivs=1`, `Seccomp=2`, single-line `uid_map`, mount allowlist, `unshare→EPERM`, in-container `pids.max=8` with fork-flood denial), read-only-root and symlink escape denial, relay authority during execution, lost-reply uncertainty, hold-FD persistence (not revoked), deadline expiry, monitor-death→unknown→reconciled. Every negative is an observed fact; missing toolroot ⇒ honest skip (UNPROVED). - `tests/test_oci_worker_authority.py` (8 closed-environment items) + `tests/conftest.py`. - `docs/architecture/whole-worker-isolation.md`: **FEASIBLE** bounded verdict; candidate comparison (podman+crun primary; bwrap stays verification-only; approval callbacks rejected by 15606); advisory table; static containment vs new-operation authorization vs dynamic revocation vs settlement vs in-flight uncertainty distinctions (writable binds and retained FDs are NOT dynamically revocable — recorded, no AC4 reinterpretation); Runtime/Workspace/authority integration proposal (planned, not implemented); limitations and residual threats. - `Makefile`: `make oci-worker-proof` (requires `CREATIDY_TEST_OCI_TOOLROOT`). ## Exact Review Subjects Base/mergebase: `19775b9679cf04f071e4fe5f2542fe230272ea36` HEAD: `494e623dff6f42bdbb87b93a37aa0f5a45488124` (3b9affa implementation + 494e623 evidence-accuracy remediation; no rebase/amend/force) 14 files, +2389/−5. No `src/` changes; no dependency/lockfile changes; no production behavior change. ## Validation (closed environment, no live inference/network effects) - `uv sync --locked`: PASS. - Final `make check package-check audit && git diff --check`: PASS — 1405 tests + 81 subtests, 71 honest native skips (53 #50 bwrap + 18 #78 without toolroot); format/lint/basedpyright(strict)/import boundaries/secret scan/reproducible packaging/installed CLI smoke/advisory audit all PASS. Independently re-run by both review ordinals. - Native receipt `CREATIDY_TEST_OCI_TOOLROOT=/tmp/kilo/kernel78-tooling make oci-worker-proof`: **26 passed, 0 failed, 0 native skips** (18 isolation + 8 authority/profile), ~252s; independently re-run by both ordinals. - Platform: Ubuntu 24.04, Linux 6.18.33.2-microsoft-standard-WSL2 x86-64, unprivileged user; podman 6.1.3, crun 1.30.1, conmon 2.2.1, netavark 1.4.0, busybox 1:1.36.1-6ubuntu3.1 (pins and hashes in the toolroot `provenance.json` and `SETUP.md`; binary SHA-256s verified by reviewers). ## Related Finding (outside this PR) ADR 0008's bubblewrap 0.11.0 pin is inside the affected range of GHSA-pxhw-h44j-8pfx / CVE-2026-87766 (setup-time same-privilege path traversal; no known privilege escalation for the unprivileged #50 profile). Recorded as [#80](https://forgejo.creatidy.com/Creatidy/creatidy-kernel/issues/80); no remediation changes in this PR; #50 scope untouched. Advisory substance independently corroborated by both reviewers. ## Limits Synthetic worker only — not Codex/Kilo/ZCode AC4 conformance; #53 remains gated on real-harness executor closure (comment 15612). Single-UID mapping only (no setuid newuidmap; privileged installation out of authorization) — multi-UID confinement is a recorded deployment prerequisite. No adversarial penetration testing (out of scope). No merge/release/deploy/live inference authority; issue #78 stays open pending owner disposition.
feat: prove bounded rootless OCI whole-worker isolation (#78)
All checks were successful
ci / check (pull_request) Successful in 2m19s
3b9affa4d2
Research delivery for the #53 universal executor enforcement gate (owner
decision 15606): determine whether maintained rootless Podman/crun can
confine an entire synthetic worker independently of approval callbacks.

- tools/oci_worker_poc: synthetic worker (native shell/Python commands,
  child/setsid descendants, cancellation/deadline), controller-owned
  isolation profile (single-UID rootless userns, network=none, cap-drop
  all, NNP, seccomp deny-list, enumerated read-only mounts plus one
  writable workspace, cgroup memory/pids limits with fail-closed
  fallback refusal), and an authority seam: an external-effect relay
  whose Attempt-bound single-use grants refuse unknown, expired,
  revoked, replayed and mismatched authority, recording lost replies
  as uncertain effects rather than cancellations.
- Native receipt: 18 isolation items plus 8 closed-environment
  authority/profile items under CREATIDY_TEST_OCI_TOOLROOT; every
  negative is an observed in-container or host-side fact; missing
  toolroot stays UNPROVED, never a synthetic pass.
- docs/architecture/whole-worker-isolation.md: FEASIBLE bounded
  verdict, candidate comparison, advisory table (bwrap CVE-2026-87766
  finding recorded separately as #80), explicit static-containment vs
  dynamic-revocation vs in-flight-uncertainty distinctions, and the
  Runtime/Workspace/authority integration proposal. No production
  behavior changes; #53 stays gated.

Refs #78, gates #53, records #80
fix: sharpen isolation evidence accuracy per ordinal-1 review (#78)
All checks were successful
ci / check (pull_request) Successful in 2m23s
494e623dff
Independent whole-PR review ordinal 1 (APPROVE, 4 P3 findings) on
3b9affa4d2 / 19775b9679
fe230272ea36; normal remediation on the same PR:

- Decision record: loopback interface observed UP under network=none
  (no external interface); denial evidence unchanged.
- SETUP.md: provenance.json covers podman/crun/conmon; netavark and
  busybox additions now pinned by explicit SHA-256 in the table.
- Worker descendants: the setsid shell and its long-running grandchild
  both carry the attempt-unique marker in their cmdlines, so settlement
  is scanned directly for the whole worker tree instead of inferred.
- Stale doc pointer in the package docstring.

Native receipt re-run: 26 passed, 0 failed. make check: 1405 tests +
81 subtests, 71 honest skips; package-check, audit-format gates and
git diff --check pass.

Refs #78
fix: distinguish OCI existence and network boundary evidence (#78)
All checks were successful
ci / check (pull_request) Successful in 2m24s
c576524a37
kilo merged commit 3bcc650802 into develop 2026-10-08 21:35:37 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Creatidy/creatidy-kernel!81
No description provided.