release: implement site registry v0.4 trust pipeline
This commit is contained in:
parent
2861337a45
commit
e26efc19fa
67 changed files with 10698 additions and 640 deletions
76
docs/SECURITY-REVIEW-0.4.md
Normal file
76
docs/SECURITY-REVIEW-0.4.md
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# Version 0.4 security review
|
||||
|
||||
Reviewed 2026-09-13 after implementation and before release promotion.
|
||||
|
||||
## Scope and trust boundaries
|
||||
|
||||
The review covered source-manifest and acquisition validation, typed coverage,
|
||||
SQLite migrations and projections, observation import and candidate-site network
|
||||
access, reviewer votes and policy compilation, generation and revocation signing,
|
||||
consumer verification, CLI argument relationships, systemd isolation, dependency
|
||||
advisories, source packaging, and accidental credential or dataset disclosure.
|
||||
|
||||
The design treats provider bytes, websites, DNS answers, redirects, observation
|
||||
batches, public proposals, mirrors, and lookup results as untrusted. Reviewer and
|
||||
publisher private keys, the mutable writer database, consumer trust roots, and the
|
||||
host operating system remain privileged. A source assertion or observation cannot
|
||||
approve a route. One reviewer cannot satisfy the reference approval quorum, while
|
||||
one authenticated revocation can stop an exact subject.
|
||||
|
||||
## Findings fixed before release
|
||||
|
||||
1. **Cross-generation revocation reinstatement:** a publisher-signed feed could
|
||||
claim supersession while an older consumer lacked the reviewer votes needed to
|
||||
recompute it. Cross-generation feeds now only add blocks. Clearing a block
|
||||
requires the exact full generation containing the authenticated fresh quorum.
|
||||
2. **Stale emergency feeds:** feeds previously had no artifact deadline and a
|
||||
verified object could be reused indefinitely. Feeds now expire within seven
|
||||
days, and freshness is checked both during verification and every resolution.
|
||||
3. **Resolver continuity:** `verify-revocations` accepted a previous feed, while
|
||||
`resolve` had no equivalent input. `resolve` now accepts the last feed and
|
||||
signature and refuses replacements that discard subjects or vote IDs.
|
||||
4. **Publisher/reviewer separation:** physical-key and identity checks covered
|
||||
approval voters only. They now cover every reviewer vote, including emergency
|
||||
revocations, and remove a rejected signature output.
|
||||
5. **Observation-batch mutation:** completed batch counters, state, and membership
|
||||
were not all protected by schema triggers. A batch must now be created open,
|
||||
can complete once only with its exact row count, and cannot accept later rows,
|
||||
change, or be deleted.
|
||||
6. **Policy-epoch revocation bypass:** a new policy epoch retained an old signed
|
||||
revocation in the audit log but excluded it from compilation. All authenticated
|
||||
revocations now remain sticky across policy epochs until a fresh quorum under
|
||||
the active policy explicitly supersedes them.
|
||||
7. **Special-address observation targets:** the outbound filter omitted several
|
||||
IPv4 and IPv6 special-use ranges. The observer now also blocks IPv4-compatible,
|
||||
site-local, translation, discard, benchmarking, ORCHID, documentation, and 6to4
|
||||
destinations before constructing a pinned client.
|
||||
|
||||
Regression coverage includes expired verified objects, signed cross-generation
|
||||
reinstatement attempts, physical reviewer-key reuse by a publisher, immutable
|
||||
observation batches and late inserts, policy-epoch revocation changes, signature
|
||||
and feed tampering, redirect loops, private and reserved address ranges,
|
||||
compressed bodies, malformed markup, extraction caps,
|
||||
and a deterministic 512-case parser mutation corpus.
|
||||
|
||||
## Review result
|
||||
|
||||
No known critical, high, or medium security finding remains in the reviewed 0.4
|
||||
scope. `unsafe` Rust is forbidden workspace-wide. External SSH operations use
|
||||
argument vectors and descriptor-bound private temporary files. Generation reads
|
||||
hash a no-follow source into a private unlinked SQLite snapshot before querying.
|
||||
Network clients disable ambient proxies; source acquisition uses reviewed HTTPS
|
||||
endpoints and explicit byte limits; the observer pins an entirely public DNS set
|
||||
per hop and bounds redirects, headers, body bytes, bandwidth, time, and extracted
|
||||
links.
|
||||
|
||||
`cargo audit --deny warnings` scanned 1,243 RustSec advisories across 272 locked
|
||||
dependencies without a finding. The complete offline gate separately exercises
|
||||
strict Clippy, documentation, unit and integration tests, native CLI behavior,
|
||||
consumer parity, source-package defenses, and the synthetic five-source import.
|
||||
`systemd-analyze verify` accepted the observer service and timer; its only output
|
||||
was an unrelated warning from the host's installed `arch-audit.service`.
|
||||
|
||||
This review authenticates software behavior, not provider truth or a public
|
||||
dataset. Publishers must protect writer and signing authority, inspect evidence,
|
||||
retain the last accepted feed, refresh it before expiry, and distribute trust
|
||||
roots through an independent authenticated channel.
|
||||
Loading…
Add table
Add a link
Reference in a new issue