HexBrain

curl · Report #3973093

06: Incomplete fix for CVE-2026-7009: GCC/SecTrust builds silently discard stapled OCSP responses

Informativestatus
9upvotes
31 Aug 2026disclosed

How it was found

Summary

Curl_vtls_apple_verify() in lib/vtls/apple.c passes the stapled OCSP response to SecTrustSetOCSPResponse() only when both HAVE_BUILTIN_AVAILABLE and SUPPORTS_SecOCSP are defined. When HAVE_BUILTIN_AVAILABLE is absent, the OCSP buffer is silently discarded. GCC does not support __builtin_available, so the HAVE_BUILTIN_AVAILABLE feature test in CMakeLists.txt fails for every GCC build. The macOS CI workflow (.github/workflows/macos.yml) runs GCC+CMake jobs with -DUSE_APPLE_SECTRUST=ON, confirming this is a supported configuration.

The CVE-2026-7009 fix in ossl_apple_verify() (lib/vtls/openssl.c) rejects a missing staple when SSL_get_tlsext_status_ocsp_resp() returns a negative length. A positive length passes that check. When SecTrust accepts the certificate chain without seeing the OCSP data, sectrust_verified becomes true and Curl_ossl_check_peer_cert() skips OpenSSL's verifystatus(). A nonempty invalid OCSP response therefore satisfies --cert-status / CURLOPT_SSL_VERIFYSTATUS without being parsed, signature-verified, or checked for GOOD status.

Affected versions

Introduced in curl 8.17.0. The GCC/SecTrust variant remains in 8.20.0–8.21.0 and affected 8.22.0 prereleases/development snapshots.

Root cause

In lib/vtls/apple.c, lines 128 and 203:

#if defined(HAVE_BUILTIN_AVAILABLE) && defined(SUPPORTS_SecOCSP)

SUPPORTS_SecOCSP is defined on any macOS 10.9+ SDK (line 74), but the guard also requires HAVE_BUILTIN_AVAILABLE. Without it, the #else branch discards the OCSP buffer:

#else
  (void)ocsp_buf;
  (void)ocsp_len;
#endif

In lib/vtls/openssl.c, ossl_apple_verify() only sets ocsp_missing = TRUE for negative ocsp_len (line 4759). Positive-length data that was silently discarded by SecTrust is not flagged as missing. After Curl_vtls_apple_verify() returns success, sectrust_verified is set to TRUE (line 4776), and Curl_ossl_check_peer_cert() skips verifystatus() (line 4866).

Reproduction

  1. Use curl 8.20.0 or a later affected revision, such as 8.21.0, on macOS or in a test harness that can observe calls to the Apple Security framework.
  2. Build curl with an OpenSSL-based TLS backend and Apple SecTrust enabled, using GCC through CMake. Confirm that the configuration test does not define HAVE_BUILTIN_AVAILABLE.
  3. Confirm that the selected Apple SDK exposes SecTrustSetOCSPResponse() and therefore defines the SecTrust OCSP capability, while the GCC build still compiles out the call because HAVE_BUILTIN_AVAILABLE is absent.
  4. Prepare a TLS certificate and private key for a test hostname whose certificate chain will otherwise be accepted by SecTrust.
  5. Configure a TLS 1.2 test server to use that certificate and staple a nonempty invalid OCSP response. An OCSP response with an unauthorized, revoked, malformed, incorrectly signed, mismatched, or expired status can be used.
  6. Instrument or interpose the Apple Security framework sufficiently to record whether curl calls SecTrustSetOCSPResponse(). If deterministic testing is needed, make the trust evaluation accept the certificate when no OCSP response is supplied and reject it when the invalid response is supplied.
  7. Connect to the test server with the GCC-built curl, enable the native CA store, and require OCSP stapling with --cert-status or CURLOPT_SSL_VERIFYSTATUS.
  8. Verify that curl receives a positive-length stapled OCSP response but never passes it to SecTrustSetOCSPResponse().
  9. Observe the vulnerable result: SecTrust accepts the certificate chain, curl reports successful certificate verification, and the transfer succeeds even though OCSP status verification was explicitly required and the stapled response is invalid.
  10. Build a control configuration in which HAVE_BUILTIN_AVAILABLE is defined, using a compatible Clang compiler, and repeat the request. Verify that curl passes the OCSP response to SecTrust and that trust evaluation rejects it.
  11. As a second control, use the OpenSSL certificate-verification path instead of Apple SecTrust and repeat the request. Verify that OpenSSL parses the same response and rejects the transfer with CURLE_SSL_INVALIDCERTSTATUS.
  12. Confirm the fix by repeating the GCC/SecTrust case after changing curl to pass the response to SecTrustSetOCSPResponse() without the unavailable compiler builtin, or to fail closed when it cannot pass the response. The transfer must no longer succeed.

Expected result

When OCSP stapling verification is required, every received response must be validated by SecTrust or OpenSSL. An invalid response must terminate the connection.

Vulnerable result

In the affected GCC/SecTrust configuration, curl treats the presence of a nonempty response as sufficient, silently discards its contents, and accepts the connection without validating the response.

Suggested fix

Do not silently discard a required staple. Either call SecTrustSetOCSPResponse() without relying on __builtin_available when the deployment target guarantees the API (macOS >= 10.9), or fail CURLOPT_SSL_VERIFYSTATUS when a received OCSP response cannot be passed to SecTrust. A REQUIRES_SecOCSP path analogous to the existing REQUIRES_SecTrustEvaluateWithError pattern would close the gap for high deployment targets without affecting other configurations.

I leave severity and CVE classification to you. This may be best treated as an incomplete-fix variant of CVE-2026-7009 affecting versions currently declared fixed (8.20.0 and later).

Impact

Summary:

An attacker possessing a hostname-valid but revoked certificate and its private key could impersonate the target server despite the client explicitly requiring OCSP verification. This may enable man-in-the-middle interception, disclosure, or modification of TLS-protected traffic.

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