Watch
1
0
Fork
You've already forked RedFlag
0

feat: signed release manifest + fail-closed binary distribution

No unsigned binary path: build refuses when signing is disabled, downloads
return 404 when no signed package resolves. Signed release manifest endpoint,
installer verifies manifest signature and pins binary hash, Windows token
mandatory, Rust helper verify-binary.
This commit is contained in:
Fimeg 2026-05-29 10:47:41 -04:00
commit 1c18a6b55a
10 changed files with 492 additions and 7022 deletions

View file

@ -102,8 +102,9 @@ curl -sfL https://your-server.com/install | sudo bash -s -- your-registration-to
**Windows (PowerShell):**
```powershell
iwr https://your-server.com/install.ps1 | iex
& ([scriptblock]::Create((iwr -useb https://your-server.com/install.ps1).Content)) -Token your-registration-token
```
The token is required — the installer will not register without it. (`iwr ... | iex` cannot pass arguments; the scriptblock form is how PowerShell hands the token to the fetched script, the equivalent of Linux's `bash -s -- token`.)
**macOS (curl):**
```bash
@ -277,6 +278,34 @@ Remove-Item "C:\ProgramData\RedFlag\config.json"
5. Agent verifies signature + nonce + timestamp before execution
6. All updates have checksum verification + rollback on failure
### Binary Integrity: Closing the Cold-Start Gap
The update pipeline runs as root and executes downloaded binaries. That makes the
binary itself a trust boundary, not just the transport. RedFlag verifies the agent
binary at every stage of its life:
- **Install time (cold start).** The installer fetches a signed *release manifest*
one Ed25519-signed document listing the expected SHA-256 of every released binary
per platform/architecture, signed with the same key the agent trusts. Before it
executes anything, the installer verifies the manifest signature and confirms the
downloaded binary's hash matches the manifest entry. Any mismatch removes the
binary and aborts. This closes the gap where a first install would run an
unverified binary.
- **Upgrade time.** Self-upgrade verifies SHA-256 + Ed25519 signature before the
atomic binary swap, with rollback to the previous binary on failure.
- **Runtime.** A small, privileged, network-less Rust executor — separate from the Go
agent and outside its trust boundary — re-verifies the agent binary's hash. A
mismatch stops command issuance and surfaces in the Security Health panel alongside
nonce and machine-binding violations.
**The two-binary payoff.** To run unsigned code on a managed host, an attacker now has
to replace *both* the Go agent and the Rust executor — atomically, while the executor
is actively watching the agent, before the next check-in reaches the server. That is a
different class of problem than swapping a single binary: it takes local root with
precise timing, or a compromise of the build-and-signing infrastructure itself — which
the capability-token gate already addresses. The defense is layered on purpose, and the
layers are independent.
---
---
@ -384,7 +413,7 @@ Remove-Item "C:\Program Files\Aggregator\*" -Recurse -ErrorAction SilentlyContin
Remove-Item "C:\ProgramData\Aggregator\*" -Recurse -ErrorAction SilentlyContinue
# Then install new agent
iwr https://your-server.com/install.ps1 | iex
& ([scriptblock]::Create((iwr -useb https://your-server.com/install.ps1).Content)) -Token your-registration-token
```
### Full Fresh Install (Clean State)