docs: bind the supply-chain claims to the helper
This commit is contained in:
parent
14d4730c76
commit
c3037655cd
10 changed files with 194 additions and 128 deletions
|
|
@ -29,9 +29,10 @@ The boundary that *is* preservable locally is the OS privilege boundary:
|
|||
|
||||
| Defended against | Fleet mode | Standalone |
|
||||
|---|---|---|
|
||||
| Tampered artifact (hash mismatch) | yes | **yes** — helper verification unchanged |
|
||||
| Known-vuln package (OSV) | yes | **yes** — gates run before mint |
|
||||
| Too-new package (age/soak gates) | yes | **yes** |
|
||||
| Tampered local/mirror artifact (hash mismatch) | yes | **yes** — helper rehashes a supplied local path |
|
||||
| Registry artifact with no local path | not helper-rehashed today | **not helper-rehashed today** |
|
||||
| Known-vuln package (OSV) | yes, over reported resolved entries | **yes, over reported resolved entries** |
|
||||
| Too-new package (age/soak gates) | fleet policy | **not yet applied** — local evidence records `not_applicable` |
|
||||
| Unprivileged local malware minting installs | yes | **yes** — mint key is root-owned |
|
||||
| Compromised agent process | yes (server refuses) | **yes** — agent user cannot read mint key |
|
||||
| Local root attacker | yes (authority off-host) | **no — out of scope, say so in docs** |
|
||||
|
|
@ -50,7 +51,7 @@ Standalone mint runs as a **separate privileged invocation of the helper**
|
|||
uses. Rationale:
|
||||
|
||||
- Keeps the artifact set at three (`agent`, `server`, `helper`) — no fourth binary.
|
||||
- The helper is already the audited, privileged, network-less Rust component
|
||||
- The helper is already the audited, privileged, short-lived Rust component
|
||||
("auditable in one sitting"). Mint is ~the token struct it already parses, signed
|
||||
instead of verified.
|
||||
- Minter-equals-verifier is acceptable *here only* because both already run as root on
|
||||
|
|
@ -72,8 +73,8 @@ Keys:
|
|||
tray (redflag-local member)
|
||||
→ POST /v1/updates/:id/approve (agent local API, group ACL boundary)
|
||||
→ agent: resolve closure via DiscoveryRunner (dry-run, hash-resolve — read-only)
|
||||
→ agent: run gate predicates locally (OSV.dev query, age gate, soak gate)
|
||||
any vuln in closure = full stop, same as ApproveUpdate's 409 — no silent waiver;
|
||||
→ agent: run the current local predicate (OSV.dev query over resolved entries)
|
||||
any vuln in the checked set = full stop — no silent waiver;
|
||||
override requires explicit reason, journaled locally
|
||||
→ agent: write mint request file (closure + gate evidence + operator + reason)
|
||||
→ sudo systemd-run redflag-helper --mint <request> (narrowed sudoers entry)
|
||||
|
|
@ -82,11 +83,15 @@ tray (redflag-local member)
|
|||
→ token → normal consumer path → helper verify + execute (unchanged)
|
||||
```
|
||||
|
||||
The mint step **re-validates rather than trusts** the agent's gate verdicts where it
|
||||
can do so without network (closure hash shape, evidence timestamps, forward-only
|
||||
version check). It cannot re-run OSV (network-less) — the OSV verdict is part of the
|
||||
journaled evidence, so a lying agent user leaves a tamper-evident trail and still
|
||||
cannot bypass artifact-hash verification at execute time.
|
||||
The mint step **re-validates rather than trusts** the agent's evidence where the current
|
||||
contract permits: closure entry shape, evidence timestamps, host binding, operation, and
|
||||
the presence of an explicit override reason when OSV was vulnerable or unreachable. It
|
||||
does not re-run OSV; the unprivileged agent performs that query and the privileged mint
|
||||
path journals the supplied verdict. Network reachability is not the enforcement boundary
|
||||
here: the current helper unit retains host network access.
|
||||
|
||||
Age and soak evidence fields exist, but the local approval handler currently records both
|
||||
as `not_applicable`. Bringing the fleet age/soak policies into standalone mode remains work.
|
||||
|
||||
Doctrine carried over unchanged: signing required, forward-only, no skip-verification
|
||||
path, no doctrinal knobs.
|
||||
|
|
@ -113,11 +118,10 @@ as install/upgrade: idempotent, re-runnable, verified by the post-join healthche
|
|||
rather than assumed (`docs/tasks/INSTALL-001` is the enforcement pattern). Two
|
||||
standing rules keep it from rotting:
|
||||
|
||||
1. **Gate logic stays single-source.** Standalone and fleet share the same gate
|
||||
code (vuln full-stop, soak, age, hash verification). When a gate gains a
|
||||
fleet-side capability (e.g. DB-backed policy config), the standalone resolution
|
||||
path must be extended in the same change — a gate that behaves differently per
|
||||
mode is drift, not configuration.
|
||||
1. **Gate logic should converge.** Fleet and standalone share capability and helper
|
||||
verification primitives, while standalone currently omits the age/soak policies.
|
||||
Closing that drift is required; future gate changes must extend both resolution
|
||||
paths in the same change.
|
||||
2. **The join flow is exercised, not trusted.** Keyring replacement, key
|
||||
destruction, and journal upload need test coverage that runs both directions of
|
||||
the matrix (fresh-fleet install vs standalone-then-join must converge on
|
||||
|
|
@ -138,10 +142,11 @@ standing rules keep it from rotting:
|
|||
1. **Mint placement: `redflag-helper --mint`.** Artifact set stays at three. Two keys
|
||||
keep roles distinct (mint key root-owned `0600`, verify key in pinned keyring);
|
||||
SEC-022 attests both invocation modes.
|
||||
2. **OSV in standalone: best-effort with honest verdict.** Vuln found = full stop.
|
||||
2. **OSV in standalone: best-effort with honest verdict.** Vuln found in a reported
|
||||
resolved entry = full stop.
|
||||
OSV unreachable = explicit operator acceptance of "closure unverified" with reason,
|
||||
journaled — mirrors the fleet `unverified` hold from v0.2.3.1. Age/soak gates and
|
||||
execute-time hash verification never relax.
|
||||
complete execute-time registry artifact rehashing are not current standalone guarantees.
|
||||
3. **Gate-evidence freshness window: 15 minutes, hard-coded.** Not configurable
|
||||
(no doctrinal knobs); expired evidence means the agent re-resolves and re-checks.
|
||||
|
||||
|
|
@ -152,3 +157,5 @@ standing rules keep it from rotting:
|
|||
- `docs/tasks/SEC-023` — package-mutation boundary (mint path must not weaken it).
|
||||
- `docs/tasks/SEC-022` — binary mutual attestation (helper trust file).
|
||||
- `docs/tasks/THREAT-001` — must document the standalone trust model table above.
|
||||
|
||||
*Last reviewed: 2026-08-25*
|
||||
|
|
|
|||
Loading…
Reference in a new issue