fix: second audit — reliable rebuild exit detection, harmonia wait, closure+minisig verification - #174
Merged
Merged
Conversation
…losure+minisig verification
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Second audit findings and fixes
C1 — nixos-rebuild exit code swallowed (CRITICAL, both passes)
The original pattern:
The
|| trueon the grep masks the entire pipeline's exit code underset -o pipefail. Log-pattern matching was the only failure gate — and patterns like "error:" can appear in warnings that don't indicate actual failure, while real failures can produce error messages that don't match.Fixed by capturing
PIPESTATUS[0](nixos-rebuild's actual exit code) on the line immediately after the pipeline. The|| trueongrepdoes not resetPIPESTATUS— it applies only to grep's own exit status in the list, not to the pipeline array. Both pass-1 and pass-2 now fail closed on any non-zero nixos-rebuild exit.H1 — Step 11 harmonia wait was
sleep 3(HIGH)A 3-second sleep before checking harmonia was racey — harmonia routinely takes 5-15s to start after activation. If the check failed, the cache push was skipped with a warn. Replaced with a 60s polling loop (12 × 5s) that checks the actual HTTP endpoint before attempting
nix copy. Push failure remains warn-only since syncd repopulates the cache on its first cycle.H2 — Step 10
nix buildfailure undetected (HIGH)--print-out-paths 2>&1 | tail -1mixed stderr (Nix build progress) into the captured store path. On failure,tail -1would capture a Nix error message rather than a store path. Fixed to2>/dev/null(suppress build progress) + explicit guard:[[ -n "${CLOSURE}" && -e "${CLOSURE}" ]]before proceeding.M1 — Step 12 minisig existence check, not verification (MEDIUM)
The enrollment verification step checked if the minisig endpoint responded, but did not run
minisign -Vto verify the signature was cryptographically valid. A stale sig or a sig generated with a different key would pass. Now downloads the sig to a tmpfile and verifies it against the local public key — same approach asdoctor.sh.M2 — No generation verification after pass-2 (MEDIUM)
After pass-2
nixos-rebuild switch, there was no confirmation that/run/current-systempointed to the closure built in step 10. Addedreadlink /run/current-systemcomparison — warns if they differ (e.g., nixos-rebuild cached an older derivation).