no_proxy IDN mismatch: Unicode hostnames bypass proxy exclusion list

Disclosed: 2026-04-07 06:24:27 By mzfr To curl
Unknown
Vulnerability Details
## Summary Unicode (IDN) hostnames in `no_proxy` are never converted to punycode before comparison, so they never match the request hostname (which curl has already converted to punycode). A user who types `no_proxy="bücher.de"` and requests `http://bücher.de/` expects the proxy to be bypassed. Instead curl converts the URL to `xn--bcher-kva.de`, compares it raw against `bücher.de`, fails to match, and sends the request through the proxy. Same string typed by the user in both places, two different internal representations. This is the same class of bug as CVE-2022-42916 and CVE-2022-43551 (HSTS bypass via IDN confusion). ```bash LANG=C.UTF-8 http_proxy=http://127.0.0.1:18877 no_proxy="bücher.de" ./curl -v "http://bücher.de/" # Output: "Failed to connect to xn--bcher-kva.de port 80 via 127.0.0.1" # curl tried the proxy despite no_proxy matching the URL hostname ``` ## Affected version ``` curl 8.20.0-DEV (Darwin) libcurl/8.20.0-DEV OpenSSL/3.6.1 zlib/1.2.12 brotli/1.2.0 zstd/1.5.7 libidn2/2.3.8 nghttp2/1.68.0 Features: alt-svc AsynchDNS brotli HSTS HTTP2 HTTPS-proxy IDN IPv6 Largefile libz SSL threadsafe TLS-SRP UnixSockets zstd ``` - Git HEAD `38b626e790`. Also confirmed on 8.19.0 stable. Requires IDN support (libidn2). ## Steps To Reproduce 1. Start a listener: `nc -l 18877` 2. In another terminal: ```bash LANG=C.UTF-8 \ http_proxy=http://127.0.0.1:18877 \ no_proxy="bücher.de" \ ./curl -v "http://bücher.de/" ``` 3. The netcat listener receives the request. Verbose output shows: ``` * Uses proxy env variable no_proxy == 'bücher.de' * Uses proxy env variable http_proxy == 'http://127.0.0.1:18877' * Trying 127.0.0.1:18877... * Failed to connect to xn--bcher-kva.de port 80 via 127.0.0.1 ``` The request should go direct (bypassing the proxy) because `bücher.de` is in `no_proxy`. Instead curl converts the URL hostname to punycode (`xn--bcher-kva.de`) before calling `Curl_check_noproxy()` at `lib/noproxy.c:188`, but never converts the `no_proxy` entries. `match_host()` at line 124 compares raw `bücher.de` against `xn--bcher-kva.de` and fails. ## Impact Traffic the user explicitly excluded from the proxy via `no_proxy` is sent through the proxy, leaking request URLs, headers, and bodies to the proxy operator
Actions
View on HackerOne
Report Stats
  • Report ID: 3650443
  • State: Closed
  • Substate: informative
Share this report