Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions gems/mechanize/CVE-2026-107399.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
gem: mechanize
cve: 2026-107399
ghsa: c6rp-p8xm-4q9f
url: https://nvd.nist.gov/vuln/detail/CVE-2026-107399
title: Mechanize sends credential headers to another origin after
a meta refresh
date: 2026-10-08
description: |
## Summary

`mechanize` applied no trust boundary to a `meta` refresh, so credentials
set through `Mechanize#request_headers=` followed a refresh that
pointed at another origin.

## Details

`Mechanize::HTTP::Agent#response_follow_meta_refresh` fetched the refresh
target with no notion of a crossed origin, so `@request_headers` were
re-applied in full. An attacker who could place a `meta` refresh in a
page the agent fetched — through stored content, an open redirect, or
control of any page in the crawl — collected the same credentials as
through an HTTP redirect, on a code path that had none of the redirect
path's protections.

The refresh fetch passes an empty per-request headers hash, so only
headers set through `Mechanize#request_headers=` were exposed.

This requires `Mechanize#follow_meta_refresh = true`. It is `false`
by default, so an agent in its default configuration is not affected.
Crawlers commonly enable it.

## Impact

An attacker who can place a `meta` refresh in any page the agent fetches
captures bearer tokens and session cookies set through `request_headers=`.
Disclosure only; no integrity or availability impact.
cvss_v3: 6.8
patched_versions:
- ">= 2.14.1"
related:
url:
- https://nvd.nist.gov/vuln/detail/CVE-2026-107399
- 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/84c74df87d15f5d119df268ba6aa79bc1e16a2c3
- https://advisories.gitlab.com/gem/mechanize/CVE-2026-107399
- https://github.com/sparklemotion/mechanize/security/advisories/GHSA-c6rp-p8xm-4q9f
- https://github.com/advisories/GHSA-c6rp-p8xm-4q9f
notes: |
- cvss_v3 from GHSA and nvd.nist.gov URLs.
70 changes: 70 additions & 0 deletions gems/mechanize/CVE-2026-107715.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
gem: mechanize
cve: 2026-107715
ghsa: 2mwr-xjcg-37j7
url: https://nvd.nist.gov/vuln/detail/CVE-2026-107715
title: Mechanize sends credential headers to another host after
an HTTP redirect
date: 2026-10-08
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.
cvss_v3: 6.8
patched_versions:
- ">= 2.14.1"
related:
url:
- 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
notes: |
- cvss_v3 from GHSA and nvd.nist.gov URLs.
Loading