curl · Report #3650443
no_proxy IDN mismatch: Unicode hostnames bypass proxy exclusion list
How it was found
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).
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
-
Start a listener:
nc -l 18877 -
In another terminal:
LANG=C.UTF-8 \
http_proxy=http://127.0.0.1:18877 \
no_proxy="bücher.de" \
./curl -v "http://bücher.de/"
- 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