stalwartlabs/stalwart · critical

Failed to load the platform certificate verifier

Error message

Failed to load the platform certificate verifier

What it means

This panic comes from an .expect() while constructing rustls_platform_verifier::Verifier::new() inside the SHARED_TLS_CONFIGS LazyLock in crates/utils/src/http.rs:72-73. The platform verifier relies on the OS certificate store via rustls-platform-verifier, and fails when that platform verification backend cannot be initialized. Because it runs inside a LazyLock initializer, the panic aborts the process the first time a TLS client config is requested (or at init_shared_tls_configs()).

Source

Thrown at crates/utils/src/http.rs:73

    fn verify_tls13_signature(
        &self,
        _message: &[u8],
        _cert: &CertificateDer<'_>,
        _dss: &DigitallySignedStruct,
    ) -> Result<HandshakeSignatureValid, TlsError> {
        Ok(HandshakeSignatureValid::assertion())
    }

    fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
        self.0.signature_verification_algorithms.supported_schemes()
    }
}

static SHARED_TLS_CONFIGS: LazyLock<SharedTlsConfigs> = LazyLock::new(|| {
    let provider = Arc::new(aws_lc_rs::default_provider());

    let verifier = rustls_platform_verifier::Verifier::new(provider.clone())
        .expect("Failed to load the platform certificate verifier");

    let mut strict = ClientConfig::builder_with_provider(provider.clone())
        .with_safe_default_protocol_versions()
        .expect("Failed to build the TLS client configuration")
        .dangerous()
        .with_custom_certificate_verifier(Arc::new(verifier))
        .with_no_client_auth();
    strict.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];

    let mut insecure = ClientConfig::builder_with_provider(provider.clone())
        .with_safe_default_protocol_versions()
        .expect("Failed to build the TLS client configuration")
        .dangerous()
        .with_custom_certificate_verifier(Arc::new(NoCertificateVerification(provider)))
        .with_no_client_auth();
    insecure.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];

    let mut strict_http1 = strict.clone();

View on GitHub (pinned to e962003857)

Solutions

  1. Install/repair the OS trust store and platform verifier support in the runtime environment (e.g. apt-get install -y ca-certificates on Debian/Ubuntu, apk add ca-certificates on Alpine)
  2. Initialize the shared TLS config explicitly early in main via init_shared_tls_configs() so the failure surfaces at startup with a clear message rather than lazily mid-request
  3. If the platform is unsupported, fall back to a rustls WebPkiServerVerifier / webpki-roots-based ClientConfig instead of the platform verifier
  4. Check the binary targets a supported OS/arch and that the rustls-platform-verifier crate version supports the target platform

Example fix

// before
let verifier = rustls_platform_verifier::Verifier::new(provider.clone())
    .expect("Failed to load the platform certificate verifier");
// after
let verifier = match rustls_platform_verifier::Verifier::new(provider.clone()) {
    Ok(v) => v,
    Err(e) => {
        log::warn!("platform verifier unavailable ({e}); using webpki roots fallback");
        build_webpki_fallback_verifier(provider.clone())
    }
};
Defensive patterns

Strategy: fallback

Validate before calling

// probe once at startup:
fn platform_verifier_ok() -> bool {
    rustls_platform_verifier::Verifier::new(Arc::new(aws_lc_rs::default_provider())).is_ok()
}

Try / catch

// Rust panics are not try/catch-able normally; force the LazyLock at startup
// and use catch_unwind plus a webpki-roots fallback config when needed:
let ok = std::panic::catch_unwind(init_shared_tls_configs).is_ok();
let config = if ok { shared_tls_config(false) } else { fallback_webpki_roots_config() };

Prevention

When it happens

Trigger: Calling init_shared_tls_configs() or shared_tls_config() (which forces the LazyLock) on a system where rustls_platform_verifier::Verifier::new() cannot load the OS trust store / verifier backend, e.g. minimal Docker images lacking platform verifier support, unsupported OS targets, or a broken system certificate service.

Common situations: Running in scratch/alpine/musl Docker images without ca-certificates or the platform verifier proxy; cross-compiled binaries on an OS the crate does not support; hardened/sandboxed environments (no DBus on Linux, restricted macOS Security.framework); tests in minimal CI containers.

Understand the failure class

Related errors


AI-assisted analysis of stalwartlabs/stalwart@e962003857 (2026-09-06). Data as JSON: /api/errors/53dd7bfbc17f2fe2. Report an issue: GitHub.