Reproducing DEBIAN-CVE-2026-94266 (curl effective-URL credential leak)
curl / libcurl
| Version type | Vulnerable | Fixed |
|---|---|---|
| Releases | 7.62.0 - 8.22.0 | 8.23.0 |
| Tested builds | 8.23.0-DEV | 8.23.1-DEV |
| Catalog | Fixed in fork | Fork branch | Merged |
|---|---|---|---|
| Severity | Low | Updated |
| Advisory | |
|---|---|
| Fixes | |
| Code | |
| Discussion |
Setup
curl exposes netrc credentials in CURLINFO_EFFECTIVE_URL after a relative redirect.
| Vulnerable | upstream at aad438d, reports 8.23.0-DEV |
|---|---|
| Fixed | our fork at ce57339, reports 8.23.1-DEV |
| Build | same flags both sides |
| Sandbox | no network, loopback only |
lib/url.c merges the netrc login into the URL handle. When Curl_http_follow re-parses a relative redirect into the same handle, stale userinfo remains in CURLINFO_EFFECTIVE_URL. Upstream fix 7a6bd027, included in the fork, strips the user and password in a new effective_url() before returning the value.
A loopback server answers /r1 with a 301 redirect to relative Location /r2. The client authenticates with a netrc file, follows the redirect, and prints %{url_effective}. If the value contains user:pass, the credentials leaked into the reported URL.
Reproduce (vulnerable build)
docker run --rm --network none --pids-limit 64 --memory 512m --read-only --tmpfs /tmp:rw,noexec,nosuid,size=64m cve-94266-demo python3 /task/repro.py /opt/tree-vuln/bin/curl$ LD_LIBRARY_PATH=/opt/tree-vuln/lib /opt/tree-vuln/bin/curl --version | head -1
curl 8.23.0-DEV (x86_64-pc-linux-gnu) libcurl/8.23.0-DEV OpenSSL/3.5.7
$ LD_LIBRARY_PATH=/opt/tree-vuln/lib /opt/tree-vuln/bin/curl --netrc-optional --netrc-file /tmp/netrc94266 -L --max-time 20 -w EFFECTIVE_URL=%{url_effective}
-o /dev/null http://127.0.0.1:8000/r1
EFFECTIVE_URL=http://netrcuser:netrcSECRET123@127.0.0.1:8000/r2
req1: Basic bmV0cmN1c2VyOm5ldHJjU0VDUk...
req2: Basic bmV0cmN1c2VyOm5ldHJjU0VDUk...Regression test 5032 shows credentials in the effective URL.
docker run --rm --network none --pids-limit 64 --memory 1g cve-94266-demo sh -c 'cp /src/fixed/tests/data/test5032 /src/vuln/tests/data/test5032 && cd /src/vuln && make -C tests/server >/tmp/srv.log 2>&1 && cd tests && perl runtests.pl 5032 2>&1 | tail -n 20'Warning: test5032 not present in tests/data/Makefile.am
test 5032 [CVE-2026-94266 effective URL has no netrc credentials after redirect]
5032: stdout FAILED:
@@ -1 +1 @@
-EFFECTIVE_URL=http://127.0.0.1:36705/50320002[LF]
+EFFECTIVE_URL=http://netrcuser:netrcSECRET123@127.0.0.1:36705/50320002[LF]
- abort tests
TESTDONE: 1 tests were considered during 1 seconds.
TESTDONE: 0 tests out of 1 reported OK: 0%
FAIL 5032: 'CVE-2026-94266 effective URL has no netrc credentials after redirect' netrc, CURLINFO_EFFECTIVE_URLVerify (fork-fixed build)
Run the same repro against the fork build.
docker run --rm --network none --pids-limit 64 --memory 512m --read-only --tmpfs /tmp:rw,noexec,nosuid,size=64m cve-94266-demo python3 /task/repro.py /opt/tree-fixed/bin/curl$ LD_LIBRARY_PATH=/opt/tree-fixed/lib /opt/tree-fixed/bin/curl --version | head -1
curl 8.23.1-DEV (x86_64-pc-linux-gnu) libcurl/8.23.1-DEV OpenSSL/3.5.7
$ LD_LIBRARY_PATH=/opt/tree-fixed/lib /opt/tree-fixed/bin/curl --netrc-optional --netrc-file /tmp/netrc94266 -L --max-time 20 -w EFFECTIVE_URL=%{url_effective}
-o /dev/null http://127.0.0.1:8000/r1
EFFECTIVE_URL=http://127.0.0.1:8000/r2
req1: Basic bmV0cmN1c2VyOm5ldHJjU0VDUk...
req2: Basic bmV0cmN1c2VyOm5ldHJjU0VDUk...The redirect still completes (exit 0, both requests authenticated). The effective URL no longer contains credentials.
The regression test passes on the fixed tree.
docker run --rm --network none --pids-limit 64 --memory 1g cve-94266-demo sh -c 'cd /src/fixed && make -C tests/server >/tmp/srv.log 2>&1 && cd tests && perl runtests.pl 5032 2>&1 | tail -n 6'test 5032 [CVE-2026-94266 effective URL has no netrc credentials after redirect]
s-p----e--- OK (1 out of 1 , remaining: 00:00, took 1.068s, duration: 00:01)
TESTDONE: 1 tests were considered during 1 seconds.
TESTDONE: 1 tests out of 1 reported OK: 100%Limits
Trigger is netrc credentials plus a redirect that merges into the base URL (a relative Location, as in upstream test 1876). An absolute Location with no userinfo resets the handle and stays clean even unfixed. Wire traffic is identical either way: both requests carry the normal Authorization header.
Attack flow
Agent runbook
docker run --rm --network none --pids-limit 64 --memory 512m --read-only --tmpfs /tmp:rw,noexec,nosuid,size=64m cve-94266-demo python3 /task/repro.py /opt/tree-vuln/bin/curl
docker run --rm --network none --pids-limit 64 --memory 1g cve-94266-demo sh -c 'cp /src/fixed/tests/data/test5032 /src/vuln/tests/data/test5032 && cd /src/vuln && make -C tests/server >/tmp/srv.log 2>&1 && cd tests && perl runtests.pl 5032 2>&1 | tail -n 20'
docker run --rm --network none --pids-limit 64 --memory 512m --read-only --tmpfs /tmp:rw,noexec,nosuid,size=64m cve-94266-demo python3 /task/repro.py /opt/tree-fixed/bin/curl
docker run --rm --network none --pids-limit 64 --memory 1g cve-94266-demo sh -c 'cd /src/fixed && make -C tests/server >/tmp/srv.log 2>&1 && cd tests && perl runtests.pl 5032 2>&1 | tail -n 6'Release information
| Source | Official advisory |
|---|---|
| Checked | |
| Severity | Low |
| Weakness | CWE-522 |
| Other fixed branches |
|
Recorded evidence
| upstream fix 7a6bd027 present in fork base | |
| regression test tests/data/test5032 executed RED then GREEN |
Status history
| Date | Status | Record |
|---|---|---|
| In progress | fix agent dispatched | |
| Fixed in fork | merged to fork master a33880b |