Skip to content

fix(sigstore): apply url_replacements to Sigstore TUF root fetch#10596

Merged
jdx merged 1 commit into
jdx:mainfrom
JamBalaya56562:fix-sigstore-tuf-url-replacements
Jun 24, 2026
Merged

fix(sigstore): apply url_replacements to Sigstore TUF root fetch#10596
jdx merged 1 commit into
jdx:mainfrom
JamBalaya56562:fix-sigstore-tuf-url-replacements

Conversation

@JamBalaya56562

@JamBalaya56562 JamBalaya56562 commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes discussion #10437: mise install of an aqua cosign-verified tool (e.g. cosign = "3.1.1") fails behind a mirror because the Sigstore TUF root fetch ignores settings.url_replacements:

TUF repository load failed: Failed to fetch https://tuf-repo-cdn.sigstore.dev/15.root.json

Root cause

The Sigstore public-good TUF root is fetched inside the external sigstore-verify crate via TrustedRoot::production() (crates/mise-sigstore/src/lib.rs), which hardcodes https://tuf-repo-cdn.sigstore.dev and uses its own HTTP client. That bypasses mise's apply_url_replacements, which only runs inside mise's own HTTP client.

Fix

Route the TUF root fetch through the same mirror as the rest of mise's traffic:

  • src/github/sigstore.rs (the sole bridge): add routed_tuf_url() (mirrors the existing routed_api_url()), which applies url_replacements to the canonical TUF URL and returns the replaced URL only when it actually changed. It is pushed into mise-sigstore via set_tuf_url(...) at the start of every entry point that can trigger a TUF fetch: cosign (verify_cosign_signature, verify_cosign_signature_with_key), SLSA (verify_slsa_provenance, verify_slsa_provenance_artifacts), and attestations (verify_attestation, verify_attestation_with_predicate_type).
  • crates/mise-sigstore/src/lib.rs: add a process-global override (set_tuf_url) read at the single chokepoint production_trusted_root(). When an override is set it uses TufConfig::custom(mirror_url, PRODUCTION_TUF_ROOT) + TrustedRoot::from_tuf; otherwise it keeps the default (TufConfig::production()), which is identical to today's TrustedRoot::production().

Security

The mirror branch still bootstraps from the embedded production root (PRODUCTION_TUF_ROOT). TUF verifies all fetched metadata against this pinned root, so a malicious or compromised mirror cannot forge the chain of trust — it can only mirror the identical content. The custom-root pin is required: the sigstore crate only falls back to its embedded root for the known canonical URL, so a mirror URL without the explicit root fails closed. A code comment documents this to prevent regressions.

With no url_replacements configured, behavior is byte-for-byte unchanged.

Testing

Pure, network-free unit tests (run by CI):

  • src/github/sigstore.rs: test_routed_tuf_url_applies_url_replacement, test_routed_tuf_url_none_without_replacement (model on the existing routed_api_url tests, using SettingsGuard).
  • crates/mise-sigstore/src/lib.rs: select_tuf_config_default_uses_production_url, select_tuf_config_override_uses_mirror_url.

rustfmt --edition 2024 --check passes on the changed files.

Note

The authoring sandbox can't build mise (insufficient memory), so compilation/clippy/tests are left to CI. Manual end-to-end check for a maintainer: set MISE_URL_REPLACEMENTS mapping https://tuf-repo-cdn.sigstore.dev to a working mirror and run mise install cosign@3.1.1 — the TUF fetch should hit the mirror and verification should still succeed; with no replacement it should still hit the default CDN.

Known limitation

Custom (mirror) TUF URLs have no embedded offline-fallback targets in the sigstore crate, so offline + mirror is not supported (online mirror only). Not relevant to the reported use case.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added configurable Sigstore TUF trust-root URL support for custom verification sources.
    • Sigstore verification now honors routed/mirrored URL replacement rules across all related operations.
  • Tests
    • Added coverage to confirm TUF URL selection and URL routing/replacement behavior.

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: e727038b-491f-4c5e-b97f-cb26cf9fe399

📥 Commits

Reviewing files that changed from the base of the PR and between 6146bfc and ac33273.

📒 Files selected for processing (2)
  • crates/mise-sigstore/src/lib.rs
  • src/github/sigstore.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/mise-sigstore/src/lib.rs
  • src/github/sigstore.rs

📝 Walkthrough

Walkthrough

The PR adds a configurable Sigstore TUF URL override to the mise-sigstore crate via a process-global RwLock, a new set_tuf_url() export, and a select_tuf_config() function. In src/github/sigstore.rs, a new routed_tuf_url() helper applies mise URL replacements to the default TUF URL, and all six sigstore verification entry points call set_tuf_url(routed_tuf_url()) before executing.

Changes

Sigstore TUF URL Override and Routing

Layer / File(s) Summary
TUF URL override infrastructure in mise-sigstore
crates/mise-sigstore/src/lib.rs
Re-exports DEFAULT_TUF_URL and expands trust-root imports; adds TUF_URL_OVERRIDE (RwLock<Option<String>>), exports set_tuf_url(), introduces select_tuf_config() to choose TufConfig::custom with pinned PRODUCTION_TUF_ROOT when override is set or TufConfig::production() otherwise; updates production_trusted_root() to use selected config; adds two unit tests for both selection paths.
URL replacement routing in github/sigstore.rs
src/github/sigstore.rs
Adds routed_tuf_url() which parses DEFAULT_TUF_URL, applies mise url_replacements, and returns Some only when URL differs; calls mise_sigstore::set_tuf_url(routed_tuf_url()) at the top of verify_attestation, verify_attestation_with_predicate_type, verify_slsa_provenance, verify_slsa_provenance_artifacts, verify_cosign_signature, and verify_cosign_signature_with_key; adds two tests for replacement and no-replacement cases.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant sigstore_rs as github/sigstore.rs
    participant http as http::apply_url_replacements
    participant mise_sigstore as mise_sigstore crate

    Caller->>sigstore_rs: verify_attestation / verify_slsa_provenance / verify_cosign_signature
    sigstore_rs->>http: apply_url_replacements(DEFAULT_TUF_URL)
    http-->>sigstore_rs: replaced URL or unchanged
    alt URL changed
        sigstore_rs->>mise_sigstore: set_tuf_url(Some(replaced_url))
    else no change
        sigstore_rs->>mise_sigstore: set_tuf_url(None)
    end
    sigstore_rs->>mise_sigstore: verify_*()
    mise_sigstore->>mise_sigstore: select_tuf_config() → TufConfig::custom or TufConfig::production
    mise_sigstore->>mise_sigstore: TrustedRoot::from_tuf(config).await
    mise_sigstore-->>sigstore_rs: verification result
    sigstore_rs-->>Caller: result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 Hop hop, the TUF root bends,
A mirror URL the config sends.
With RwLock guarding the override gate,
Each verify call sets the URL straight.
No more hardcoded production path—
Just route the trust along the right math! 🌐

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(sigstore): apply url_replacements to Sigstore TUF root fetch' directly and clearly summarizes the main change: applying URL replacements to the Sigstore TUF root fetch mechanism, which is the core bug fix described in the PR objectives.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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.

@greptile-apps

greptile-apps Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a mirror/proxy bypass for the Sigstore TUF root fetch: the external sigstore-verify crate's TrustedRoot::production() hardcoded https://tuf-repo-cdn.sigstore.dev and used its own HTTP client, so settings.url_replacements never applied to it. The fix routes the TUF root fetch through the same replacement logic as the rest of mise's traffic.

  • Adds a process-global TUF_URL_OVERRIDE in mise-sigstore with set_tuf_url/select_tuf_config helpers; production_trusted_root() now reads the override, and mirror fetches are explicitly bootstrapped from the embedded PRODUCTION_TUF_ROOT to preserve the chain of trust.
  • Adds routed_tuf_url() in the sigstore bridge module (mirroring the existing routed_api_url pattern) and calls set_tuf_url at the top of every public verification entry point, with pure unit tests for both the replacement and no-replacement paths.

Confidence Score: 5/5

Safe to merge — the change is narrowly scoped, the no-replacement path is byte-for-byte unchanged, and the security-sensitive mirror branch pins the embedded production root.

Both changed files have clear, well-commented logic. The global TUF URL override is always set to the same deterministic value (derived from static settings) before any TUF fetch occurs, lock poisoning is handled explicitly, and the embedded production root is required for mirror bootstrapping to keep the TUF chain of trust intact. Previous review comments about lock-poisoning recovery and the missing debug log have both been addressed. Unit tests cover the replacement and no-replacement paths without network access.

No files require special attention.

Important Files Changed

Filename Overview
crates/mise-sigstore/src/lib.rs Adds process-global TUF_URL_OVERRIDE with set_tuf_url/select_tuf_config helpers; production_trusted_root() now reads the override. Lock-poisoning recovery uses unwrap_or_else(
src/github/sigstore.rs Adds routed_tuf_url() (mirrors routed_api_url pattern with debug log on parse failure) and injects set_tuf_url at the top of every public verification entry point; unit tests cover both replacement and no-replacement cases.

Reviews (2): Last reviewed commit: "fix(sigstore): apply url_replacements to..." | Re-trigger Greptile

Comment thread crates/mise-sigstore/src/lib.rs
Comment thread src/github/sigstore.rs
@JamBalaya56562
JamBalaya56562 force-pushed the fix-sigstore-tuf-url-replacements branch from fa24aa4 to 6146bfc Compare June 24, 2026 04:02
The Sigstore public-good TUF root fetch happens inside the sigstore-verify
crate via `TrustedRoot::production()`, which hardcodes
`https://tuf-repo-cdn.sigstore.dev` and uses its own HTTP client, bypassing
mise's `settings.url_replacements`. In isolated/mirrored networks this breaks
`mise install` of aqua cosign-verified tools (e.g. `cosign`).

Route the TUF root fetch through the same mirror: the bridge computes the
url-replaced TUF URL and pushes it into mise-sigstore via a process-global
override, set before every TUF-fetching entry point (cosign, SLSA, attestation).
The override still bootstraps from the embedded production root
(`PRODUCTION_TUF_ROOT`), so a mirror cannot forge the chain of trust. With no
replacement configured the behavior is unchanged.

Resolves jdx#10437

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@JamBalaya56562
JamBalaya56562 force-pushed the fix-sigstore-tuf-url-replacements branch from 6146bfc to ac33273 Compare June 24, 2026 04:05
@JamBalaya56562
JamBalaya56562 marked this pull request as ready for review June 24, 2026 04:12
@jdx
jdx merged commit b0de95f into jdx:main Jun 24, 2026
33 checks passed
@JamBalaya56562
JamBalaya56562 deleted the fix-sigstore-tuf-url-replacements branch June 25, 2026 00:21
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.

2 participants