Ctrl K
ComunidadGuías…

docs/verify-release.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Verifying a Crux release

Every Crux release (tag `v*`) ships with a verifiable supply chain — threat
ref **T.5** in [THREAT_MODEL.md](THREAT_MODEL.md):

| Artifact | What proves it |
|---|---|
| Native release binaries (`corecruxd-*`, `crux-*`, `corecruxctl-*`, `crux-hook-*` for `linux-amd64` and both Darwin targets) | cosign keyless signature (`.sig` + `.pem` per file) + SLSA v1.0 provenance |
| Cross Linux release binaries (the same four prefixes for `linux-musl-amd64` and `linux-arm64`) | cosign keyless signature; not yet included as SLSA subjects |
| `RELEASE-MANIFEST-<target>.txt` | signed sha256 list covering every file in the release package (licences, docs, content) |
| `install.sh` | cosign keyless signature (`install.sh.sig` + `install.sh.pem`) and coverage by `RELEASE-MANIFEST-linux-amd64.txt` |
| `crux-daemon-<target>.cdx.json` | signed CycloneDX 1.6 SBOM of the workspace, per target |
| `multiple.intoto.jsonl` | SLSA provenance for native-target binaries, SBOMs, and manifests, generated by the SLSA L3 builder |
| Container image `ghcr.io/cuecrux/crux-daemon` | cosign keyless signature + CycloneDX SBOM attestation, both digest-addressed |

All signatures are **keyless** (Sigstore): short-lived certificates bound to
the GitHub Actions workflow identity, logged in the Rekor transparency log.
There is no long-lived signing key that can leak — what you verify is "this
exact artifact was built by the release workflow of `CueCrux/Crux` at this
tag".

Tooling: [`cosign`](https://docs.sigstore.dev/cosign/system_config/installation/)
and [`slsa-verifier`](https://github.com/slsa-framework/slsa-verifier#installation).
Set the tag you are verifying once:

```bash
TAG=v0.5.0   # the release you downloaded
REPO=CueCrux/Crux
```

## 1. Verify a release binary

Download the binary, its `.sig` and `.pem` from the GitHub Release, then:

```bash
cosign verify-blob \
  --certificate corecruxd-linux-amd64.pem \
  --signature corecruxd-linux-amd64.sig \
  --certificate-identity "https://github.com/${REPO}/.github/workflows/release.yml@refs/tags/${TAG}" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  corecruxd-linux-amd64
```

Expected output: `Verified OK`. Repeat for `crux-<target>`,
`corecruxctl-<target>`, `crux-hook-<target>`, the SBOM and the manifest (same
flags, different filenames).

Before running the installer, verify `install.sh` with the same command and
workflow identity, using `install.sh.pem` and `install.sh.sig`.

## 2. Verify the whole package via the signed manifest

The licence/docs/content files are not individually signed; they are covered
by the signed manifest:

```bash
cosign verify-blob \
  --certificate RELEASE-MANIFEST-linux-amd64.txt.pem \
  --signature RELEASE-MANIFEST-linux-amd64.txt.sig \
  --certificate-identity "https://github.com/${REPO}/.github/workflows/release.yml@refs/tags/${TAG}" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  RELEASE-MANIFEST-linux-amd64.txt

sha256sum --check --ignore-missing RELEASE-MANIFEST-linux-amd64.txt
```

Manifest entries use the flat public release-asset filenames. Download the
assets you want to verify into the same directory as the manifest; nested
repository staging paths do not need to be recreated. The release workflow
rejects duplicate basenames before publishing, so every checksum maps to one
unambiguous public asset.

The linux-amd64 manifest includes `install.sh`; the checksum command therefore
provides a second, manifest-rooted check when both files are present.

## 3. Verify SLSA provenance

`multiple.intoto.jsonl` (a release asset) attests that each native-target
binary was built from this repository at this tag by the SLSA L3 trusted
builder:

```bash
slsa-verifier verify-artifact corecruxd-linux-amd64 \
  --provenance-path multiple.intoto.jsonl \
  --source-uri "github.com/${REPO}" \
  --source-tag "${TAG}"
```

Expected output ends with `PASSED: SLSA verification passed`.

The `linux-musl-amd64` and `linux-arm64` cross-build legs are cosign-signed but
are not yet subjects in `multiple.intoto.jsonl`; do not claim a SLSA pass for
those files. Their signatures and signed release manifests remain verifiable
with steps 1 and 2.

## 4. Verify the container image

Always verify by digest, never by floating tag:

```bash
IMAGE=ghcr.io/cuecrux/crux-daemon:${TAG#v}
DIGEST_REF=$(cosign triangulate --type digest "${IMAGE}" 2>/dev/null || docker buildx imagetools inspect "${IMAGE}" --format '{{json .Manifest.Digest}}' | xargs -I{} echo "ghcr.io/cuecrux/crux-daemon@{}")

cosign verify \
  --certificate-identity "https://github.com/${REPO}/.github/workflows/docker.yml@refs/tags/${TAG}" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  "${DIGEST_REF}"
```

And the SBOM attestation attached to the image:

```bash
cosign verify-attestation \
  --type cyclonedx \
  --certificate-identity "https://github.com/${REPO}/.github/workflows/docker.yml@refs/tags/${TAG}" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  "${DIGEST_REF}" \
  | jq -r '.payload' | base64 -d | jq '.predicate.metadata'
```

Note: images built from `main` merges (the `edge` tag) are signed with
identity `…/docker.yml@refs/heads/main` instead of the tag ref.

## 5. Inspect the SBOM

```bash
jq '.components | length' crux-daemon-linux-amd64.cdx.json   # dependency count
jq -r '.components[] | "\(.name) \(.version)"' crux-daemon-linux-amd64.cdx.json | sort
```

Feed it to any CycloneDX-aware scanner (`trivy sbom crux-daemon-linux-amd64.cdx.json`,
Dependency-Track, etc.) to re-scan the exact dependency set that shipped.

## What failure looks like

- A tampered binary fails step 1 with `Error: searching log query matched zero entries` or a hash mismatch.
- A binary rebuilt outside CI fails step 3 (`FAILED: SLSA verification failed`) because no provenance exists for its hash.
- An image re-pushed by an attacker with `packages: write` fails step 4 — they cannot mint a certificate for the `docker.yml` workflow identity.

If any verification fails, do not run the artifact; report it via
[SECURITY.md](../SECURITY.md).