← Blog

Why Oam.js ships unsigned, checksummed binaries

August 8, 2026

Every Oam.js release binary is unsigned. No Apple notarization, no Windows Authenticode. What every release does ship is a SHA256SUMS manifest, and the installers refuse to install anything that does not match it. This post spells the trust model out: what gets verified, what that verification proves, and — just as important — what it does not.

What the installer actually verifies

curl -fsSL https://oamjs.org/install.sh | sh downloads two things into a temp directory: the binary for your OS and architecture, and the SHA256SUMS manifest published by the same release. Then it:

The failure paths refuse rather than degrade. No entry for the asset in the manifest: refuse. Neither sha256sum nor shasum on the machine: refuse, rather than install unverified. Pointing OAM_INSTALL_BASE at a mirror does not relax anything — whatever the source, the installer still verifies against the published SHA256SUMS. And oam self-update re-runs this same installer, so there is one copy of the verify logic, not two drifting ones.

What a checksum proves — and what it does not

A matching SHA-256 proves you received exactly the bytes the release published. A flipped bit in transit, a truncated download, a proxy serving a stale file — the check catches all of it, loudly.

It does not prove who published those bytes. A code signature binds a binary to an identity through a certificate authority; a checksum binds it to whatever the release page currently says. Someone in control of the YawLabs/oam GitHub account could publish a malicious binary and a SHA256SUMS that matches it, and every check above would pass. The trust anchor is GitHub account control, nothing stronger. The installer prints checksum ok, and that is easy to read as more than it is — so here it is, stated plainly.

Why ship unsigned at all

Because of how oam actually reaches machines. The canonical channel is the one-line installer, and curl, scoop and brew fetches bypass the Gatekeeper and SmartScreen quarantine entirely — on that path a signature would change nothing about the install, and the SHA256SUMS manifest is the integrity check. The release script does keep a documented seam where a signing step — notarization, Authenticode — would slot in without changing the installers. That is a fact about the script, not a commitment.

The cost lands on the other path. macOS quarantines files downloaded by a browser, and these binaries are unsigned, so Gatekeeper refuses the first run of a hand-downloaded binary. The workaround, after moving it into place:

xattr -d com.apple.quarantine ~/.local/bin/oam

Verify the checksum first. Clearing the quarantine attribute is you personally asserting the trust a signature would have carried — the wrong move on bytes you have not checked.

Why four extra files ship with every release

Alongside the binaries, every release publishes SHA256SUMS, and every release since v0.8.1 adds LICENSE, NOTICE and THIRD_PARTY_LICENSES.md. The manifest is the trust model above. The other three exist because the binary is a binary redistribution of V8, ICU, the Node streams port and ~380 Rust crates, and those licenses require their notices to travel with the bytes. THIRD_PARTY_LICENSES.md reproduces the notices for the Rust crates; NOTICE carries what no cargo tool can see — V8 itself, the 16 third-party trees bundled inside the prebuilt V8 static library, the vendored Node.js sources, the vendored web-platform-tests data.

The installer copies the three license files next to the binary, in ~/.oam/bin/licenses, so the copy on your machine carries its own attribution instead of pointing back at a repo. Best-effort, and honestly so: releases before v0.8.1 shipped no license assets, and on those the installer says so rather than leaving an empty directory that implies otherwise.

Verifying by hand

If you take a binary from the downloads page instead of running the installer, the same check is two commands. macOS and Linux — check every file the release published:

curl -fsSLO https://github.com/YawLabs/oam/releases/download/v0.9.0/SHA256SUMS
shasum -a 256 -c SHA256SUMS --ignore-missing

Or one file, compared against the manifest by eye:

shasum -a 256 oam-aarch64-apple-darwin

Windows (PowerShell):

Get-FileHash .\oam-x86_64-pc-windows-msvc.exe -Algorithm SHA256 | Format-List

One trap: Get-FileHash prints uppercase and the manifest is lowercase. Compare case-insensitively, or pipe through .Hash.ToLower().

The current release is v0.9.0. The full table of binaries, sizes and sums — and the OAM_VERSION knob for pinning one — is on the downloads page.