fix(security): bind seq into mesh signatures (v2 preimage), guard DID slice, cfg-gate dev password

- mesh: verify_signature accepts a v2 preimage (t,v,ts,seq) alongside
  legacy v1 (t,v,ts); signed_with_seq() is the v2 sender path, not yet
  wired — senders stay v1 until the fleet verifies v2 (receivers
  hard-drop bad sigs, so flipping send-side first would break
  mixed-fleet alerts). Tests: v2 verify, v2 seq-tamper rejection,
  v1 sign-then-set-seq compat.
- mesh listener: malformed radio-supplied DID shorter than the
  'did🔑' prefix can no longer panic advert_name (slice -> .get()).
- auth: the pre-setup password123 dev login and the constant itself are
  now #[cfg(debug_assertions)] — no release binary carries the bypass,
  whatever its runtime config says.
- orchestrator: canned host-facts under #[cfg(test)] — awaiting real
  subprocesses under tokio's paused test clock deadlocks against
  auto-advanced timers (the old blocking detection only worked by never
  yielding).
- drop two now-unused std::process::Command imports left by 4c75bb3d.

Tests: mesh 110/110 (incl. 2 new), api 68/68, container 159/159,
archipelago-container check clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-07-04 17:49:52 -04:00
co-authored by Claude Fable 5
parent 291f2d7186
commit 2c8c99fd28
7 changed files with 145 additions and 37 deletions
+13 -6
View File
@@ -150,12 +150,19 @@ modules; production request/boot paths are essentially panic-free. The real risk
which sets `X-Real-IP $remote_addr`) — direct connections (e.g. the FIPS peer
listener) bucket under their socket IP, so per-request header rotation no longer
defeats the login limiter. 3 unit tests.
- [ ] 🟢 **Include `seq` in the mesh signed preimage.** `message_types.rs:245-288` signs
`(t,v,ts)` but sets the anti-replay `seq` after signing → a radio MITM can alter ordering
without breaking the signature.
- [ ] 🟢 **Guard the short-DID slice panic** (`mesh/listener/decode.rs:566`) and gate the
dev-mode `password123` bypass (`auth.rs:18`) behind `#[cfg]` before it can reach a
release build.
- [x] 🟢 **Include `seq` in the mesh signed preimage.** DONE 2026-07-04 (receiver half):
`verify_signature` accepts a v2 preimage `(t,v,ts,seq)` alongside legacy v1 `(t,v,ts)`;
`signed_with_seq()` is the v2 sender path, deliberately NOT yet wired — receivers
hard-drop bad signatures, so senders stay on v1 until the whole fleet verifies v2.
The seq-tampering window closes only when the v1 arm is removed (track as a
post-fleet-rollout follow-up). Unit tests cover v2 verify, v2 seq-tamper rejection,
and v1 sign-then-set-seq compatibility.
- [x] 🟢 **Guard the short-DID slice panic** (`mesh/listener/decode.rs:566`) and gate the
dev-mode `password123` bypass (`auth.rs:18`) behind `#[cfg]`. DONE 2026-07-04:
advert_name uses `.get()` fallback (malformed radio-supplied DID can't panic the
listener); the pre-setup dev-password login + the constant itself are
`#[cfg(debug_assertions)]` — no release binary carries the bypass regardless of
runtime config.
- [ ] 🟢 **Apply the seccomp/apparmor profile**`security/src/container_policies.rs:71` is a
TODO; the profile is defined but never applied to podman.