Skip to content

verify-ca without an explicit ssl_ca file silently falls back to platform trust (builtin errors instead) #46

Description

@aesslinger

Summary

build_tls_connector's verify-ca/verify-full handling only takes its dedicated cert-validation path when ssl_ca is actually set:

let needs_cert_validation = matches!(
    params.ssl_mode.as_deref(),
    Some("verify-ca" | "verify-full")
);

if needs_cert_validation {
    if let Some(ca_path) = user_ca {
        // ...VerifyCaCertVerifier / WebPkiServerVerifier branches...
    }
}

// falls through here when ssl_mode is verify-ca/verify-full but ssl_ca is unset
let builder = rustls::ClientConfig::builder()
    .with_platform_verifier()
    ...

So verify-ca with no ssl_ca file configured silently falls through to with_platform_verifier() — full OS-trust-store validation, no error.

Builtin's actual behavior (for reference)

src-tauri/src/pool_manager.rs's build_postgres_tls_connector, "verify-ca" branch:

"verify-ca" => {
    // Validate chain, skip hostname. Requires an explicit CA file —
    // platform roots are not used (macOS EKU check rejects them).
    let ca_path = user_ca.ok_or_else(|| {
        "verify-ca mode requires an explicit CA file via the connection's \
        CA Certificate field. On macOS, platform root certificates are \
        not compatible with strict EKU checks. For automatic platform \
        trust, use verify-full instead."
            .to_string()
    })?;
    ...
}

The builtin errors with a clear message if verify-ca has no CA file — it never falls back to platform trust for this mode. Only verify-full is designed to optionally use platform trust when no CA is given (that's the documented distinction between the two modes: use verify-full if you want automatic OS-trust-store validation).

Impact

A user who selects verify-ca but forgets (or doesn't realize they need) to also set ssl_ca silently gets verify-full-like behavior (platform-trust validation) instead of a clear error telling them what's missing. Not a security hole in the sense of accepting untrusted certs — platform trust is still some validation — but it's a behavioral divergence from the builtin and a worse user experience (silent substitution instead of actionable error).

Discovery context

Found while planning the fix for #44 (ssl_mode=require incorrectly validating against platform trust) — while tracing which ssl_mode/ssl_ca combinations currently reach the with_platform_verifier() fallback branch. Distinct from both #43 and #44: this is about verify-ca specifically missing its own CA-required guard, not about require's cert-validation logic or SslMode protocol enforcement. Confirmed structurally present in the current code as of main post-#45; not yet checked whether it predates recent PRs, but the code path itself (needs_cert_validation/user_ca structure) has existed since #40 at the latest.

Proposed fix

In build_tls_connector, when ssl_mode == Some("verify-ca") and user_ca is None, return an error matching the builtin's message (or an equivalent one specific to this plugin's "CA Certificate field" terminology), instead of falling through to the platform-verifier branch. verify-full without ssl_ca should continue to use the platform verifier — that part is already correct and matches the builtin.

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