Mechanize sends credential headers to another host after an HTTP redirect
Published: October 08, 2026
SECURITY IDENTIFIERS
- CVE: CVE-2026-107715 (NVD)
- GHSA: GHSA-2mwr-xjcg-37j7
GEM
SEVERITY
CVSS v3.x: 6.8 (Medium)
PATCHED VERSIONS
>= 2.14.1
DESCRIPTION
Summary
mechanize leaked credentials to the redirect target when an HTTP
redirect crossed to another host. Credentials set through
Mechanize#request_headers= leaked even when they were Authorization.
Details
Two defects, both in lib/mechanize/http/agent.rb.
1. Mechanize#request_headers= bypassed the redirect strip entirely.
#request_add_headers copied @request_headers onto every request
unconditionally, with no host check, including the request issued
after a redirect. The strip in #response_redirect mutated only
the per-request headers hash and never touched agent state. Because
request_headers= is the documented way to set a default credential
for every request, the header the code explicitly protected —
Authorization — was the one most likely to leak.
2. The strip list omitted Proxy-Authorization and Cookie2.
Only CREDENTIAL_HEADERS = ['Authorization'] and
COOKIE_HEADERS = ['Cookie'] were removed from the per-request
headers hash on a cross-host redirect.
Cookies held in Mechanize#cookie_jar and credentials held in
Mechanize::HTTP::AuthStore are not affected. Both are looked
up per-URI, so they never follow a redirect to a foreign host.
The exposure was limited to headers the caller set by hand.
Impact
An attacker who controls a redirect target — through an open redirect
on the site being fetched, an attacker-supplied fetch URL, DNS rebinding,
or MITM — captures bearer tokens and session cookies from any
mechanize agent that sets credentials through request_headers= or
the per-request headers argument. Disclosure only; no integrity or
availability impact.
Credit
Reported by @SnailSploit.
RELATED
- https://nvd.nist.gov/vuln/detail/CVE-2026-107715
- https://rubygems.org/gems/mechanize/versions/2.14.1
- https://github.com/sparklemotion/mechanize/releases/tag/v2.14.1
- https://github.com/sparklemotion/mechanize/blob/main/CHANGELOG.md#2141--2026-08-22
- https://github.com/sparklemotion/mechanize/pull/676
- https://github.com/sparklemotion/mechanize/commit/02a1235842d6eda8d4a5a3d8f13aba2cecf52e4f
- https://github.com/sparklemotion/mechanize/commit/94e0902867296be804f36eccbb47acf7d5018745
- https://github.com/sparklemotion/mechanize/commit/ac49abf2869297d83c3b11bbfb8b18e63b588c95
- https://advisories.gitlab.com/gem/mechanize/CVE-2026-107715
- https://github.com/sparklemotion/mechanize/security/advisories/GHSA-2mwr-xjcg-37j7
- https://github.com/advisories/GHSA-2mwr-xjcg-37j7
