Skip to content

[audit] Enforce SPKI cert pinning — migrate keyless HTTP from ureq to rustls #95

@avrabe

Description

@avrabe

Follow-up from the 2026-04-30 14-perspective audit (summary in audit/2026-04-30/findings.md, finding C-4 / CRITICAL). Three independent reviewers (cryptographer, red-team, supply-chain engineer) converged on this same gap.

Background

Issue #12 added the SPKI pinning infrastructure (src/lib/src/signature/keyless/cert_pinning.rs), but the pins are not enforced at the TLS layer. ureq does not expose a ServerCertVerifier hook, so today:

  • Pins are computed and validated against the leaf cert post-handshake.
  • Mismatches are logged, not rejected.
  • Even WSC_REQUIRE_CERT_PINNING=1 only escalates the log level — the TLS handshake completes regardless.
  • An attacker with a valid WebPKI cert for fulcio.sigstore.dev (e.g. compromised CA, mis-issued cert) bypasses the defence entirely.

This is a silent posture downgrade vs the protection the SPKI infrastructure suggests is in place.

Scope

Replace ureq with an HTTP client that exposes a custom rustls::ServerCertVerifier, so pin validation can fail the handshake itself.

Likely candidate: reqwest with rustls-tls feature (or direct hyper-rustls for finer control). Touches every Sigstore call site:

  • src/lib/src/signature/keyless/signer.rs (Fulcio cert request)
  • src/lib/src/signature/keyless/rekor.rs / rekor_verifier.rs (Rekor entry submit + lookup)
  • src/lib/src/signature/keyless/oidc.rs (OIDC discovery, JWKS fetch)
  • src/lib/src/signature/keyless/cert_pinning.rs (becomes the verifier impl rather than a post-hoc validator)

Acceptance

  • HTTP client wrapping uses rustls' ServerCertVerifier interface.
  • Pin mismatch causes the TLS handshake to fail with a clear error, not a log line.
  • WSC_REQUIRE_CERT_PINNING=1 becomes redundant (pinning is the only mode); deprecate the env var.
  • Integration test: forged cert chain (correct WebPKI, wrong SPKI) → handshake fails, no body fetched.
  • CR-7 verification artifact (currently CV-6) updated with the new evidence.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions