Apr 14, 2026·6 min read·4 visits
The follow-redirects package leaks custom HTTP headers (such as X-API-Key) to third-party domains upon HTTP 302 redirects due to an incomplete header sanitization blacklist.
The `follow-redirects` Node.js library contains an information exposure vulnerability where sensitive custom authentication headers are leaked to cross-domain redirect targets. A hardcoded regex blacklist failed to remove non-standard headers during cross-origin redirects or protocol downgrades.
The follow-redirects library serves as a foundational HTTP client utility within the Node.js ecosystem, providing automatic redirect handling for standard HTTP requests. It is frequently utilized as a core dependency by high-level HTTP client frameworks, most notably axios. The library manages state transitions between HTTP 3xx responses, forwarding request bodies and headers to the newly specified destination.
GHSA-R4Q5-VMMM-2653 identifies a critical information exposure vulnerability (CWE-200) within this state transition logic. When processing a cross-origin redirect or a protocol downgrade (HTTPS to HTTP), the library actively evaluates the request headers to prevent the leakage of authentication materials. The sanitization mechanism relies on an explicit blacklist to strip specific sensitive headers before dispatching the subsequent request.
The vulnerability stems from the fact that this blacklist is restricted entirely to standard HTTP authentication mechanisms. Custom authentication headers, heavily relied upon in modern REST API architectures, are not recognized by the sanitization filter. Consequently, applications leveraging custom headers transmit their authentication tokens directly to untrusted third-party domains when instructed to do so by a malicious or compromised endpoint.
The root cause of this vulnerability lies in the header sanitization logic implemented within the RedirectableRequest class. During the request processing lifecycle, the _processResponse function evaluates the properties of the destination URL provided in the Location header. If the library detects a protocol downgrade or determines that the target host differs from the original host, it invokes a routine to strip sensitive context.
The core failing is the implementation of the removeMatchingHeaders function, which utilized a static, hardcoded regular expression: /^(?:(?:proxy-)?authorization|cookie)$/i. This regular expression explicitly targets exactly three HTTP headers: Authorization, Proxy-Authorization, and Cookie. Any header name that fails to match this precise pattern is systematically preserved and attached to the outbound redirect request.
Modern web services frequently eschew standard Authorization headers in favor of custom application-specific headers such as X-API-Key, X-Auth-Token, or Bearer-Token. Because the static blacklist implementation makes no provision for custom headers, the RedirectableRequest class treats these tokens as benign operational metadata. The sanitization phase is bypassed completely for these inputs, directly resulting in cross-domain credential exposure.
Commit 844c4d302ac963d29bdb5dc1754ec7df3d70d7f9 introduces a fundamental architectural shift in how follow-redirects manages header sanitization. The maintainers abandoned the static regular expression in favor of a dynamically compiled filter constructed during the instantiation of the RedirectableRequest object.
The patch introduces a sensitiveHeaders array within the request configuration options. The library establishes a baseline array of default sensitive headers (Authorization, Proxy-Authorization, Cookie) and concatenates it with the user-supplied array. This combined array is then mapped through a newly introduced escapeRegex utility function to safely sanitize the header names against injection attacks before compiling them into a final case-insensitive regular expression.
// Patched logic dynamically constructing the regex
var sensitiveHeaders = [
"Authorization",
"Proxy-Authorization",
"Cookie",
];
this._headerFilter = new RegExp("^(?:" +
sensitiveHeaders.concat(options.sensitiveHeaders || []).map(escapeRegex).join("|") +
")$", "i");The escapeRegex function is critical here. It prevents a scenario where an application dynamically passes untrusted strings into the sensitiveHeaders array, which could otherwise result in a Regular Expression Denial of Service (ReDoS) or logic bypass by altering the capture groups. By escaping special characters, the filter securely targets the exact header strings specified by the developer.
Exploitation of this vulnerability requires the attacker to control the HTTP response of an endpoint that the vulnerable application queries. The attacker configures the target server to return an HTTP 302 Found or 301 Moved Permanently status code, supplying an attacker-controlled server in the Location header. When the vulnerable Node.js application follows the redirect, the custom headers are attached to the new request, and the attacker captures the tokens from the incoming traffic.
The severity is amplified in applications that utilize transitive dependencies like axios. Because developers interact with the axios API rather than follow-redirects directly, they may be unaware that cross-origin redirection is occurring transparently. If axios is configured to send custom API keys globally, every redirect triggered by external data sources becomes a potential credential theft vector.
Furthermore, the patch implements a specific trust boundary bypass via the isSubdomain function check. The logic !isSubdomain(redirectUrl.host, currentHost) dictates that headers are entirely preserved if the redirect targets a subdomain of the original request. If an attacker manages to execute a subdomain takeover on the target infrastructure, they can direct traffic to the compromised subdomain and successfully capture the sensitive custom headers, bypassing the new configuration entirely.
The primary impact of this vulnerability is the loss of confidentiality for authentication tokens and API keys. Because these credentials frequently grant access to high-privilege external services (such as cloud provider APIs, payment gateways, or internal microservices), their exposure directly enables unauthorized access and subsequent data exfiltration or state mutation.
The vulnerability operates autonomously within the application backend. An attacker does not require direct network access to the vulnerable application itself; they only need the application to interact with an endpoint they control or can manipulate. This characterizes the attack vector as remote and requiring zero privileges on the affected host.
In microservice architectures, this flaw facilitates lateral movement. An application interacting with a seemingly benign internal service might be redirected to an external attacker-controlled node. The custom service-to-service authentication tokens are thereby leaked, providing the attacker with valid credentials to authenticate against other internal services bypassing external perimeter defenses.
Immediate remediation requires upgrading the follow-redirects library to version 1.15.6 or later. For applications relying on transitive dependencies, developers must utilize package manager resolution features (such as npm overrides or yarn resolutions) to force the dependency tree to adopt the patched version of follow-redirects.
Upgrading the package alone is insufficient for complete remediation if custom headers are in use. Developers must actively modify their HTTP client configurations to declare all custom authentication headers explicitly. The sensitiveHeaders array must be populated with every non-standard header utilized for authorization within the application's outbound requests.
As a defense-in-depth measure, developers should restrict the maximum number of allowed redirects and strictly validate the origin of redirect destinations where business logic permits. Disabling automatic redirect following entirely for highly sensitive API interactions guarantees that credentials will never depart the initially requested origin.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
follow-redirects follow-redirects maintainers | < 1.15.6 | 1.15.6 |
| Attribute | Detail |
|---|---|
| Vulnerability Type | Information Exposure (Sensitive Header Leak) |
| CWE ID | CWE-200 |
| CVSSv3 Score | 7.4 |
| Attack Vector | Network |
| Privileges Required | None |
| Affected Component | RedirectableRequest class |
| Exploit Status | Proof of Concept available |
Exposure of Sensitive Information to an Unauthorized Actor