Problem
The install script and ww perform upgrade fetch binaries from IPFS via IPNS (releases.wetware.run). Integrity is verified by checksums, but authenticity is not. The IPNS key is a single point of trust: if compromised, an attacker can serve malicious binaries with matching checksums.
Threat model
IPNS key compromised (via VPS breach, leaked SSH key, CI supply chain)
→ attacker publishes malicious CID to releases.wetware.run
→ binary + matching CHECKSUMS.txt served from attacker's CID
→ checksum verification passes
→ malicious binary runs `perform install` with full user access
Proposed solution
Sign CHECKSUMS.txt with an Ed25519 key held only in GitHub Actions (separate trust domain from VPS/IPNS). Verify the signature in both:
scripts/install.sh (using openssl pkeyutl, available on macOS + Linux)
ww perform upgrade (using ed25519-dalek, already a dependency)
Public key lives at share/keys/release.pub in the release tree (FHS convention for vendor-provided read-only data). The authoritative copy is hardcoded in install.sh (served via GitHub HTTPS) and compiled into the ww binary via include_bytes!.
Trust model
Signing key (private) Signing key (public)
│ │
│ stored as GitHub secret │ hardcoded in install.sh (GitHub HTTPS)
│ never touches VPS │ compiled into ww binary (include_bytes!)
│ │ published at share/keys/release.pub
▼ ▼
CI signs CHECKSUMS.txt ────> install.sh / ww verify CHECKSUMS.txt.sig
Two independent systems must both be compromised (IPNS key + signing key).
Implementation outline
- Generate Ed25519 keypair, store private as
RELEASE_SIGNING_KEY GitHub secret
- Commit public key to
share/keys/release.pub (base58) and share/keys/release.pub.raw (32 bytes for include_bytes!)
- CI publish job: sign CHECKSUMS.txt with openssl after assembly, place
.sig in release tree
scripts/install.sh: verify signature with openssl pkeyutl before trusting checksums (pubkey hardcoded as base64 DER)
src/cli/main.rs perform_upgrade: verify signature with ed25519-dalek before trusting checksums
- Key rotation: update GitHub secret + repo pubkey + install.sh hardcoded key. Users on old binary must re-run install script.
Files to modify
share/keys/release.pub (new)
share/keys/release.pub.raw (new)
scripts/install.sh
src/cli/main.rs (perform_upgrade, ~line 2557)
.github/workflows/rust.yml (publish job)
.github/workflows/release.yml (publish-ipfs job)
Not in scope
- Signed key rotation protocol
- macOS notarization
- Signing individual binaries (CHECKSUMS.txt covers them)
- Signing WASM components separately
Related
Problem
The install script and
ww perform upgradefetch binaries from IPFS via IPNS (releases.wetware.run). Integrity is verified by checksums, but authenticity is not. The IPNS key is a single point of trust: if compromised, an attacker can serve malicious binaries with matching checksums.Threat model
Proposed solution
Sign
CHECKSUMS.txtwith an Ed25519 key held only in GitHub Actions (separate trust domain from VPS/IPNS). Verify the signature in both:scripts/install.sh(usingopenssl pkeyutl, available on macOS + Linux)ww perform upgrade(usinged25519-dalek, already a dependency)Public key lives at
share/keys/release.pubin the release tree (FHS convention for vendor-provided read-only data). The authoritative copy is hardcoded ininstall.sh(served via GitHub HTTPS) and compiled into thewwbinary viainclude_bytes!.Trust model
Two independent systems must both be compromised (IPNS key + signing key).
Implementation outline
RELEASE_SIGNING_KEYGitHub secretshare/keys/release.pub(base58) andshare/keys/release.pub.raw(32 bytes for include_bytes!).sigin release treescripts/install.sh: verify signature withopenssl pkeyutlbefore trusting checksums (pubkey hardcoded as base64 DER)src/cli/main.rsperform_upgrade: verify signature with ed25519-dalek before trusting checksumsFiles to modify
share/keys/release.pub(new)share/keys/release.pub.raw(new)scripts/install.shsrc/cli/main.rs(perform_upgrade, ~line 2557).github/workflows/rust.yml(publish job).github/workflows/release.yml(publish-ipfs job)Not in scope
Related