HexBrain

curl · Report #3969368

CVE-2026-80231: native CA store conn reuse

Validstatus
lowseverity
5upvotes
3 Sept 2026disclosed

How it was found

Summary

native_ca_store is in struct ssl_config_data (line 73 of vtls_config.h), not ssl_primary_config. match_ssl_primary_config() does not compare it. On macOS, Curl_ssl_easy_config_complete() (line 258) auto-sets native_ca_store = TRUE when no custom CA is configured — without modifying ssl_options. When CURL_CA_BUNDLE is defined, the auto-fill gives both transfers the same primary.CAfile, making all primary config fields match while native_ca_store differs.

Transfer A (explicit CURLOPT_CAINFO = CURL_CA_BUNDLE path): custom_cafile=TRUE, auto-setting prevented, native_ca_store=FALSE — OpenSSL-only verification.

Transfer B (no CURLOPT_CAINFO): auto-fill sets same CAfile, custom_cafile=FALSE, auto native_ca_store=TRUE — intended SecTrust verification.

match_ssl_primary_config sees matching CAfile + ssl_options → connection reused. B inherits A's connection without SecTrust ever running.

Reproduction

macOS baremetal (poc-native-ca.c), built with -DUSE_APPLE_SECTRUST=ON -DCURL_CA_BUNDLE=<path> -DCURL_USE_OPENSSL=ON:

  1. Transfer A: explicit CURLOPT_CAINFO = CURL_CA_BUNDLE path → OpenSSL verifies
  2. Transfer B: no CAINFO → auto-fill, auto native_ca_store=TRUE → should use SecTrust
  3. Observe: "Reusing existing https: connection" — SecTrust never runs

Root cause trace

  1. Curl_ssl_easy_config_complete() (line 258): !custom_capath && !custom_cafile && !custom_cablob → native_ca_store = TRUE. Does NOT modify ssl_options.
  2. CURL_CA_BUNDLE auto-fill (line 269): sets STRING_SSL_CAFILE → primary.CAfile = bundle path.
  3. Transfer A explicitly sets CURLOPT_CAINFO to the same path → custom_cafile=TRUE, auto-setting prevented, native_ca_store=FALSE. Same primary.CAfile, same ssl_options=0.
  4. match_ssl_primary_config matches all fields → connection reused. native_ca_store not compared.

Remediation

Move native_ca_store into ssl_primary_config so match_ssl_primary_config() compares it. Or add an explicit check in Curl_ssl_conn_config_match().

Impact

A transfer expecting SecTrust verification silently inherits an OpenSSL-only verified connection (or vice versa). Certificates trusted by one policy but not the other pass without re-verification.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original