Skip to content

The installer verifies an artifact's digest and inspects its archive before anything is unpacked, and any failure leaves the previous installation working

curl … | sh is only as good as what the script does with what it downloads. This one, in

declared statusdeclared status: guaranteed Declared deterministic and blocking, implemented, and naming the behavioural test that is to prove it. Whether a recorded run supports it is the evidence verdict, shown beside it.

recorded evidencerecorded evidence: not run Declared guaranteed, and not supported by a recorded run: the test is named, and no passing run of the current inputs is recorded. how evidence is recorded

A wrong digest, a truncated download, an archive that escapes its own directory or carries a link, and an executable that reports another version are each refused by name, before the launcher is replaced. There is no warn-and-continue path and sudo appears nowhere.

What it means

curl … | sh is only as good as what the script does with what it downloads. This one, in order: resolves the machine and refuses an unsupported one by name; reads release metadata over HTTPS and matches every value it takes out of it against the shape it must have; checks the artifact URL against this project's own release host; verifies the SHA-256 and the size against the metadata before extracting anything; refuses an archive containing an absolute path, a .. traversal, a symbolic or hard link, a device, or any entry outside the archive's own directory; runs the unpacked tool once, from a temporary location, and requires it to report the version that was resolved.

Only then is the launcher replaced, by a rename. Every failure before that point leaves the previous installation exactly as it was, and says so.

How it works

The behaviour is share/install/install.sh.in; the platform facts it needs are a generated region inside it. sudo appears nowhere: a destination that cannot be written is named, not elevated. There is no warn-and-continue path — a digest mismatch discards the download and stops.

How to see it

curl -fsSL https://majordomus.dev/install.sh | sh -s -- --dry-run
bash test/run.sh 85_installer

The case builds a real archive from the tree you are in, serves real metadata over a real connection, installs it, and then attacks it: a corrupted digest, a truncated download, an archive that unpacks outside its own directory, an archive carrying a symlink to /etc/passwd, an executable that reports a different version, an unwritable destination, and a release that does not exist. After each one it requires the previously installed tool still to run and to report its own version.

What it does not cover

Checksums bind an artifact to its metadata; they do not prove who wrote the metadata. What remains trusted is GitHub Pages serving that metadata, GitHub Releases serving the artifacts, and the pipeline that produced both. Each archive is also attested by the release workflow, and the installer verifies that attestation when the GitHub CLI is installed and signed in — otherwise it says it verified the checksum only. A refused attestation is not fatal unless MAJORDOMUS_REQUIRE_PROVENANCE=1 asks for it, because GitHub answers an archive older than attestations and a substituted one the same way; docs/DISTRIBUTION.md states what each path verifies.

Why it exists

The failure mode of an installer is not that it fails. It is that it half-succeeds: a partially written binary where a working one was, or an archive that unpacked something into a directory nobody looked at. Both are prevented by the same discipline — verify first, stage beside, swap atomically — and both are tested by doing them.

Detail rendered from docs/claims/installer-verifies-before-installing.md.

From the statement to the proof

  1. 1 · the public statement

    The installer verifies an artifact's digest and inspects its archive before anything is unpacked, and any failure leaves the previous installation working

    Made on Install, Doctor.

  2. 2 · the canonical claim

    installer-verifies-before-installingdeclared status: guaranteed in docs/CLAIMS.yaml

    Defined in read it on this site · docs/INSTALL.md

  3. 3 · the implementation

    share/install/install.sh.in

  4. 4 · the test and the scenarios

    Test: test/cases/85_installer.sh

    Executed in Install the tool in one command, on a machine with no toolchain.

  5. 5 · the recorded runs

    recorded evidence: not run how evidence is recorded

Verify it yourself

The test runs in a disposable temporary repository and asserts the behaviour, not a string in the source.

from a clone of the repository
bash test/run.sh 85_installer

Where this claim is used

responsibilities it covers

Searches the titles and descriptions of every page this site publishes.