Custodian
Guides

Verifying a release download

Confirm a custodian download is the one we published — check the signature over the checksum file, then the checksum of your download, and on macOS check the signed app bundle.

You downloaded custodian. Before you run it, you can confirm — without trusting us — that the bytes you have are the bytes we published. This page shows you how: verify the signature over the release's checksum file, then check your download against that file, and on macOS check the signed app bundle and run it.

Everything the Custodian server does is arranged so that breaching it achieves nothing, on the condition that the binary is what it says it is. This is how you check that condition.

What you need

Standard command-line tools:

  • sha256sum (GNU coreutils) — compare digests.
  • openssl — verify the signature and recompute the key fingerprint.
  • tar — unpack the macOS archive.
  • gh or curl — download the release assets.

What a release publishes

Each release publishes these assets. The download you take depends on your platform; the rest let you verify it.

AssetWhat it is
custodian-linux-arm64, custodian-linux-x64, custodian-windows-x64.exethe Linux and Windows binaries (single files)
custodian-darwin-arm64.app.tar.gz, custodian-darwin-x64.app.tar.gzthe macOS downloads — a custodian.app bundle, gzip-tarred
embedded.provisionprofilethe Developer ID provisioning profile the macOS bundle embeds (a build input)
checksums.txtthe SHA-256 of every asset as published
checksums.txt.sigthe detached ECDSA P-256 signature over checksums.txt
custodian-release-signing-key.pub.pem, .fingerprintthe signing public key and its fingerprint

embedded.provisionprofile is a build input the macOS bundle embeds, not a download you run; checksums.txt covers it like every other asset, but none of the checks on this page consume it.

The x64 builds require an x86-64-v3 CPU (AVX2). A host older than that will not run them — take the arm64 build there instead.

Fetch the assets

Work in an empty directory. Set the release tag you are verifying and the place you downloaded from:

export TAG=v0.3.0                              # the release you are verifying
export REPO=<the repository you downloaded from>
mkdir "custodian-verify-${TAG}" && cd "custodian-verify-${TAG}"

Fetch the binary you intend to run, the checksum file, its signature, and the signing key and its fingerprint. With gh (substitute your own download asset name — here, the linux-x64 binary):

gh release download "$TAG" -R "$REPO" --clobber \
  -p 'custodian-linux-x64' \
  -p 'checksums.txt' \
  -p 'checksums.txt.sig' \
  -p 'custodian-release-signing-key.pub.pem' \
  -p 'custodian-release-signing-key.fingerprint'

With curl instead, fetch each by its URL — curl -fSL -o checksums.txt "<url>/checksums.txt", and so on. How you fetch changes nothing about what the checks below prove; that is the point of verifying against a signature.

Confirm the signing key is the published one

Confirm the key you fetched matches its published fingerprint before you trust a signature made under it:

computed="sha256:$(openssl pkey -pubin \
  -in custodian-release-signing-key.pub.pem -outform DER | sha256sum | cut -d' ' -f1)"
echo "computed:  ${computed}"
echo "published: $(cat custodian-release-signing-key.fingerprint)"
test "${computed}" = "$(cat custodian-release-signing-key.fingerprint)" \
  && echo "fingerprint OK"
fingerprint OK

The published fingerprint is:

sha256:b477412e8852c1f35f0f1094cdf66527272ecc95b8faccebfc6e0a2070b67fba

Compare that fingerprint against the one shown in the release notes and here on this site. If any disagree, stop — do not proceed on a key you cannot corroborate.

Verify the signature over the checksum file

This proves the checksum file is one we published. The signature is ECDSA P-256 over the SHA-256 of the file:

openssl dgst -sha256 \
  -verify custodian-release-signing-key.pub.pem \
  -signature checksums.txt.sig \
  checksums.txt
Verified OK

A tampered checksum file, or the wrong key, prints Verification Failure and exits non-zero. A release from before the signing key was provisioned ships without a signature; if there is no checksums.txt.sig, you have no cryptographic binding to us for the checksum file, and you should treat the absent signature as a finding.

Verify your download against the checksum file

The signature above vouches for the checksum file; now confirm your download matches its entry in that file. --ignore-missing lets you check just the one asset you downloaded:

sha256sum -c --ignore-missing checksums.txt
custodian-linux-x64: OK

A changed byte anywhere in the download prints FAILED for that line and exits non-zero. For a macOS download, this checks the archive as published:

custodian-darwin-arm64.app.tar.gz: OK

At this point you know the checksum file is ours, it names the key we say it does, and your download is the byte-for-byte artefact that checksum file covers.

On macOS: check and run the app bundle

The macOS download is a custodian.app bundle inside the archive. Unpack the archive you just verified and run the executable inside it:

tar -xzf custodian-darwin-arm64.app.tar.gz          # → custodian.app
./custodian.app/Contents/MacOS/custodian version

Because the bundle is signed with a Developer ID certificate, notarised and stapled, it runs on a Mac that has never seen it before without turning off any protection and without a network round-trip to Apple on first launch.

Confirm the signature, the team identifier and the keychain entitlement. These commands are macOS-only:

# a valid Developer ID signature and the team identifier (35Z4D8S6ZM)
codesign --verify --deep --strict --verbose=2 custodian.app
codesign -dvv custodian.app 2>&1 | grep -E 'Authority|TeamIdentifier'

# the entitlement that authorises the data protection keychain
codesign -d --entitlements :- custodian.app 2>&1 | grep -A1 keychain-access-groups

# Gatekeeper accepts it, and the staple means no network is needed
spctl --assess --type execute --verbose=4 custodian.app
stapler validate custodian.app

A download whose signature does not verify, whose team identifier is not 35Z4D8S6ZM, or which carries no keychain-access-groups entitlement is not the one we published — treat it as suspect. That entitlement is also what lets custodian create a device key in the Secure Enclave on this Mac; without it, device-key operations are refused. See enrolling and managing devices.

What these checks prove — and what they do not

  • The signature says we published these bytes. It is a binding to the publisher, not to the source: it says nothing about what the bytes do.
  • The checksum says the bytes you hold are unmodified since the checksum file was written — and, anchored by the signature, since we wrote it.

Treat the checksum file as trusted only to the extent you trust the signature over it and the channel you fetched it over. None of these checks tells you the software is safe to run — that is a judgement you make by other means; they tell you only that what you downloaded is what we published.

On this page