Skip to content

Install Seal v0.4.0

The v0.4.0 release publishes seal-v0.4.0-darwin-arm64, seal-v0.4.0-darwin-x64, seal-v0.4.0-linux-x64, seal-receipt-v2.mjs, and SHA256SUMS; its tag resolves to commit dabac65caaa999a789be9329e02a70a5173fd7d0. Its release-manifest.json uses schema seal.release/v2. This checkout supports Protect on Linux x86-64 and macOS x64/arm64. The native macOS process-start witness helper is release-produced, not independently reproduced. Windows and Linux ARM are unsupported. Node 20+ is required. The installer refuses before changing anything on an unsupported or mismatched platform.

This page is the SHA256SUMS verification wall. The README short form uses the same shell gate. In every install command below, a failed checksum comparison prevents both chmod and execution of the artifact. The commands use POSIX syntax for sh, dash, bash, and zsh. Copy each whole command, including its continuation backslashes and && operators; there is no shell-option preamble. The release version is a separate assignment; omitting it cannot remove the verification gate. Each continuation starts with &&, so copying a continuation alone produces a syntax error.

The digest comparison below is your check, with the OS SHA-256 tool, against the SHA256SUMS asset attached to the same GitHub release. That is not the installer checking itself. The --sha256 flag is a second pin the installer demands and will refuse without. The optional --bytes flag adds a length check. Together they answer “did I download the bytes the release named?” They do not answer “is the publisher honest?”

Terminal window
SEAL_VERSION=v0.4.0
artifact_name="seal-v0.4.0-linux-x64" \
&& artifact_sha256="5b49ea26d29b608fcb4e3e370062b96e8c4a81d7fb5ce1fd30a2cbe737c69d3b" \
&& artifact_bytes=6301771 \
&& sums_name="SHA256SUMS" \
&& sums_sha256="0552373fc3cb7f7257b4cf491395425a1ce2f7126cc60142a961f53ff29026ce" \
&& checker_name="seal-receipt-v2.mjs" \
&& checker_sha256="d0767c186e5a284ab1a78ea27b75d3a3d6a91101a96874b6c4936776ba4850ac" \
&& checker_bytes=10498 \
&& curl -fsSLO "https://github.com/velvetmonkey/seal/releases/download/$SEAL_VERSION/$sums_name" \
&& curl -fsSLO "https://github.com/velvetmonkey/seal/releases/download/$SEAL_VERSION/$artifact_name" \
&& curl -fsSLO "https://github.com/velvetmonkey/seal/releases/download/$SEAL_VERSION/$checker_name" \
&& if command -v shasum >/dev/null 2>&1; then sums_actual="$(shasum -a 256 "$sums_name")"; else sums_actual="$(sha256sum "$sums_name")"; fi \
&& test "${sums_actual%% *}" = "$sums_sha256" \
&& expected_record="$(awk -v name="$artifact_name" '$3 == name { print $1, $2, $3 }' "$sums_name")" \
&& test "$expected_record" = "$artifact_sha256 $artifact_bytes $artifact_name" \
&& if command -v shasum >/dev/null 2>&1; then actual_digest="$(shasum -a 256 "$artifact_name")"; else actual_digest="$(sha256sum "$artifact_name")"; fi \
&& test "${actual_digest%% *}" = "$artifact_sha256" \
&& actual_bytes="$(wc -c < "$artifact_name")" \
&& test "$actual_bytes" -eq "$artifact_bytes" \
&& checker_record="$(awk -v name="$checker_name" '$3 == name { print $1, $2, $3 }' "$sums_name")" \
&& test "$checker_record" = "$checker_sha256 $checker_bytes $checker_name" \
&& if command -v shasum >/dev/null 2>&1; then checker_actual="$(shasum -a 256 "$checker_name")"; else checker_actual="$(sha256sum "$checker_name")"; fi \
&& test "${checker_actual%% *}" = "$checker_sha256" \
&& checker_count="$(wc -c < "$checker_name")" \
&& test "$checker_count" -eq "$checker_bytes" \
&& chmod +x "$artifact_name" \
&& ./"$artifact_name" --sha256 "$artifact_sha256" --bytes "$artifact_bytes" --prefix ~/.local

Success prints installed seal 0.4.0 linux-x64 and the store, command, and tree lines. Path prefixes on store: and command: differ per machine. The tree hash of the published v0.4.0 asset is pinned here:

Seal installed-tree pin role: published-asset

installed seal 0.4.0 linux-x64
store: /home/you/.local/lib/seal/store/261324816077d3ab04cd55640ec79b605f2845dadb7b56d057892111601ffe32
command: /home/you/.local/bin/seal
tree: 261324816077d3ab04cd55640ec79b605f2845dadb7b56d057892111601ffe32

Add ~/.local/bin to PATH:

Terminal window
$ export PATH="$HOME/.local/bin:$PATH"

Further distribution detail, including what each payload contains, is in DISTRIBUTION.md. The downloaded checker is only checked against SHA256SUMS; from a source checkout, run node checker/seal-receipt-v2.mjs docs/reference/receipt-operations-v1/receipt-block.json.

A build of this checkout (not the published release asset) writes dist/seal-v<identity>-linux-x64. That tree digest is a different claim from the published-asset pin above:

Seal installed-tree pin role: fresh-build

tree: b38dfbc1c47392309a5063e5c274f37dbe9533cabc26d3e79082417151eda9ac

That hash is the installed-tree digest of the payload scripts/build-dist.cjs packs from this tree. It is not a captured command transcript. It will change when a payload member changes; it does not change when only docs change.

The installed tree is exactly the regular payload files named by the artifact’s payload manifest (a fresh build includes checker/seal-receipt-v2.mjs for seal verify). Order those relative slash-separated paths by bytewise lexicographic path order. For each file, SHA-256 its exact payload bytes and form one UTF-8 line: <file-sha256><two spaces><decimal byte count><two spaces><path><newline>. Concatenate those lines without another separator and SHA-256 the resulting UTF-8 byte sequence. That final digest is the installed-tree hash. The same definition applies to a published asset; its payload manifest, rather than this checkout, selects its file set.

Build and install this checkout on Linux x86-64

Section titled “Build and install this checkout on Linux x86-64”

For the source-build evaluator walk, run this from the checkout root with Node 20+ on Linux x86-64. It builds the artifact, checks its SHA-256 digest and byte count, and installs under this checkout’s dist/local directory:

Terminal window
platform="linux-$(node -p 'process.arch')" \
&& node scripts/build-dist.cjs --platform "$platform" --out dist \
&& read -r expected_digest expected_bytes expected_name < dist/SHA256SUMS \
&& test "$expected_name" = "$(node scripts/product-identity.cjs --artifact-name | sed 's/-linux-x64$//')-$platform" \
&& test -n "$expected_digest" \
&& if command -v shasum >/dev/null 2>&1; then actual_digest="$(shasum -a 256 "dist/$expected_name")"; else actual_digest="$(sha256sum "dist/$expected_name")"; fi \
&& test "${actual_digest%% *}" = "$expected_digest" \
&& actual_bytes="$(wc -c < "dist/$expected_name")" \
&& test "$actual_bytes" -eq "$expected_bytes" \
&& chmod +x "dist/$expected_name" \
&& ./"dist/$expected_name" --sha256 "$expected_digest" --bytes "$expected_bytes" --prefix "$PWD/dist/local"

Add this installation to PATH in the same shell before following the walk:

Terminal window
$ export PATH="$PWD/dist/local/bin:$PATH"

The macOS CI lane selects macos-15 for darwin-arm64 and macos-15-intel for darwin-x64. CI passes --macos-helper to include the matching native process-start witness helper in the payload. For this recipe, set MACOS_HELPER to the path of that helper from the matching release runner. The recipe selects the artifact label from Node’s running architecture and uses the SHA-256 utility shipped by macOS when GNU sha256sum is absent:

Terminal window
platform="darwin-$(node -p 'process.arch')" \
&& node scripts/build-dist.cjs --platform "$platform" --macos-helper "$MACOS_HELPER" --out dist \
&& read -r expected_digest expected_bytes expected_name < dist/SHA256SUMS \
&& test "$expected_name" = "$(node scripts/product-identity.cjs --artifact-name | sed 's/-linux-x64$//')-$platform" \
&& test -n "$expected_digest" \
&& if command -v shasum >/dev/null 2>&1; then actual_digest="$(shasum -a 256 "dist/$expected_name")"; else actual_digest="$(sha256sum "dist/$expected_name")"; fi \
&& test "${actual_digest%% *}" = "$expected_digest" \
&& actual_bytes="$(wc -c < "dist/$expected_name")" \
&& test "$actual_bytes" -eq "$expected_bytes" \
&& chmod +x "dist/$expected_name" \
&& ./"dist/$expected_name" --sha256 "$expected_digest" --bytes "$expected_bytes" --prefix ~/.local

This checkout supports Protect on Linux x86-64 and macOS x64/arm64. The native macOS process-start witness helper is release-produced, not independently reproduced. macOS Protect execution is not exercised in CI.

Run the harmless approve-once demo and answer y:

Terminal window
demo_dir="$(mktemp -d)" && demo_dir="$(cd "$demo_dir" && pwd -P)" && printf 'y\n' | seal demo --dir "$demo_dir" && printf 'Demo directory: %s\n' "$demo_dir"

When you are finished, remove the directory printed as Demo directory: /absolute/path.

If you installed the published release, continue with Choosing what to protect. If you built and installed this checkout, continue with the Evaluator walk.

Previous: Start. Up: Start. Next: Evaluator walk.