Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/docs/souveraine-components/audit-status.md
Fimeg 9815185caa docs: put agent identity behind a real uid
Join the older storage and authority audits to the SAF principal contract. Passwd entries are not isolation while one human-owned process still executes every agent, and the existing souveraine account is machined's—not Souvie's.\n\nKeep the readiness task honest: its current health fields inventory paths, but do not yet prove admission or the UID handling a live turn.
2026-08-17 12:36:45 -04:00

5.6 KiB

Component audit status — toward the RedFlag security bar

Live tracker. Each component page carries an Audit gaps section with the detail; this page is the rollup: which RedFlag primitive each gap maps to, and where it sits in priority. When a gap closes, move it here to "Closed" and update the component page.

The bar is read from RedFlag's source, not the doctrine summary. The five primitives that matter, with anchors into ~/Projects/RedFlag:

Primitive What it is in RedFlag Anchor
Capability token Ed25519-signed, forward-only (Version), operation-scoped, expiring authorization agent/internal/capability/token.go
Closure hash sha256 over sorted/dedup name@version#sha256 — binds token to exactly what it authorizes Token.ClosureHash()
Canonical message Deterministic field-delimited string that is signed/verified Token.CanonicalMessage()
KeyID fingerprint hex(sha256(pubkey)[:16]) — binds a signature to a pinned key KeyIDFor()
Independent verifier The privileged executor verifies the token itself; never trusts the relay's claim helper/src/main.rs, token-executor mode
Binary integrity SHA-256 compare (verify-binary), exit-on-mismatch helper/src/main.rs:2226-2283
Kernel stop (defense-in-depth) eBPF on execve, denies outside a valid token context; not the gate docs/tasks/KERN-001
Least-privilege executor network-less, single-op, exact-match sudoers helper/src/main.rs

Two things to internalize from RedFlag's own status, because they set expectations for Souveraine:

  1. Binary mutual attestation is deliberately unwired in RedFlag too (SEC-022: "kill-on-mismatch and phone-home are deliberately not wired"). The standing guarantee in both systems is DAC — root/owner-owned binaries the running user cannot overwrite. The watchdog raises the cost on top of that; it is not the gate.
  2. The token is the universal primitive, not just for installs. RedFlag's ARCH-001 direction is "every fleet operation is a capability" — nothing runs on standing authority. Souveraine's equivalent: every authority verb (sign, unlock, handoff, release-secret, step-up) should be a capability, not a "the caller is local so it's fine."

Priority order

P0 — the unlock/handoff verb has no attestation

Component: sessiond. Gap: shell_ready / lock honored on any same-uid caller; no token. Primitive missing: capability token + independent verifier. Why P0: unlock-adjacent verbs are the highest-value authority in the system; a same-uid process that reaches the socket can induce a handoff or retake. Closes when: the shell presents a machined-signed token (operation-scoped, short expiry, closure carrying the shell binary hash) that sessiond verifies against the pinned machine pubkey before honoring shell_ready. Depends on machined issuing tokens (P1).

P1 — machined signs but does not issue tokens

Component: machined. Gap: signs raw domain:payload bytes; no operation, expiry, closure, or KeyID. Primitive missing: capability token (full), closure hash, canonical message, KeyID. Why P1: it is the root authority; every other attestation depends on it minting real tokens. Closes when: machined issues forward-only, expiring, operation-scoped tokens over a canonical message that includes the authorized target (verb + binary hash), advertises a KeyID fingerprint, and the signing/verification logic is byte-identical across mint and verifier (RedFlag invariant: agent/internal/capability/token.gohelper/src/main.rs).

P2 — secrets releases on D-Bus policy, not caller identity

Component: secrets. Gap: any session-bus process can GetSecrets; no per-caller capability, no item-scoping, no SO_PEERCRED. Primitive missing: capability token with closure = item path; independent verifier. Why P2: the data is highest-sensitivity but the trust boundary (the unlocked user session) is currently accepted by design; closes when personal- tier credentials require a step-up token (§10) honored by secrets, not just session-unlocked.

P3 — caller identity is uid 1000 for everything

Cross-cutting. Gap: SO_PEERCRED is logged (machined) or unread (sessiond); every substrate caller is the same UID, so the audit trail cannot distinguish Annie from a curl script. Primitive it blocks: AgentID-equivalent — the token's "who is asking" field. Closes when: per-agent UNIX accounts and per-agent worker processes land, making SO_PEERCRED kernel-backed caller identity that the token binds to. Passwd entries alone do not close it while one uid-1000 server executes every turn. Creation, node admission, the acting-as-human health refusal, and the operating-skill projection are owned by ../../../souveraine/saf/identity/02-agent-principal.md. This is the enabler for P0/P1/P2, tracked separately because it is account provisioning and process isolation, not crypto.

P4 — binary integrity watchdog (shared with RedFlag)

All components. Gap: no self/peer SHA-256 verification. Primitive missing: verify-binary equivalent, wired. Status: deliberately deferred, same as RedFlag SEC-022. DAC (root/owner-owned, non-overwritable) is the standing guarantee. When the capability token lands (P1), the token's closure should carry each component's expected hash so a swapped binary cannot replay a valid old token — that is the point at which the watchdog becomes load-bearing rather than ornamental.

Closed

(none yet — component family documented 2026-07-16, all gaps open.)