"Is This Installer Safe to Run?" What gitaiflow Checks Before It Installs
A plain account of how the installers verify a download, which checks are mandatory, which are best-effort, and what no installer can promise.
CB
Developers are right to hesitate at curl ... | bash. You're about to run a program fetched from the internet, with your user's permissions, and the only thing between you and a bad file is how carefully the installer checks it.
I'd rather you not take my word for it. This post lays out exactly what the gitaiflow installers verify, including the places where the guarantee is weaker than you might assume, so you can decide for yourself.
1. What Can Go Wrong Between My Build and Your Machine
There are three different failures, and they need different defenses:
- Accidental corruption. A truncated or damaged download.
- A swapped file. Someone replaces the binary on the server with a different one.
- A compromised distribution channel. Whoever controls the place the files are hosted replaces the binary and anything published next to it.
A checksum helps with the first two. Only a signature helps with the third.
2. What Every Release Publishes
Alongside the program for each platform, every release publishes two small files:
SHA256SUMS: a list of SHA-256 fingerprints, one per binary.SHA256SUMS.sig: an Ed25519 digital signature over that list.
The signature covers the checksum file rather than each binary. So if the list can be trusted, every fingerprint in it can be trusted.
3. The Checksum: Necessary, but Not Enough
All installers, on every platform, treat the checksum as mandatory. They abort if the checksum file can't be fetched, if it has no entry for your binary, or if the fingerprint of what you downloaded doesn't match.
That stops corruption and a casually swapped file. It doesn't stop a determined attacker, and I want to be direct about why: the checksum file is hosted next to the binary. Anyone who can replace the binary on the host can replace the checksum file to match it.
4. The Signature: Trust That Doesn't Depend on the Host
The signature closes that gap. It works because of where the keys live:
- The private key is kept offline in secret storage. It isn't on the file host, the build machine or the usual release credentials, and it's used briefly when a release is signed.
- The public key is built into the installer itself, and into the Claude Desktop extension. It is never fetched from the host, because a key served from the same place as the binary would let a compromised host swap its own trust anchor.
The result: an attacker who controls the host can replace the binary and rewrite the checksum list, but can't produce a signature that verifies against the public key you already have. Taking over the distribution channel is no longer enough to get a malicious binary installed.
5. What Each Install Path Actually Enforces
This is the part worth reading slowly, because the paths are not identical:
- macOS and Linux installer script: the checksum is mandatory. The signature check is best-effort, because it needs an OpenSSL build with raw Ed25519 support (3.2 or newer), and some systems, notably the LibreSSL that ships with macOS, don't have it. If the signature can't be checked, the installer prints a warning and continues, because the checksum still matched.
- Windows installer script: the checksum is mandatory. There is no signature check, because the PowerShell host can't reliably verify Ed25519.
- Claude Desktop extension: both are mandatory. After the installer finishes, the extension re-verifies the binary on its own, without trusting that the installer did anything, using Python's cryptography library, which supports Ed25519 on every platform it ships for.
So on the shell installers, read what they print. You want to see both of these lines:
==> Checksum verified. ==> Release signature verified.
If you see a Warning: about the signature instead, you got the weaker guarantee: a matching checksum, with no proof that the checksum file itself is genuine. The extension is the path that always checks the signature.
The diagram shows the macOS and Linux script. The extension is stricter, as the next one shows.
6. What Happens When a Check Fails
A failure leaves nothing behind that could be trusted later:
- The macOS and Linux installer downloads into a temporary file in the install folder and only moves it into place after the checks pass. The temporary file is removed when the script exits, whatever the reason.
- On Windows, a failed checksum removes the downloaded binary.
- In the extension, a binary that fails verification is deleted. This matters, because the extension only verifies right after a fresh install. A failed binary left on disk would otherwise be trusted on every later run.
The installer never runs the downloaded program. It installs per-user, with no sudo, and it doesn't edit your shell profile. If you don't already have ~/.gitaiflow/config.env, it creates an empty one and leaves an existing one untouched. On Windows it adds the install folder to your user PATH.
7. What Signing Does Not Protect Against
A security claim is only useful if you know where it ends:
- A compromised build before signing. A signature says "the release process signed off on this", not "this is free of bugs or malicious code".
- A stolen signing key. That's why it's kept offline and away from routine credentials.
- Anything installed before verification existed. Checks only run on new installs and updates.
- Anything after verification. This protects distribution. It isn't a sandbox and doesn't limit what the program does once it's running.
- Server-side revocation. There isn't any. The trust anchor is the public key in the installer you already have. If a key is ever rotated, the new public key has to ship in a new installer before anything is signed with it, and older installs will reject releases signed with a key they don't know until they're upgraded.
8. If You Want to Be Careful, Here's How
Don't pipe it. Download the script, read it, then run it, pinning the version so you know what you're getting:
curl -fsSL https://install.djangoplay.org/gitaiflow -o install.sh less install.sh bash install.sh v1.1.3
The public key and every check described above are in that script in plain text. Reading it takes a few minutes, and it is the most direct way to confirm this post is accurate.
Want the Full Picture?
This post covers installer verification. Installation options for every platform are in the gitaiflow documentation ↗.
What I'd Tell You Before You Run Any Installer
- A checksum next to a binary protects against accidents, not attackers. Ask what the checksum is anchored to.
- Ask which check is mandatory and which is best-effort. Many tools verify strictly on one platform and loosely on another, and the output tells you which you got.
- Read the script before you run it. It's short, it's text, and it's the one thing you can verify yourself.