Skip to content
HackerOne Bug Bounty Disclosure: tls-session-resumption-client-cert-bypass-with-curlopt-ssl-ctx-function-cipher-by-causal

HackerOne Bug Bounty Disclosure: tls-session-resumption-client-cert-bypass-with-curlopt-ssl-ctx-function-cipher-by-causal

Redpacketsecurity •admin • September 15, 2026

Report title TLS session resumption client cert bypass with CURLOPT_SSL_CTX_FUNCTION

Report link

Date submitted 2026-09-14T07:41:55.278Z

### What Was Reported

A researcher found that libcurl could reuse a TLS session created with a client certificate when a later request used the same easy handle without that certificate. In practical terms, a request intended to be anonymous could be authenticated to the server as the identity used by an earlier request.

### How the Issue Worked

The behavior involved `CURLOPT_SSL_CTX_FUNCTION`, a callback that allows applications to customize the TLS configuration. The callback can install a client certificate directly into the OpenSSL context. However, libcurl’s TLS session cache did not include the callback or the certificate it installed when calculating its cache key.

As a result, libcurl could treat two connections as equivalent even though one used a client certificate and the other did not. The second connection could resume the first TLS session and inherit its client identity.

### Why Connection-Reuse Options Did Not Help

The researcher tested both `CURLOPT_FORBID_REUSE` and `CURLOPT_FRESH_CONNECT`. These options caused libcurl to create a new network connection, but they did not prevent reuse of the cached TLS session. The server therefore observed a new TCP connection that resumed the TLS session.

This distinction is important: disabling connection reuse is not the same as disabling TLS session resumption.

### Demonstrated Impact

In the proof of concept, the first request installed a certificate identifying the client as `alice`. The callback was then removed before the second request. Despite this, the server saw the second request as coming from `alice`, and the TLS handshake reported that the session had been resumed.

When `CURLOPT_SSL_SESSIONID_CACHE` was disabled, the second request no longer inherited the certificate and appeared as having no client certificate. This confirmed that the TLS session cache—not the connection pool—was responsible.

### Who Could Be Affected

The problem required an application to reuse the same libcurl easy handle for requests to the same origin while switching between transfers that used and did not use `CURLOPT_SSL_CTX_FUNCTION`. This was considered an uncommon usage pattern by the curl security team.

Applications using client certificates through the regular `CURLOPT_SSLCERT` option were not the focus of this report. The issue specifically concerned certificates installed indirectly through the TLS context callback.

The curl security team concluded that this was primarily a documentation problem rather than a libcurl vulnerability. The report was therefore closed as **Informative**.

Curl updated the documentation to warn that TLS sessions are cached and that callback-installed sensitive TLS settings may not be applied again on subsequent transfers. The documentation now discourages using `CURLOPT_SSL_CTX_FUNCTION` to configure client certificates or other sensitive state without accounting for TLS session resumption.

### Recommended Mitigations

Applications that install client certificates or other identity-sensitive settings through `CURLOPT_SSL_CTX_FUNCTION` should avoid assuming that the callback will run for every transfer. They can disable TLS session caching with:

curl_easy_setopt(handle, CURLOPT_SSL_SESSIONID_CACHE, 0L);

Applications should also consider using separate easy handles for transfers with different client identities, or use libcurl options that are directly represented in its TLS configuration and session-cache logic.

`CURLOPT_FORBID_REUSE` and `CURLOPT_FRESH_CONNECT` only address reuse of existing connections. They do not necessarily prevent TLS session resumption on a newly created connection. When TLS client identity changes between requests, applications must explicitly manage session caching and handle separation.

A considerable amount of time and effort goes into maintaining this website, creating backend automation and creating new features and content for you to make actionable intelligence decisions. Everyone that supports the site helps enable new functionality.

If you like the site, please support us on Patreon or Buy Me A Coffee using the buttons below.

HackerOne report summary

Programme

Submitted by Cipher by Causal Security

Profile

Report title TLS session resumption client cert bypass with CURLOPT_SSL_CTX_FUNCTION

Report link

Date submitted 2026-09-14T07:41:55.278Z

### What Was Reported

A researcher found that libcurl could reuse a TLS session created with a client certificate when a later request used the same easy handle without that certificate. In practical terms, a request intended to be anonymous could be authenticated to the server as the identity used by an earlier request.

### How the Issue Worked

The behavior involved `CURLOPT_SSL_CTX_FUNCTION`, a callback that allows applications to customize the TLS configuration. The callback can install a client certificate directly into the OpenSSL context. However, libcurl’s TLS session cache did not include the callback or the certificate it installed when calculating its cache key.

As a result, libcurl could treat two connections as equivalent even though one used a client certificate and the other did not. The second connection could resume the first TLS session and inherit its client identity.

### Why Connection-Reuse Options Did Not Help

The researcher tested both `CURLOPT_FORBID_REUSE` and `CURLOPT_FRESH_CONNECT`. These options caused libcurl to create a new network connection, but they did not prevent reuse of the cached TLS session. The server therefore observed a new TCP connection that resumed the TLS session.

This distinction is important: disabling connection reuse is not the same as disabling TLS session resumption.

### Demonstrated Impact

In the proof of concept, the first request installed a certificate identifying the client as `alice`. The callback was then removed before the second request. Despite this, the server saw the second request as coming from `alice`, and the TLS handshake reported that the session had been resumed.

When `CURLOPT_SSL_SESSIONID_CACHE` was disabled, the second request no longer inherited the certificate and appeared as having no client certificate. This confirmed that the TLS session cache—not the connection pool—was responsible.

### Who Could Be Affected

The problem required an application to reuse the same libcurl easy handle for requests to the same origin while switching between transfers that used and did not use `CURLOPT_SSL_CTX_FUNCTION`. This was considered an uncommon usage pattern by the curl security team.

Applications using client certificates through the regular `CURLOPT_SSLCERT` option were not the focus of this report. The issue specifically concerned certificates installed indirectly through the TLS context callback.

The curl security team concluded that this was primarily a documentation problem rather than a libcurl vulnerability. The report was therefore closed as **Informative**.

Curl updated the documentation to warn that TLS sessions are cached and that callback-installed sensitive TLS settings may not be applied again on subsequent transfers. The documentation now discourages using `CURLOPT_SSL_CTX_FUNCTION` to configure client certificates or other sensitive state without accounting for TLS session resumption.

### Recommended Mitigations

Applications that install client certificates or other identity-sensitive settings through `CURLOPT_SSL_CTX_FUNCTION` should avoid assuming that the callback will run for every transfer. They can disable TLS session caching with:

curl_easy_setopt(handle, CURLOPT_SSL_SESSIONID_CACHE, 0L);

Applications should also consider using separate easy handles for transfers with different client identities, or use libcurl options that are directly represented in its TLS configuration and session-cache logic.

`CURLOPT_FORBID_REUSE` and `CURLOPT_FRESH_CONNECT` only address reuse of existing connections. They do not necessarily prevent TLS session resumption on a newly created connection. When TLS client identity changes between requests, applications must explicitly manage session caching and handle separation.

A considerable amount of time and effort goes into maintaining this website, creating backend automation and creating new features and content for you to make actionable intelligence decisions. Everyone that supports the site helps enable new functionality.

If you like the site, please support us on Patreon or Buy Me A Coffee using the buttons below.

Extracted Entities