fix(dispatcher): Verify project runner archive attestation before extraction#1672
Conversation
…raction The dispatcher project-runner download flow now requires a valid Sigstore attestation for each downloaded `uloop-project-runner-*.tar.gz` / `uloop-project-runner-*.zip` archive before it will extract and cache the runner binary. Fail-closed on bundle-missing, network-failure, digest-mismatch, and identity-mismatch — the .sha256 file ships from the same origin as the archive and cannot certify authenticity if that origin is compromised. This is Phase B3 of TODO 2 (Obsidian spec). Phase B2 (PR #1671, installer attestation) already merged; the shared verifier hook and identity constants from B2 are reused here with attestationRunnerPublishWorkflowPath. The existing TestDownloadDispatcherRealCLIWritesDownloadStatus test now stubs the attestation hook so it still verifies download status behavior without an outbound sigstore call. Two new tests cover the attestation integration: fail-closed on hook error, and the exact release tag + workflow path that get forwarded to the hook.
|
Warning Review limit reached
Next review available in: 16 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
The dispatcher project-runner download flow now requires a valid Sigstore attestation for each downloaded
uloop-project-runner-*.tar.gz/uloop-project-runner-*.ziparchive before it will extract and cache the runner binary.This is Phase B3 of TODO 2 (
docs/plans/). Phase B1 (PR #1670) added the verifier package; Phase B2 (PR #1671) wired the installer path. This PR reuses the shared verifier hook and identity constants from B2 withattestationRunnerPublishWorkflowPath.User Impact
Before: A compromised GitHub releases origin could serve a malicious
uloop-project-runner-*.tar.gz+ matching.sha256, and the dispatcher would happily extract and execute it — sha256 alone cannot prove authenticity when the checksum ships from the same origin as the archive.After: The runner archive will not be extracted unless its
.sigstore.jsonbundle cryptographically verifies against Sigstore's public-good trust anchor, the workflow identity matches.github/workflows/native-cli-publish.ymlon an allowed ref (refs/heads/v3-betaorrefs/heads/main), and the release tag's commit SHA matches the certificate's Source Repository Digest extension (OID 1.3.6.1.4.1.57264.1.13). Fail-closed on bundle-missing, network-failure, digest-mismatch, and identity-mismatch.Changes
downloadDispatcherRealCLIForPinnow callsverifyReleaseAssetAttestationwithattestationRunnerPublishWorkflowPathafter the sha256 check succeeds but before the archive is extracted.TestDownloadDispatcherRealCLIWritesDownloadStatusstubs the attestation hook (unchanged behavior).uloop-project-runner-v<version>release tag +native-cli-publish.ymlworkflow path forwarded to the hook.Verification
scripts/check-go-cli.sh— 0 lint issues across all Go modulesgo test ./...incli/dispatcher/— all packages passFollow-up
Phase B4 (dispatcher self-update archive verification via
ULOOP_EXPECTED_ARCHIVE_SHA256from a verified in-toto statement) remains — see Obsidian spec line 68-71. The self-update path inupdate.goonly attests the installer script; the archive that install.sh downloads is still same-origin-sha256-only, so TODO 2's acceptance criterion is not yet met on the self-update path. Runner downloads (this PR) do not have that gap because the dispatcher extracts the archive directly in Go.Refs:
docs/plans/spec, TODO 2 Phase B3