|
| 1 | +--- |
| 2 | +gem: mechanize |
| 3 | +cve: 2026-107715 |
| 4 | +ghsa: 2mwr-xjcg-37j7 |
| 5 | +url: https://nvd.nist.gov/vuln/detail/CVE-2026-107715 |
| 6 | +title: Mechanize sends credential headers to another host after |
| 7 | + an HTTP redirect |
| 8 | +date: 2026-10-08 |
| 9 | +description: | |
| 10 | + ## Summary |
| 11 | +
|
| 12 | + `mechanize` leaked credentials to the redirect target when an HTTP |
| 13 | + redirect crossed to another host. Credentials set through |
| 14 | + `Mechanize#request_headers=` leaked even when they were `Authorization`. |
| 15 | +
|
| 16 | + ## Details |
| 17 | +
|
| 18 | + Two defects, both in `lib/mechanize/http/agent.rb`. |
| 19 | +
|
| 20 | + **1. `Mechanize#request_headers=` bypassed the redirect strip entirely.** |
| 21 | +
|
| 22 | + `#request_add_headers` copied `@request_headers` onto every request |
| 23 | + unconditionally, with no host check, including the request issued |
| 24 | + after a redirect. The strip in `#response_redirect` mutated only |
| 25 | + the per-request headers hash and never touched agent state. Because |
| 26 | + `request_headers=` is the documented way to set a default credential |
| 27 | + for every request, the header the code explicitly protected — |
| 28 | + `Authorization` — was the one most likely to leak. |
| 29 | +
|
| 30 | + **2. The strip list omitted `Proxy-Authorization` and `Cookie2`.** |
| 31 | +
|
| 32 | + Only `CREDENTIAL_HEADERS = ['Authorization']` and |
| 33 | + `COOKIE_HEADERS = ['Cookie']` were removed from the per-request |
| 34 | + headers hash on a cross-host redirect. |
| 35 | +
|
| 36 | + Cookies held in `Mechanize#cookie_jar` and credentials held in |
| 37 | + `Mechanize::HTTP::AuthStore` are **not** affected. Both are looked |
| 38 | + up per-URI, so they never follow a redirect to a foreign host. |
| 39 | + The exposure was limited to headers the caller set by hand. |
| 40 | +
|
| 41 | + ## Impact |
| 42 | +
|
| 43 | + An attacker who controls a redirect target — through an open redirect |
| 44 | + on the site being fetched, an attacker-supplied fetch URL, DNS rebinding, |
| 45 | + or MITM — captures bearer tokens and session cookies from any |
| 46 | + `mechanize` agent that sets credentials through `request_headers=` or |
| 47 | + the per-request `headers` argument. Disclosure only; no integrity or |
| 48 | + availability impact. |
| 49 | +
|
| 50 | + ## Credit |
| 51 | +
|
| 52 | + Reported by @SnailSploit. |
| 53 | +cvss_v3: 6.8 |
| 54 | +patched_versions: |
| 55 | + - ">= 2.14.1" |
| 56 | +related: |
| 57 | + url: |
| 58 | + - https://nvd.nist.gov/vuln/detail/CVE-2026-107715 |
| 59 | + - https://rubygems.org/gems/mechanize/versions/2.14.1 |
| 60 | + - https://github.com/sparklemotion/mechanize/releases/tag/v2.14.1 |
| 61 | + - https://github.com/sparklemotion/mechanize/blob/main/CHANGELOG.md#2141--2026-08-22 |
| 62 | + - https://github.com/sparklemotion/mechanize/pull/676 |
| 63 | + - https://github.com/sparklemotion/mechanize/commit/02a1235842d6eda8d4a5a3d8f13aba2cecf52e4f |
| 64 | + - https://github.com/sparklemotion/mechanize/commit/94e0902867296be804f36eccbb47acf7d5018745 |
| 65 | + - https://github.com/sparklemotion/mechanize/commit/ac49abf2869297d83c3b11bbfb8b18e63b588c95 |
| 66 | + - https://advisories.gitlab.com/gem/mechanize/CVE-2026-107715 |
| 67 | + - https://github.com/sparklemotion/mechanize/security/advisories/GHSA-2mwr-xjcg-37j7 |
| 68 | + - https://github.com/advisories/GHSA-2mwr-xjcg-37j7 |
| 69 | +notes: | |
| 70 | + - cvss_v3 from GHSA and nvd.nist.gov URLs. |
0 commit comments