HACKERONE

curl: Secure cookies leaked to HTTP origins through HTTPS forwarding proxy_H1:3803415

Description

## Summary:
When curl accesses an `http://` origin through an HTTPS forwarding proxy, it sends Secure cookies in the request. The cookies travel in cleartext between the proxy and the origin server, visible to the proxy operator and anyone on that network path. curl also reports `CURLINFO_SCHEME` as `"https"` to the application for what is an `http://` transfer, which can mislead application-level security logic.

This is a regression introduced on 2026-06-12 in [commit 73daec6](https://github.com/curl/curl/commit/73daec6620bf9983df89e8df3660bfa3b8fd501d) ([PR #21967](https://github.com/curl/curl/pull/21967)). [proxy.c:652](https://github.com/curl/curl/blob/bb837dd/lib/proxy.c#L652) sets `conn->scheme` to the proxy's HTTPS scheme. `Curl_secure_context()` ([cookie.c:1273](https://github.com/curl/curl/blob/bb837dd/lib/cookie.c#L1273)) checks `conn->scheme->protocol & CURLPROTO_HTTPS` and returns TRUE, so Secure cookies are included. Before this commit, `conn->scheme` held the origin's scheme and Secure cookies were correctly withheld.

The same `conn->scheme` change causes [url.c:2505](https://github.com/curl/curl/blob/bb837dd/lib/url.c#L2505) to report `CURLINFO_SCHEME` as `"https"` for an `http://` origin.

## Affected version
```
$ curl --version
curl 8.21.0-DEV (Linux) libcurl/8.21.0-DEV OpenSSL/3.0.20 zlib/1.2.13 brotli/1.0.9 zstd/1.5.4 libpsl/0.21.2 nghttp2/1.52.0
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns mqtt mqtts pop3 pop3s rtsp smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS brotli HSTS HTTP2 HTTPS-proxy IPv6 Largefile libz PSL SSL threadsafe TLS-SRP UnixSockets zstd
```

Only affected since commit [73daec6](https://github.com/curl/curl/commit/73daec6620bf9983df89e8df3660bfa3b8fd501d) (2026-06-12). No released version is affected. Still present on origin/master at [79a2416](https://github.com/curl/curl/commit/79a24161ab) as of 2026-06-15.

## Steps To Reproduce:

A self-contained Dockerfile and patch (`fix.patch`) are attached. The Dockerfile builds three curl binaries from source: pre-regression (`c951368`), regression (`bb837dd`), and regression with the suggested fix applied. It also runs a Squid HTTPS forwarding proxy and a plain HTTP origin server that logs received cookies.

```bash
docker build -t cookie-proxy .
docker run --rm -it cookie-proxy
```

Inside the container, test each binary:

```bash
curl-safe -sv -x https://127.0.0.1:8443 --proxy-insecure -b /tmp/cookies.txt http://test.example:8080/path
curl-vuln -sv -x https://127.0.0.1:8443 --proxy-insecure -b /tmp/cookies.txt http://test.example:8080/path
curl-fixed -sv -x https://127.0.0.1:8443 --proxy-insecure -b /tmp/cookies.txt http://test.example:8080/path
```

Check what the origin received:

```bash
tail /tmp/origin.log
```

`curl-vuln` leaks the Secure cookie (the verbose output includes a `Cookie:` header, and the origin log confirms receipt). `curl-safe` and `curl-fixed` withhold it (no `Cookie:` header, origin log shows `RECEIVED no Cookie header`).

## Suggested fix

A patch is attached (`fix.patch`). `Curl_secure_context()` should check `data->state.origin->scheme` instead of `conn->scheme`. The refactor already migrated most security checks to `data->state.origin` but missed this function. The `conn->scheme` assignment at [proxy.c:652](https://github.com/curl/curl/blob/bb837dd/lib/proxy.c#L652) is still needed for SSL filter setup, so it should stay, but `Curl_secure_context()` should not read it. `Curl_xfer_is_secure()` is not affected because it has an additional `Curl_conn_is_ssl()` check that correctly excludes proxy SSL filters ([cfilters.c:693](https://github.com/curl/curl/blob/bb837dd/lib/cfilters.c#L693)).

## Impact

Secure cookies (session tokens, auth cookies, CSRF tokens) are sent in cleartext over the HTTP connection between the HTTPS proxy and the origin server. Anyone who can observe that network path can read them. The proxy operator can harvest them regardless. The `CURLINFO_SCHEME` misreporting can also trick application-level security checks (e.g. "only allow this action over HTTPS") into treating an insecure transfer as secure.

The bug affects all HTTP methods (GET, HEAD, POST, PUT, DELETE, PATCH, etc.) because the Secure context check runs in `Curl_cookie_getlist` ([cookie.c:1300](https://github.com/curl/curl/blob/bb837dd/lib/cookie.c#L1300)), which is called from the request header construction path for every method. WebSocket upgrade requests (`ws://` through the proxy) are also affected. Any libcurl application using the cookie engine (`CURLOPT_COOKIEFILE` / `CURLOPT_COOKIEJAR`) through an HTTPS proxy is affected, not just the curl CLI.

RFC violated: [RFC 6265](https://datatracker.ietf.org/doc/html/rfc6265#section-5.4) Section 5.4 step 3 ties "secure channel" to the `https` URI scheme ([RFC 7230](https://datatracker.ietf.org/doc/html/rfc7230#section-2.7.2) Section 2.7.2). The request uses `http://`, so Secure cookies must not be sent regardless of the TLS transport to the proxy.
Visit Original Source

Basic Information

ID H1:3803415
Published Jun 15, 2026 at 11:37
Modified Jun 15, 2026 at 13:48

💭 Join the Security Discussion

🔒 Your email address will not be published. Required fields are marked *

⚠️ Please be respectful and constructive in your comments. Security discussions should remain professional.