Description
## Summary:
A security feature bypass exists in `libcurl` when built with the **wolfSSL** backend and **HTTP/3** support. The Certificate Pinning feature (`--pinnedpubkey`) is silently ignored if the user also disables peer verification `-k` or `--insecure `) . This behavior is inconsistent with other backends (like OpenSSL) and exposes connections to Man-in-the-Middle attacks.
## Affected version
Reproduced on `curl 8.8.0-DEV` .
```text
docker run --rm smbd/curl-http3-wolfssl:5.7.0 curl -V
curl 8.8.0-DEV (x86_64-pc-linux-gnu) libcurl/8.8.0-DEV wolfSSL/5.7.0 zlib/1.2.13 nghttp2/1.52.0 ngtcp2/1.5.0 nghttp3/1.3.0
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns mqtt pop3 pop3s rtsp smtp smtps telnet tftp
Features: alt-svc AsynchDNS HSTS HTTP2 HTTP3 IPv6 Largefile libz SSL threadsafe UnixSockets
```
## Steps To Reproduce:
We compare the behavior of a standard build (OpenSSL) versus the vulnerable build (wolfSSL) using a **bogus** pinned hash (`AAAA...`) against a valid server (`google.com`).
1. **Control Test (Standard OpenSSL ):**
Run: `curl -k --pinnedpubkey "sha256//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" https://www.google.com/`
**Result:** `curl: (90) SSL: public key does not match pinned public key`
2. **Exploit Test (Vulnerable wolfSSL + HTTP/3 build):**
Run the same command using the vulnerable environment (reproduced here via Docker `smbd/curl-http3-wolfssl:5.7.0`) :
`docker run --rm smbd/curl-http3-wolfssl:5.7.0 curl -v --http3 -k --pinnedpubkey "sha256//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" https://www.google.com/`
**Result:** ` docker run --rm smbd/curl-http3-wolfssl:5.7.0 curl -v --http3 -k --pinnedpubkey "sha256//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" https://www.google.com/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Host www.google.com:443 was resolved.
* IPv6: 2800:3f0:4001:83c::2004
* IPv4: 172.217.30.68
* Trying 172.217.30.68:443...
* Trying [2800:3f0:4001:83c::2004]:443...
* Immediate connect fail for 2800:3f0:4001:83c::2004: Network is unreachable
* Trying 172.217.30.68:443...
* Connected to www.google.com (172.217.30.68) port 443
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* ALPN: curl offers h2,http/1.1
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to www.google.com (172.217.30.68) port 443
* using HTTP/3
* [HTTP/3] [0] OPENED stream for https://www.google.com/
* [HTTP/3] [0] [:method: GET]
* [HTTP/3] [0] [:scheme: https]
* [HTTP/3] [0] [:authority: www.google.com]
* [HTTP/3] [0] [:path: /]
* [HTTP/3] [0] [user-agent: curl/8.8.0-DEV]
* [HTTP/3] [0] [accept: */*]
> GET / HTTP/3
> Host: www.google.com
> User-Agent: curl/8.8.0-DEV
> Accept: */*
>
* Request completely sent off
< HTTP/3 200
< date: Tue, 16 Dec 2025 16:44:58 GMT
< expires: -1
< cache-control: private, max-age=0
< content-type: text/html; charset=ISO-8859-1
< content-security-policy-report-only: object-src 'none';base-uri 'self';script-src 'nonce-zhAjavKpmSo8XJCkxA_NgQ' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp
< accept-ch: Sec-CH-Prefers-Color-Scheme
< p3p: CP="This is not a P3P policy! See g.co/p3phelp for more info."
< server: gws
< x-xss-protection: 0
< x-frame-options: SAMEORIGIN
< set-cookie: __Secure-STRP=AD6DoguQyJNF6fdQjWRffsBqL5E7sCEdu2diQU92k64Obdab6qaZZ_YrOXrt5mjSi_mZUvgnouZxGUgkqQQ0qUaPWIKNTV8dktGI; expires=Tue, 16-Dec-2025 16:49:58 GMT; path=/; domain=.google.com; Secure; SameSite=strict
< set-cookie: AEC=AaJma5sy9-_cBlJAKCzRhnuHw8Hi2jSxiSB0qdTwn8F7JAvuHTabjD7SuO4; expires=Sun, 14-Jun-2026 16:44:58 GMT; path=/; domain=.google.com; Secure; HttpOnly; SameSite=lax
< set-cookie: NID=527=UAu9nT29vQQ1b9IRZfHQWcggNUyZO7X6TTM2XOkZfaPi93mxevHPyD3CB1KhkeUivwLhDrFjkCOg1iVwpetsU5zpb7HuBvlYJxY0sFo_V2wH_u2IJ4IvB-pyvLSn4YsS-qeG5RWrGwQy1hEHoNLK-PByHY1YI_10N-Jred14vtoFNySz1nc0la5zEC8qWvqhVzf0davySmgyeGedns-JHN2ceE3i_Tdh; expires=Wed, 17-Jun-2026 16:44:58 GMT; path=/; domain=.google.com; HttpOnly
< set-cookie: __Secure-BUCKET=CN8C; expires=Sun, 14-Jun-2026 16:44:58 GMT; path=/; domain=.google.com; Secure; HttpOnly
< alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
< accept-ranges: none
< vary: Accept-Encoding
<
{ [104 bytes data]
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="fr-CM"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"><title>Google</title><script nonce="zhAjavKpmSo8XJCkxA_NgQ">(function(){var _g={kEI:'ioxBaZb1NrTU5OUPqOCEUQ',kEXPI:'0,203004,45,1101175,4,2,4,3030729,344796,270476,5262392,36811500,25228681,217550,30632,7033,2105,4600,6553,50098,14067,61059,28338,48236,28322,3,2749,7714,6975,7774,15974,2662,4719,27257,19845,9881,36458,20879,1018,4372,4532,1760,16179,2646,101,2,4,1,4434,12368,2305,5031,1472,2,13032,1382,4,1514,578,2777,195,572,2869,2374,2,4205,5,1789,17,8476,1430,4384,2,876,2229,5089,19,3007,14,782,20847,2407,12338,1031,1034,1197,3106,845,2047,1,1,7,437,1128,3,2842,9,27,8,3055,1012,1745,4,3510,3,11680,4,2170,73,241,296,5,1113,389,4,298,901,1448,5,4819,15,734,298,4309,2806,2138,1275,7,1786,1048,2,2434,690,741,988,1084,3780,4,93,2561,2,5375,4,343,7,606,67,1582,4,1882,6,2,2,2,680,812,745,3310,483,746,5,465,793,1,2,1033,22,323,3,1359,3,2140,3,2788,49,10,215,441 .........................................`
**Root Cause Analysis:**
The issue is located in `lib/vquic/vquic-tls.c`. The logic that triggers the pinning check (`Curl_wssl_verify_pinned`) appears to be conditionally skipped or improperly handled when the primary verification (`verifyhost`) is disabled via configuration. Unlike the OpenSSL implementation, the wolfSSL wrapper for QUIC does not treat Pinning as an independent check.
## Impact
This vulnerability allows a Man-in-the-Middle (MitM) attacker to intercept and decrypt traffic, even when the user has explicitly configured Certificate Pinning to prevent such attacks.
A security feature bypass exists in `libcurl` when built with the **wolfSSL** backend and **HTTP/3** support. The Certificate Pinning feature (`--pinnedpubkey`) is silently ignored if the user also disables peer verification `-k` or `--insecure `) . This behavior is inconsistent with other backends (like OpenSSL) and exposes connections to Man-in-the-Middle attacks.
## Affected version
Reproduced on `curl 8.8.0-DEV` .
```text
docker run --rm smbd/curl-http3-wolfssl:5.7.0 curl -V
curl 8.8.0-DEV (x86_64-pc-linux-gnu) libcurl/8.8.0-DEV wolfSSL/5.7.0 zlib/1.2.13 nghttp2/1.52.0 ngtcp2/1.5.0 nghttp3/1.3.0
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns mqtt pop3 pop3s rtsp smtp smtps telnet tftp
Features: alt-svc AsynchDNS HSTS HTTP2 HTTP3 IPv6 Largefile libz SSL threadsafe UnixSockets
```
## Steps To Reproduce:
We compare the behavior of a standard build (OpenSSL) versus the vulnerable build (wolfSSL) using a **bogus** pinned hash (`AAAA...`) against a valid server (`google.com`).
1. **Control Test (Standard OpenSSL ):**
Run: `curl -k --pinnedpubkey "sha256//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" https://www.google.com/`
**Result:** `curl: (90) SSL: public key does not match pinned public key`
2. **Exploit Test (Vulnerable wolfSSL + HTTP/3 build):**
Run the same command using the vulnerable environment (reproduced here via Docker `smbd/curl-http3-wolfssl:5.7.0`) :
`docker run --rm smbd/curl-http3-wolfssl:5.7.0 curl -v --http3 -k --pinnedpubkey "sha256//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" https://www.google.com/`
**Result:** ` docker run --rm smbd/curl-http3-wolfssl:5.7.0 curl -v --http3 -k --pinnedpubkey "sha256//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" https://www.google.com/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Host www.google.com:443 was resolved.
* IPv6: 2800:3f0:4001:83c::2004
* IPv4: 172.217.30.68
* Trying 172.217.30.68:443...
* Trying [2800:3f0:4001:83c::2004]:443...
* Immediate connect fail for 2800:3f0:4001:83c::2004: Network is unreachable
* Trying 172.217.30.68:443...
* Connected to www.google.com (172.217.30.68) port 443
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* ALPN: curl offers h2,http/1.1
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to www.google.com (172.217.30.68) port 443
* using HTTP/3
* [HTTP/3] [0] OPENED stream for https://www.google.com/
* [HTTP/3] [0] [:method: GET]
* [HTTP/3] [0] [:scheme: https]
* [HTTP/3] [0] [:authority: www.google.com]
* [HTTP/3] [0] [:path: /]
* [HTTP/3] [0] [user-agent: curl/8.8.0-DEV]
* [HTTP/3] [0] [accept: */*]
> GET / HTTP/3
> Host: www.google.com
> User-Agent: curl/8.8.0-DEV
> Accept: */*
>
* Request completely sent off
< HTTP/3 200
< date: Tue, 16 Dec 2025 16:44:58 GMT
< expires: -1
< cache-control: private, max-age=0
< content-type: text/html; charset=ISO-8859-1
< content-security-policy-report-only: object-src 'none';base-uri 'self';script-src 'nonce-zhAjavKpmSo8XJCkxA_NgQ' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp
< accept-ch: Sec-CH-Prefers-Color-Scheme
< p3p: CP="This is not a P3P policy! See g.co/p3phelp for more info."
< server: gws
< x-xss-protection: 0
< x-frame-options: SAMEORIGIN
< set-cookie: __Secure-STRP=AD6DoguQyJNF6fdQjWRffsBqL5E7sCEdu2diQU92k64Obdab6qaZZ_YrOXrt5mjSi_mZUvgnouZxGUgkqQQ0qUaPWIKNTV8dktGI; expires=Tue, 16-Dec-2025 16:49:58 GMT; path=/; domain=.google.com; Secure; SameSite=strict
< set-cookie: AEC=AaJma5sy9-_cBlJAKCzRhnuHw8Hi2jSxiSB0qdTwn8F7JAvuHTabjD7SuO4; expires=Sun, 14-Jun-2026 16:44:58 GMT; path=/; domain=.google.com; Secure; HttpOnly; SameSite=lax
< set-cookie: NID=527=UAu9nT29vQQ1b9IRZfHQWcggNUyZO7X6TTM2XOkZfaPi93mxevHPyD3CB1KhkeUivwLhDrFjkCOg1iVwpetsU5zpb7HuBvlYJxY0sFo_V2wH_u2IJ4IvB-pyvLSn4YsS-qeG5RWrGwQy1hEHoNLK-PByHY1YI_10N-Jred14vtoFNySz1nc0la5zEC8qWvqhVzf0davySmgyeGedns-JHN2ceE3i_Tdh; expires=Wed, 17-Jun-2026 16:44:58 GMT; path=/; domain=.google.com; HttpOnly
< set-cookie: __Secure-BUCKET=CN8C; expires=Sun, 14-Jun-2026 16:44:58 GMT; path=/; domain=.google.com; Secure; HttpOnly
< alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
< accept-ranges: none
< vary: Accept-Encoding
<
{ [104 bytes data]
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="fr-CM"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"><title>Google</title><script nonce="zhAjavKpmSo8XJCkxA_NgQ">(function(){var _g={kEI:'ioxBaZb1NrTU5OUPqOCEUQ',kEXPI:'0,203004,45,1101175,4,2,4,3030729,344796,270476,5262392,36811500,25228681,217550,30632,7033,2105,4600,6553,50098,14067,61059,28338,48236,28322,3,2749,7714,6975,7774,15974,2662,4719,27257,19845,9881,36458,20879,1018,4372,4532,1760,16179,2646,101,2,4,1,4434,12368,2305,5031,1472,2,13032,1382,4,1514,578,2777,195,572,2869,2374,2,4205,5,1789,17,8476,1430,4384,2,876,2229,5089,19,3007,14,782,20847,2407,12338,1031,1034,1197,3106,845,2047,1,1,7,437,1128,3,2842,9,27,8,3055,1012,1745,4,3510,3,11680,4,2170,73,241,296,5,1113,389,4,298,901,1448,5,4819,15,734,298,4309,2806,2138,1275,7,1786,1048,2,2434,690,741,988,1084,3780,4,93,2561,2,5375,4,343,7,606,67,1582,4,1882,6,2,2,2,680,812,745,3310,483,746,5,465,793,1,2,1033,22,323,3,1359,3,2140,3,2788,49,10,215,441 .........................................`
**Root Cause Analysis:**
The issue is located in `lib/vquic/vquic-tls.c`. The logic that triggers the pinning check (`Curl_wssl_verify_pinned`) appears to be conditionally skipped or improperly handled when the primary verification (`verifyhost`) is disabled via configuration. Unlike the OpenSSL implementation, the wolfSSL wrapper for QUIC does not treat Pinning as an independent check.
## Impact
This vulnerability allows a Man-in-the-Middle (MitM) attacker to intercept and decrypt traffic, even when the user has explicitly configured Certificate Pinning to prevent such attacks.
Basic Information
ID
H1:3468098
Published
Dec 16, 2025 at 20:31
Modified
Dec 17, 2025 at 13:21