Skip to content

feat(harness): probe-widened attestation for interpreter-only sandboxes and a batch audit - #590

Merged
heyong4725 merged 3 commits into
mainfrom
feat/audit-probe-widening
Sep 18, 2026
Merged

heyong4725 merged 3 commits into
mainfrom
feat/audit-probe-widening

Conversation

@heyong4725

Copy link
Copy Markdown
Contributor

Summary

Second of the two builds you approved for the pilot's confinement story, stacked on #589. Interpreter-only worker and validator sandboxes could not be attested at all: the session-bound audit needs a shell, cat, the Apple Git and a socket probe, and those policies admit only Python. This PR lets the audit run under such a policy widened by exactly its own probes, while the attestation still binds the SESSION profile and the launch wrapper independently recomputes the widening. Owner review requested (confinement class).

Requirement IDs: TRT-5, TRT-6, TRT-7, CON-8, CON-5.

What changes

  • widen_for_probes(policy, git, developer_root): the session policy plus bash, cat, the Apple Git (and netcat only when no Unix-socket probe is admitted) as executables and the read roots those load from; hidden roots, output/visible roots and the network policy are untouched; a probe root that would overlap a hidden root refuses.
  • run_macos_capability_audit(..., widen_probes=True): runs the matrix under the widened profile; the report's adapter.compiled_profile_sha256/policy_id stay the session's, audit_profile_sha256/audit_policy_id record the audited profile, and probe_widening records the additions. The audit also refuses if its sentinel files vanished mid-run (a file-deny case would otherwise pass vacuously).
  • wrap_verified_command(..., policy=): a declared widening is accepted only when the wrapper recomputes it from the session policy and THIS host's own developer Git (resolved once per process) and gets the identical declaration, so nothing but the audit's probes can ride along and an attestation from another host cannot verify. Every launch site (typed worker, monolithic worker, validator, run preparation, tool controller, campaign runner, typed node host, graph audit, matched run) now passes its policy. Attestations without a widening verify exactly as before.
  • attest-many --policies <dir> [--widen-probes] [--jobs N]: audits every <name>.policy.json concurrently, serializing policies that would share a sentinel home, writing <name>.attestation.json beside each, skipping existing attestations so a batch resumes, honouring an optional <name>.sentinels.json of controller-private sentinel homes, and naming every policy it could not attest (CON-8).
  • Successors cse-causal-study-v24 / cse-causal-study-pilot-v10 (hashed sources changed; commitments inherited, gates preserved); registry count -> 60; docs in docs/monolithic/matched-session.md and the confinement README, including the stated threat model (the attestation is an unsigned controller-owned document; the recomputation guards against tool misuse, not against an author who can edit the retained file).

Review record

/review: a security specialist and a testing specialist. Applied: host-bound recomputation of the widening (replaces the earlier basename-git/ancestor-root check that a forged declaration could satisfy), audit keys emitted only for widened audits, the vanished-sentinel refusal, per-home serialization in the batch runner, Linux-safe test roots, the missing negative tests, and an end-to-end test that the typed launcher hands its policy to the wrapper. Not applied: refusing a plain attestation for a policy that could not have run the probes (it would break every engineering fixture that uses the synthetic adapter; recorded as a deliberate choice in the test). /simplify: applied (shared _beside helper, top-level replace, inlined wrapper, dropped the redundant global lock, memoized developer-Git lookup).

Gates (Class C)

ruff format --check, ruff check, trace_check, docs_inventory --check, claim_evidence --check, registry (60), and the confinement + worker-capability + relay + validation-snapshot suites (84, live sandbox cases included) pass locally. The new typed-launch test is real-process and therefore CI-gated on this Mac.

Refs #347, #567, ADR-66.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EMTXwWm3ZppWcJvQQw2qbf

…es and a batch audit

A worker or validator policy admits only an interpreter and cannot run the
capability audit's probes. `widen_for_probes` adds exactly the shell, cat,
the Apple Git (and netcat only when no Unix-socket probe is admitted) and the
read roots they load from; `run_macos_capability_audit(widen_probes=True)`
runs the matrix under that profile while the attestation binds the SESSION
profile and records the widening. `wrap_verified_command(policy=)` accepts a
declared widening only when it recomputes the identical declaration from the
session policy and this host's own developer Git, so nothing but the audit's
probes can ride along; every launch site passes its policy. The audit refuses
if its sentinel files vanished mid-run. `attest-many` audits a directory of
policies concurrently (serializing shared sentinel homes), resumes past
existing attestations, honours per-policy sentinel sidecars and names every
refusal. Successors cse-causal-study-v24 / cse-causal-study-pilot-v10;
registry count -> 60.

TRT-5, TRT-6, TRT-7, CON-8, CON-5. Refs #347, #567, ADR-66.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EMTXwWm3ZppWcJvQQw2qbf
@heyong4725

Copy link
Copy Markdown
Contributor Author

Review findings for PR #590:

  1. The macOS ci/unit job fails in test_worker_policy_is_attested_under_a_probe_widened_profile and the parallel batch test. The unix_socket_network_control case sometimes fails for the widened Python-only worker policy, so the batch reports two refusals. The probe needs to be reliable on the macOS runner before the attestation path can be accepted.
  2. The PR is based on the pre-fix fix(harness): bind session audits and reject unsafe loopback authority #589 branch (8e0dd9e), while fix(harness): bind session audits and reject unsafe loopback authority #589 has since landed on main. Its CSE v24 and pilot v10 registrations collide with the registrations already on main, and its code predates the fix(harness): bind session audits and reject unsafe loopback authority #589 rejection of unsafe loopback policy. The branch needs current main, with append-only successor registrations and the deny-external policy preserved.
  3. attest_many currently counts any existing *.attestation.json as a successful skip without loading the policy or checking that the attestation binds its policy and widened profile. A changed or corrupt policy can therefore yield ok: true on resume. Existing files need validation before they count as complete.

I’m fixing these on the PR branch and will follow up with verification results.

@heyong4725
heyong4725 changed the base branch from feat/live-session-audit to main September 18, 2026 15:58
@heyong4725

Copy link
Copy Markdown
Contributor Author

Review follow-up: the three findings above are fixed on the PR branch.

  • The probe-widened macOS audit now admits and uses the same nc Unix-socket control that passed in the synthetic audit on the CI runner. Both previously failing macOS tests pass.
  • The branch now includes merged main and targets main. It preserves the historical CSE v24 and pilot v10 registrations unchanged, rejects the unsupported loopback policy, and adds append-only v25 and pilot v11 successors with source-bound manifests.
  • attest-many validates an existing attestation against the current policy, requested probe mode, adapter, imported system profile, and widened profile before counting it as skipped. Stale or malformed records are named as refusals.

Verification: 55 confinement tests and 27 freeze-registry tests passed locally; Ruff, trace coverage, docs inventory, and claim-evidence checks passed. CI passed on macOS (1h5m55s) and Linux (48m58s). GitHub reports the PR mergeable, with review still required.

@heyong4725
heyong4725 merged commit fcef2a7 into main Sep 18, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant