Skip to content

fix: third audit — PIPESTATUS regression, atomic hw-config, age-keygen stderr, env-example guard - #175

Merged
mdheller merged 1 commit into
mainfrom
fix/enroll-third-audit
Jun 16, 2026
Merged

fix: third audit — PIPESTATUS regression, atomic hw-config, age-keygen stderr, env-example guard#175
mdheller merged 1 commit into
mainfrom
fix/enroll-third-audit

Conversation

@mdheller

Copy link
Copy Markdown
Contributor

Third audit findings

C1 — audit #2 introduced a critical regression in nixos-rebuild failure detection

The audit #2 fix replaced fragile log-pattern matching with PIPESTATUS[0] capture — but left || true on the grep at the end of each pipeline. This is broken.

When || true triggers (either because nixos-rebuild failed AND caused a non-zero pipeline exit, or because grep found no matching lines), bash executes true as a simple command. true is a pipeline-of-one and resets PIPESTATUS to [0]. Every subsequent NB1_EXIT=${PIPESTATUS[0]} reads 0, always, regardless of nixos-rebuild's actual exit code. Proven with a live test:

false | true | true || true
echo "${PIPESTATUS[0]}"   # prints 0, not 1

Fix: remove || true, bracket each nixos-rebuild pipeline with set +e / set -e. With set +e, grep exiting 1 (no matching lines on a cached build) does not abort the script. PIPESTATUS is read before any subsequent command can reset it. Tested:

set +e; false | true | true; echo "${PIPESTATUS[0]}"; set -e
# prints 1 — correct

This affects both pass-1 and pass-2.

H1 — Step 1: nixos-generate-config > HW_CONFIG creates an empty file on failure

The shell > redirect creates (or truncates) HW_CONFIG to zero bytes before nixos-generate-config runs. If the command then fails, an empty hardware-configuration.nix remains on disk. On re-run, [[ -f "${HW_CONFIG}" ]] is true, the generation step is skipped, and pass-1 nixos-rebuild fails with a confusing Nix "empty file" import error — the operator sees nothing about nixos-generate-config having failed.

Fix: write to HW_CONFIG.tmp, check -s (non-empty), then mv atomically. The .nix file is only replaced if generation succeeded with non-empty output.

M1 — Step 3: age-keygen -o ... 2>/dev/null silences errors

If age-keygen fails (permissions, disk full, etc.), the operator sees no reason why. The script exits via set -e at the subsequent chmod 600 with a misleading "no such file" error. Removed 2>/dev/null.

M2 — Step 4: No guard before cp "${COMPOSE_ENV_EXAMPLE}"

If the prophet-platform clone is incomplete, or the compose layout changed, cp fails with a raw shell error. Added an existence check with a diagnostic message before the copy.

@mdheller
mdheller merged commit fa7532b into main Jun 16, 2026
@mdheller
mdheller deleted the fix/enroll-third-audit branch June 16, 2026 18:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant