Skip to content

fix(dispatcher): Verify project runner archive attestation before extraction#1672

Merged
hatayama merged 1 commit into
v3-betafrom
feat/attestation-integrate-runner
Jul 10, 2026
Merged

fix(dispatcher): Verify project runner archive attestation before extraction#1672
hatayama merged 1 commit into
v3-betafrom
feat/attestation-integrate-runner

Conversation

@hatayama

@hatayama hatayama commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

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.

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 with attestationRunnerPublishWorkflowPath.

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.json bundle cryptographically verifies against Sigstore's public-good trust anchor, the workflow identity matches .github/workflows/native-cli-publish.yml on an allowed ref (refs/heads/v3-beta or refs/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

  • downloadDispatcherRealCLIForPin now calls verifyReleaseAssetAttestation with attestationRunnerPublishWorkflowPath after the sha256 check succeeds but before the archive is extracted.
  • Existing TestDownloadDispatcherRealCLIWritesDownloadStatus stubs the attestation hook (unchanged behavior).
  • Two new tests cover the runner integration: fail-closed on attestation error, and the exact uloop-project-runner-v<version> release tag + native-cli-publish.yml workflow path forwarded to the hook.

Verification

  • scripts/check-go-cli.sh — 0 lint issues across all Go modules
  • go test ./... in cli/dispatcher/ — all packages pass

Follow-up

Phase B4 (dispatcher self-update archive verification via ULOOP_EXPECTED_ARCHIVE_SHA256 from a verified in-toto statement) remains — see Obsidian spec line 68-71. The self-update path in update.go only 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

Review in cubic

…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.
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@hatayama, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 16 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 68c7e6de-1d52-4bff-8a9b-f71fe9a074e5

📥 Commits

Reviewing files that changed from the base of the PR and between 109bc9f and 2b25b89.

📒 Files selected for processing (2)
  • cli/dispatcher/internal/dispatcher/dispatcher_download.go
  • cli/dispatcher/internal/dispatcher/dispatcher_test.go
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/attestation-integrate-runner

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@hatayama
hatayama merged commit fa3313d into v3-beta Jul 10, 2026
9 checks passed
@hatayama
hatayama deleted the feat/attestation-integrate-runner branch July 10, 2026 04:20
@github-actions github-actions Bot mentioned this pull request Jul 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant