GHSA-9857-6mw7-fq2m: gix-transport: HTTP credentials leaked to redirected host in curl backend
SummaryThe curl-based HTTP transport in `gix-transport` sends user credentials (passwords, tokens) to an attacker-controlled server after an HTTP redirect. When a server responds with a 302 redirect during the initial `GET /info/refs`, gitoxide records the redirected base URL and rewrites all subsequent requests to point at the redirected host. The `Authorization` header is still attached because `add_basic_auth_if_present()` only checks `self.url` (the original, never-updated URL).The reqwest backend is not affected. Its custom redirect policy at `reqwest/remote.rs` lines 60-64 compares `prev_url.host_str()` to `curr_url.host_str()` and calls `attempt.stop()` on cross-domain redirects, so `redirected_base_url` is never set to a different host.DetailsThe vulnerability involves two components in `gix-transport`:**1. URL rewriting after redirect** ([gix-transport/src/client/blocking_io/http/curl/remote.rs](https://github.com/GitoxideLabs/gitoxide/blob/main/gix-transport/src/client/blocking_io/http/curl/remote.rs))After a request completes, the effective URL is compared to the requested URL. If they differ (redirect occurred), the new base URL is stored (lines 355-359). On subsequent requests, `swap_tails()` rewrites the target URL to point at the redirected host (line 166).**2. Credential check uses original URL** ([gix-transport/src/client/blocking_io/http/mod.rs, lines 293-312](https://github.com/GitoxideLabs/gitoxide/blob/main/gix-transport/src/client/blocking_io/http/mod.rs#L293))`add_basic_auth_if_present()` checks `self.url` (set once during construction, never mutated) to decide whether to attach credentials. Since `self.url` always points to the original host, credentials are approved even when the actual request goes to the redirected (attacker) host.The `Authorization` header is added to the headers list in `handshake()` (line 374) and `request()` (line 434) before being passed to the backend, which applies them to the rewritten URL via `handle.http_headers(headers)` (line 309).Attack flow: cross-domain credential leakVictim clones `https://legitimate.com/repo` with credentials configuredServer returns 302 redirect on `GET /info/refs` to `https://attacker.com/...`Curl follows the redirect and strips `Authorization` for this GET (safe so far)Attacker serves a valid info/refs response; `redirected_base_url` is set`POST /git-upload-pack` is rewritten via `swap_tails()` to `attacker.com``add_basic_auth_if_present()` checks `self.url` (still `legitimate.com`), approves credential sending`Authorization: Basic <credentials>` is sent to `attacker.com`Curl's cross-domain header stripping only protects the redirected GET. It does not protect the POST, which is a new request with credentials re-attached by gitoxide.Secondary vector: HTTPS-to-HTTP downgradeThe cleartext protection at `mod.rs` line 300-305 also checks `self.url`:This only validates the original URL's scheme, not the effective URL after redirect. A redirect from `https://legitimate.com` to `http://attacker.com` bypasses this check, causing credentials to be sent in cleartext over HTTP.Victim clones `https://legitimate.com/repo` with credentialsServer redirects to `http://attacker.com/...` (note: HTTP, not HTTPS)`add_basic_auth_if_present()` checks `self.url` (still `https://`), allows credentials`Authorization` header is sent over unencrypted HTTP to `attacker.com`PoCA complete Rust project that reproduces the issue. It starts two local TCP servers (legitimate on :8080, attacker on :9090) and uses `gix-transport` to demonstrate the credential leak.**To run:** Create the project next to the gitoxide checkout so path dependencies resolve, then `cargo run`.**Output:**The GET (from redirect) has no `Authorization` header. The POST carries the full credentials. The base64 decodes to `victim-user:super-secret-token`.ImpactAny user who clones or fetches over HTTP(S) using gitoxide with the curl backend (`http-client-curl` feature) can have their credentials stolen by an attacker who controls a redirect target (via compromised server, DNS hijacking, or MITM). The only user interaction required is initiating the clone or fetch; the redirect and credential leak happen transparently. CI/CD pipelines using tokens are also at risk.Suggested FixOnly attach `Authorization` if the effective URL's host matches the original URL's host.Or block cross-origin redirects in the curl backend, matching reqwest's behavior.Check the effective URL's scheme (not the original) for the HTTPS-to-HTTP downgrade.
CVSS v3.1: 6.8