Watch
1
0
Fork
You've already forked RedFlag
0

docs: bind the supply-chain claims to the helper

This commit is contained in:
Fimeg 2026-08-25 08:26:05 -04:00
commit c3037655cd
10 changed files with 194 additions and 128 deletions

View file

@ -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*