Skip to content

fix(remote): abort the bootstrap when the installer cannot be fetched - #189

Open
tas50 wants to merge 1 commit into
mainfrom
fix/bootstrap-detects-install-failure
Open

fix(remote): abort the bootstrap when the installer cannot be fetched#189
tas50 wants to merge 1 commit into
mainfrom
fix/bootstrap-detects-install-failure

Conversation

@tas50

@tas50 tas50 commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

The defect

The generated script opens with set -e and then runs:

curl -L 'https://omnitruck.cinc.sh/install.sh' | sudo bash -s --

A pipeline reports only the exit status of its last command, so set -e sees bash's status, not curl's. A 404, a DNS failure, or a TLS error is silently swallowed — bash cheerfully executes an empty or error-page input and exits 0 — and the script marches on to:

sudo cinc-client -j /etc/cinc/first-boot.json

which is not installed. The operator gets a confusing downstream failure instead of the real one, and cinc node bootstrap reports it against a host that is now half-configured.

The fix

Download to a temp file and run that, so a failed fetch is a failed command that set -e acts on:

set -e
CINC_INSTALLER="$(mktemp)"
trap 'rm -f "$CINC_INSTALLER"' EXIT
curl -fsSL 'https://omnitruck.cinc.sh/install.sh' -o "$CINC_INSTALLER"
sudo bash "$CINC_INSTALLER" -v '18'
  • -f so an HTTP error is a failure rather than an error page saved and executed as the "installer".
  • -sS to keep the progress meter out of the SSH output while preserving real error messages.
  • trap so the file is removed even when a later step fails.

set -o pipefail would also fix it, but it is not POSIX and the script runs under whatever login shell the target happens to have — dash, notably, does not support it.

bash -s -- becomes bash "$CINC_INSTALLER": -s means "read the script from stdin", which no longer applies, and the -- would otherwise be passed to the installer as $1.

The trust assumption is unchanged. The target still executes whatever the bootstrap URL serves; this only makes a failure to fetch it visible.

Tests

  • TestBootstrapCommandStopsWhenTheInstallerCannotBeFetched — no pipe into a shell, curl uses -f, set -e retained.
  • TestBootstrapCommandCleansUpTheInstaller — the temp file is trapped for removal.
  • TestBootstrapCommandBuildsCincClientScript and TestNodeBootstrapDryRunCommand both pinned the old curl line and are updated.

go test ./..., go vet ./..., and gofmt -l . are clean.

@tas50
tas50 force-pushed the fix/bootstrap-detects-install-failure branch 3 times, most recently from ad92bcf to 8a21cdc Compare September 8, 2026 17:38
The script opened with `set -e` and then ran

  curl -L <url> | sudo bash -s --

A pipeline reports only the exit status of its last command, so `set -e`
saw bash's status, not curl's. A 404, a DNS failure or a TLS error was
silently swallowed and the script marched on to run a cinc-client that
had never been installed. The operator then had to diagnose a confusing
downstream failure instead of the real one, a bad download.

Download to a temp file and run that, so a failed fetch is a failed
command that `set -e` acts on. curl gains -f, without which an HTTP error
page is saved and executed as the "installer", and -sS to keep the
progress meter out of the SSH output while preserving real error
messages. A trap removes the file even when a later step fails.

`set -o pipefail` would also work but is not POSIX, and the script runs
under whatever login shell the target has.

The trust assumption is unchanged: the target still executes whatever
the bootstrap URL serves.

Signed-off-by: Tim Smith <tim@mondoo.com>
@tas50
tas50 force-pushed the fix/bootstrap-detects-install-failure branch from 8a21cdc to 4fb5aba Compare September 8, 2026 17:42
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