Oct 9, 2026·7 min read·5 visits
Mechanize prior to 2.14.1 fails to prevent caller-supplied global credentials from being transmitted to untrusted hosts during cross-origin HTTP redirections, exposing sensitive credentials to third parties.
Ruby Mechanize prior to version 2.14.1 contains an information disclosure vulnerability. When executing cross-origin HTTP redirects, global headers configured on the Mechanize agent (such as Authorization or Session Cookies) are dynamically re-applied to the subsequent request, bypassing the internal header-stripping logic. An attacker who controls a redirection endpoint can capture sensitive bearer tokens or cookies.
The Ruby Mechanize library, prior to version 2.14.1, contains an information disclosure vulnerability where caller-supplied credential headers are forwarded to external hosts following HTTP redirections. Mechanize is an automation and web-scraping framework designed to simulate browser behavior, handle session cookies, and manage state across multiple HTTP transactions. Because scraping agents often follow redirections automatically, the boundary between trusted origins and untrusted destinations must be strictly maintained.
The flaw exists within the redirection logic managed by the Mechanize::HTTP::Agent class. When a client application configures global headers or per-request credentials, these secrets are retained and re-applied to requests initiated during redirect chains. If a redirection points to a third-party domain, the agent fails to isolate these headers, transmitting sensitive data such as Authorization, Proxy-Authorization, Cookie, and Cookie2 headers to unverified external endpoints.
This behavior violates the basic principles of the Same-Origin Policy (SOP). It allows any intermediary or target server in a redirection chain to capture authorization tokens and session keys intended exclusively for the original server. The issue represents a critical flaw in applications that scrape user-submitted URLs or traverse untrusted web endpoints while maintaining authenticated sessions.
The technical root cause of this vulnerability lies in the structural separation of concerns between per-request state and persistent agent-level state in lib/mechanize/http/agent.rb. When a developer configures default headers using the Mechanize#request_headers= setter, these headers are saved to the instance variable @request_headers. During an initial request, these values are merged into the request payload.
Upon encountering an HTTP redirect (such as a 301, 302, or 307 status code), the library executes Mechanize::HTTP::Agent#response_redirect. This method contains sanitization logic that strips sensitive headers like Authorization and Cookie when the target URI differs from the current URI. However, this sanitization only mutates the temporary, per-request header dictionary passed as an argument. It does not alter the persistent @request_headers configuration on the agent instance.
When the agent attempts to fetch the target of the redirection, it initiates a new HTTP request and invokes #request_add_headers. This method iterates over the unmodified @request_headers hash and unconditionally re-applies all configurations back into the outgoing request. As a result, headers that were stripped during the redirect phase are silently re-inserted prior to transmission over the network.
Additionally, the blacklist used to identify sensitive headers in older versions was incomplete. It did not include standard headers like Proxy-Authorization or Cookie2. Furthermore, the library evaluated host matches solely by comparing hostname strings (new_uri.host == page.uri.host). This comparison ignored variations in port numbers and protocol schemes, allowing credential leaks to occur when downgrading from HTTPS to plaintext HTTP on the same host.
The following block demonstrates the vulnerable state restoration inside lib/mechanize/http/agent.rb before the security patch was applied. Note how @request_headers are read and written directly to the request object, rendering the stripping logic in #response_redirect ineffective.
# VULNERABLE: lib/mechanize/http/agent.rb
# In older versions, every fetch operation re-applied `@request_headers` from scratch.
def request_add_headers(request, headers = {})
# Global headers are unconditionally added to every single request,
# including intermediate redirect hops where they should have been stripped.
@request_headers.each do |k, v|
request[k] = v
end
headers.each do |k, v|
request[k] = v
end
endThe patch implemented in version 2.14.1 introduces a mechanism to control when global headers are merged. Instead of dynamically re-applying global state on every request execution, the library now merges @request_headers exactly once when a top-level request is initiated by the user. Subsequent hops in a redirect chain set apply_request_headers to false.
The following code block highlights the remediation implemented in the patched version. The origin comparison was also updated to conform with RFC 6454 rules, checking the protocol scheme, hostname, and port number to detect cross-origin boundaries accurately.
# PATCHED: lib/mechanize/http/agent.rb
# Global headers are merged only once at the beginning of the transaction.
def fetch(uri, method = :get, headers = {}, params = [], referer = nil,
redirect_ok = @redirect_ok, apply_request_headers = true)
# Merge global request headers only if this is the initial request
headers = merge_request_headers(headers) if apply_request_headers
# ... request processing and redirect logic
end
# The comparison is expanded to ensure scheme, host, and port are validated.
def crosses_origin?(from_uri, to_uri)
to_uri.scheme != from_uri.scheme ||
to_uri.host != from_uri.host ||
to_uri.port != from_uri.port
endBy ensuring that apply_request_headers is disabled for redirection loops and authentication retries, the updated library prevents the restoration of stripped credentials. The blacklisted headers list was also expanded to include Proxy-Authorization and Cookie2 in the constant lists.
Exploitation of this vulnerability requires that an attacker induce a Mechanize-based client to send an authenticated request to a domain under the attacker's control, or to a trusted site containing an open redirect vulnerability. In a typical scenario, a target application uses Mechanize to fetch and parse external content, passing a user-supplied URL as a parameter while carrying administrative or session tokens in the global headers.
If the attacker hosts a page that issues an HTTP 302 redirect pointing to their own server, Mechanize follows the redirect. Because of the bug in #request_add_headers, the original Authorization and Cookie headers are re-injected and sent directly to the attacker-controlled server. The attacker can log these headers to capture the authentication bearer tokens or session cookies.
This behavior also occurs through HTML <meta> refresh tags found in scraped pages. If Mechanize parses a page containing <meta http-equiv="refresh" content="0;url=http://attacker.com">, it triggers an internal redirect mechanism via #response_follow_meta_refresh. In vulnerable versions, this flow does not isolate the origin, causing the agent to include global authentication headers when querying the attacker's web page.
The security impact of this vulnerability is classified as Medium with a CVSS v3.1 base score of 6.8. The primary risk is the loss of confidentiality of highly sensitive session and authentication secrets. Because Mechanize is frequently used to scrape websites, access APIs, or perform automated testing, these leaked credentials often represent critical user accounts or API keys.
The CVSS vector breakdown (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N) highlights specific environmental factors. The attack vector is Network (AV:N), indicating that exploitation can occur over the internet. Attack Complexity is High (AC:H) because the attacker must find or control a redirection target that the Mechanize instance can be persuaded to fetch.
The Scope is Changed (S:C) because credentials belonging to one origin are transmitted to a different security domain. The impact is limited to Confidentiality (C:H) as the flaw allows reading the headers but does not directly modify data on the client or compromise system availability. However, the stolen credentials can subsequently be used to gain unauthorized access to target systems, escalating the total impact.
The most complete remediation is upgrading the Mechanize gem to version 2.14.1 or later. This release restructures the header lifecycles to ensure that global credentials are not persistently re-applied to redirect requests. Developers can update their dependency files to enforce this minimum version.
# Update Mechanize within the project environment
bundle update mechanizeIf immediate upgrading is not possible, developers should avoid using the global Mechanize#request_headers= setter to assign sensitive information like API tokens and authorization headers. Instead, credentials should be supplied dynamically as argument overrides for specific, targeted #get or #post requests. This pattern prevents the agent from storing the secrets in its long-lived state.
Alternatively, automatic redirection can be disabled by setting agent.redirect_ok = false. Under this configuration, the application must catch redirection responses manually, inspect the target location, and explicitly verify that the destination belongs to a trusted domain before executing a separate, sanitized request.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
mechanize Mechanize Project | < 2.14.1 | 2.14.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-200 |
| Attack Vector | Network (High Complexity) |
| CVSS v3.1 | 6.8 (Medium) |
| Exploit Status | Proof of Concept (PoC) available |
| CISA KEV Status | Not Listed |
| Remediation Status | Patched in v2.14.1 |
The product exposes sensitive information to an actor who is not authorized to have access to that information.
CVE-2026-107720 is a critical signature verification bypass vulnerability in NearForm's fast-jwt Node.js library. Under specific configurations where the token verifier is initialized with a falsy cryptographic key (such as an empty string or null) and a non-empty algorithms allowlist, the library erroneously skips signature validation. This allows unauthenticated remote attackers to submit fabricated, unsigned JSON Web Tokens and bypass the authorization boundary of the application entirely.
An origin trust boundary failure in the Ruby mechanize library (prior to v2.14.1) allows unauthenticated remote web servers to harvest sensitive global request headers, such as Authorization Bearer tokens and cookies, by utilizing HTML-level meta-refresh redirection tags. Standard HTTP-level redirect boundaries were not applied to document-level redirects, creating a vector for cross-origin credential leakage during automated crawls.
CVE-2026-107718 is a medium-severity Open Redirect vulnerability in the core HTTP server package of the AdonisJS Node.js framework. Prior to versions 8.2.3 and 9.3.0, the framework built route paths by directly interpolating dynamic parameters and wildcard segments without URI encoding. If an application routes attacker-controlled input directly to a dynamic first path segment and uses the generated route URL as a redirect destination, a leading slash can produce a scheme-relative external URL. Modern web browsers process scheme-relative URLs by redirecting the client to the specified external domain, exposing users to credential harvesting, social engineering, and session hijacking. This vulnerability affects all applications running unpatched configurations where input validation is not explicitly implemented before generating paths.
CVE-2026-107725 is a critical security bypass in Hazelcast where missing authorization checks in the MapPermission class permit unprivileged clients to issue queries containing aggregators or projections. This architectural oversight allows attackers to run arbitrary code on the cluster servers under the privileges of the active Hazelcast process.
A stored Cross-Site Scripting (XSS) vulnerability was identified in Indico, an open-source event management system developed at CERN, prior to version 3.3.13. The vulnerability stems from weak URL validation in custom link fields and lack of HTML sanitization during Marshmallow serialization of event notes. This allows authenticated attackers with event modification privileges to inject malicious payloads that execute in the browser of users viewing the event pages or collaborating on notes.
A technical analysis of CVE-2026-107397, a stored Cross-Site Scripting (XSS) vulnerability in Indico's collaborative notes editor and custom link generation fields. Prior to version 3.3.13, Marshmallow serialization schemas omitted HTML sanitization during conflict resolution, and form validators failed to enforce strict URI schemes, enabling authenticated low-privilege attackers to execute arbitrary JavaScript.