setup() headless on a deployed box: refuse loudly instead of silently reporting success - #951
Merged
Merged
Conversation
…less is_deployed()'s re-run prompt used `read -r -p ... || true`: with stdin on /dev/null (systemd units), read hits EOF immediately, `|| true` swallows the failure, RERUN stays empty, and the ^[Yy] check reads that as a decline — setup exits 0 having done nothing, reporting success. Give the prompt the same [ -t 0 ] no-tty rule resolve_dashboard_host already applies: no terminal means proceed, never silently decline, because every caller that reached setup() headlessly already made that call before invoking it. Checked both headless callers: - firstboot_wizard's `--cli` re-run (systemd unit, stdin /dev/null) — the unit exists specifically to run setup unattended; proceeding is the whole point of invoking it that way. - firstboot_wizard's own retry after a failed provisioning attempt (the operator already confirmed the config on the setup page; a retry here is driven by the wizard loop, not a second terminal prompt) — is_deployed() can already be true at this point because render_env writes DEPLOYMENT_COMPLETED=true before the steps that can still fail, so this is exactly the path #924 named as silently reporting success on a half-deployed box. A real terminal ([ -t 0 ] true) keeps the interactive prompt exactly as before. Adds a tier-1 black-box case in tests/stack/run.sh pinning the headless branch: re-running 'pithead setup' with stdin on /dev/null after a completed setup must not print "Setup skipped" and must re-provision. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…y rework) The security pass on the first cut caught that proceed-on-headless turned a long-safe automation probe (pithead setup on a deployed box) into an unattended re-provision — Tor recreate, full re-render, a possible GRUB edit — for any caller without a tty. The appliance's own headless paths never reach this guard (a failed provisioning attempt is not deployed), so nothing legitimate needed proceed. The bug in the issue was the silent FALSE SUCCESS (EOF swallowed as decline, exit 0); the fix is a loud refusal: nonzero exit, a message naming how to proceed. The sibling GRUB prompt gets the same treatment — headless skips the GRUB edit loudly instead of silently. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Closes #924. The bug:
read -r -p ... || trueswallowed the headless EOF into an empty answer — read as decline, exit 0 — so a headless retry believed setup succeeded while nothing ran.The first cut made headless PROCEED; the security pass caught that this turned a long-safe automation probe (
pithead setupon a deployed box via ssh/cron) into an unattended re-provision — Tor recreate, full re-render, a possible GRUB edit. And the appliance's own headless paths never reach this guard at all (a failed provisioning attempt is not deployed). So the shipped fix is the honest one: headless + deployed refuses loudly — nonzero exit, a message naming how to proceed (run './pithead setup' from a terminal;applyfor config changes). Interactive behavior unchanged. The sibling GRUB prompt gets the same treatment: headless skips the GRUB edit loudly instead of silently, so the operator learns the hugepage reservation is boot-only.Tier-1 black-box pins the refusal (nonzero, actionable text, never "skipped"-as-success): stack suite 2274/0 solo. Security re-review of the redesign: the refusal path introduces no new capability. Ponytail: one tty-split reused twice.
🤖 Generated with Claude Code