CVE-2026-111755
follow-redirects sensitiveHeaders regex escaping can expose credential headers
follow-redirects is a Node.js HTTP and HTTPS client wrapper that automatically follows redirects. From 1.16.0 until 1.16.1, escapeRegex leaves valid header-name metacharacters unescaped in sensitiveHeaders. When an application declares a sensitive header whose name contains ^ or | and follows a cross-origin or HTTPS-to-HTTP redirect, unescaped regular-expression metacharacters prevent the generated filter from matching the declared header name, and the credential header is forwarded to an attacker-controlled redirect target. This issue is fixed in version 1.16.1.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
8.2
follow-redirects sensitiveHeaders regex escaping can expose credential headers
follow-redirects is a Node.js HTTP and HTTPS client wrapper that automatically follows redirects. From 1.16.0 until 1.16.1, escapeRegex leaves valid header-name metacharacters unescaped in sensitiveHeaders. When an application declares a sensitive header whose name contains ^ or | and follows a cross-origin or HTTPS-to-HTTP redirect, unescaped regular-expression metacharacters prevent the generated filter from matching the declared header name, and the credential header is forwarded to an attacker-controlled redirect target. This issue is fixed in version 1.16.1.
- Record
CVE-2026-111755- CVSS 4.0
- 8.2 High
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-185, CWE-200
- Updated
- 2026-11-02
EUVDEUVD-2026-104536
8.2
follow-redirects is a Node.js HTTP and HTTPS client wrapper that automatically follows redirects. From 1.16.0 until 1.16.1, escapeRegex leaves valid header-name metacharacters unescaped in sensitiveHeaders. When an application declares a sensitive header whose name contains ^ or | and follows a cross-origin or HTTPS-to-HTTP redirect, unescaped regular-expression metacharacters prevent the generated filter from matching the declared header name, and the credential header is forwarded to an attacker-controlled redirect target. This issue is fixed in version 1.16.1.
- Record
EUVD-2026-104536- CVSS 4.0
- 8.2 High
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-8r9p-f939-6h3c
8.2
follow-redirects sensitiveHeaders regex escaping can expose credential headers
Summary
follow-redirects 1.16.0 introduced the sensitiveHeaders option (the fix for CVE-2026-40895 / GHSA-r4q5-vmmm-2653), which lets an application declare extra header names that must be removed when a redirect crosses to a different host or downgrades protocol. The filter is a single case-insensitive regular expression built by concatenating the declared header names into an alternation after passing each through escapeRegex. escapeRegex escapes only a partial set of metacharacters and leaves ^, |, [, {, and } unescaped. Header names may legitimately contain ^ and | (both are valid RFC 9110 token characters that Node accepts and sends), and for a declared name containing either, the generated pattern can never match the intended header. As a result, an application that adopts this option to protect a custom credential header, then follows an attacker-controlled cross-origin redirect, forwards that credential to the attacker with no error or warning, while believing it is protected. The failure is silent: the protection simply does not exist for the affected names. The built-in list (Authorization, Proxy-Authorization, Cookie) contains no metacharacters and is not affected by this defect.
Details
The filter is constructed once, in the RedirectableRequest constructor at index.js:118-120:
this._headerFilter = new RegExp("^(?:" +
sensitiveHeaders.concat(options.sensitiveHeaders).map(escapeRegex).join("|") +
")$", "i");
escapeRegex at index.js:703-705:
function escapeRegex(regex) {
return regex.replace(/[\]\\/()*+?.$]/g, "\\$&"); // escapes ] \ / ( ) * + ? . $ -- NOT ^ | [ { }
}
The character class escapes ], \, /, (, ), *, +, ?, ., and $. It omits ^, |, [, {, and }. Of these, Node's http.ClientRequest accepts ^ and | in header names (they are valid tchar values under RFC 9110) and rejects [, {, } with ERR_INVALID_HTTP_TOKEN, so ^ and | are the reachable vectors for a silent credential leak. Separately, although [, {, } cannot appear as live header names, declaring a sensitiveHeaders entry that contains one of them injects an unbalanced token into the alternation (for example an unterminated character class), so the filter RegExp throws a SyntaxError in the RedirectableRequest constructor and the request fails to start. That case is a loud request-time crash from the same incomplete-escaping root cause rather than a silent bypass, and the canonical escaper below fixes it as well.
For a declared sensitive header name containing an unescaped metacharacter, the alternation is broken in a fail-open way:
- A name containing
^, for exampleX-Api^Key, yields the alternativeX-Api^Keyinside the pattern. The^becomes a mid-pattern start-of-string anchor, so the alternative can never match any real header name.test("X-Api^Key")returnsfalse, and the header is not stripped. - A name containing
|, for exampleX-Token|Secret, is split into two separate alternativesX-TokenandSecret. The real headerX-Token|Secretis never matched (not stripped), while unrelated headers literally namedX-TokenorSecretwould be stripped instead.
The generated filter source, reproduced from the exact library logic, is:
^(?:Authorization|Proxy-Authorization|Cookie|X-Api^Key|X-Token|Secret|X-Control-Key)$
Direct matching results against this filter: X-Api^Key -> false, X-Token|Secret -> false, X-Control-Key (normal name) -> true, and the split-off X-Token -> true and Secret -> true (collateral wrong-stripping). The built-ins Authorization, Proxy-Authorization, Cookie all -> true.
Secondary, related weakness (filter snapshot not refreshed after beforeRedirect): the filter is built once at construction and applied at index.js:490, which runs before the beforeRedirect(this._options, ...) hook and the subsequent _sanitizeOptions at index.js:494-506. Because the strip…
- Record
GHSA-8r9p-f939-6h3c- CVSS 4.0
- 8.2 High
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-185, CWE-200
- Updated
- 2026-11-02
NVD
8.2
follow-redirects is a Node.js HTTP and HTTPS client wrapper that automatically follows redirects. From 1.16.0 until 1.16.1, escapeRegex leaves valid header-name metacharacters unescaped in sensitiveHeaders. When an application declares a sensitive header whose name contains ^ or | and follows a cross-origin or HTTPS-to-HTTP redirect, unescaped regular-expression metacharacters prevent the generated filter from matching the declared header name, and the credential header is forwarded to an attacker-controlled redirect target. This issue is fixed in version 1.16.1.
- Record
CVE-2026-111755- CVSS 4.0
- 8.2 High
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Weakness
- CWE-185, CWE-200
- Updated
- 2026-11-02
OSV
8.2
follow-redirects sensitiveHeaders regex escaping can expose credential headers
follow-redirects is a Node.js HTTP and HTTPS client wrapper that automatically follows redirects. From 1.16.0 until 1.16.1, escapeRegex leaves valid header-name metacharacters unescaped in sensitiveHeaders. When an application declares a sensitive header whose name contains ^ or | and follows a cross-origin or HTTPS-to-HTTP redirect, unescaped regular-expression metacharacters prevent the generated filter from matching the declared header name, and the credential header is forwarded to an attacker-controlled redirect target. This issue is fixed in version 1.16.1.
- Record
CVE-2026-111755- CVSS 4.0
- 8.2 High
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-185, CWE-200
- Updated
- 2026-11-06
OSVDEBIAN-CVE-2026-111755
8.2
follow-redirects is a Node.js HTTP and HTTPS client wrapper that automatically follows redirects. From 1.16.0 until 1.16.1, escapeRegex leaves valid header-name metacharacters unescaped in sensitiveHeaders. When an application declares a sensitive header whose name contains ^ or | and follows a cross-origin or HTTPS-to-HTTP redirect, unescaped regular-expression metacharacters prevent the generated filter from matching the declared header name, and the credential header is forwarded to an attacker-controlled redirect target. This issue is fixed in version 1.16.1.
- Record
DEBIAN-CVE-2026-111755- CVSS 4.0
- 8.2 High
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Updated
- 2026-11-02
Show 4 moreShow less
OSVGHSA-8r9p-f939-6h3c
8.2
follow-redirects sensitiveHeaders regex escaping can expose credential headers
Summary
follow-redirects 1.16.0 introduced the sensitiveHeaders option (the fix for CVE-2026-40895 / GHSA-r4q5-vmmm-2653), which lets an application declare extra header names that must be removed when a redirect crosses to a different host or downgrades protocol. The filter is a single case-insensitive regular expression built by concatenating the declared header names into an alternation after passing each through escapeRegex. escapeRegex escapes only a partial set of metacharacters and leaves ^, |, [, {, and } unescaped. Header names may legitimately contain ^ and | (both are valid RFC 9110 token characters that Node accepts and sends), and for a declared name containing either, the generated pattern can never match the intended header. As a result, an application that adopts this option to protect a custom credential header, then follows an attacker-controlled cross-origin redirect, forwards that credential to the attacker with no error or warning, while believing it is protected. The failure is silent: the protection simply does not exist for the affected names. The built-in list (Authorization, Proxy-Authorization, Cookie) contains no metacharacters and is not affected by this defect.
Details
The filter is constructed once, in the RedirectableRequest constructor at index.js:118-120:
this._headerFilter = new RegExp("^(?:" +
sensitiveHeaders.concat(options.sensitiveHeaders).map(escapeRegex).join("|") +
")$", "i");
escapeRegex at index.js:703-705:
function escapeRegex(regex) {
return regex.replace(/[\]\\/()*+?.$]/g, "\\$&"); // escapes ] \ / ( ) * + ? . $ -- NOT ^ | [ { }
}
The character class escapes ], \, /, (, ), *, +, ?, ., and $. It omits ^, |, [, {, and }. Of these, Node's http.ClientRequest accepts ^ and | in header names (they are valid tchar values under RFC 9110) and rejects [, {, } with ERR_INVALID_HTTP_TOKEN, so ^ and | are the reachable vectors for a silent credential leak. Separately, although [, {, } cannot appear as live header names, declaring a sensitiveHeaders entry that contains one of them injects an unbalanced token into the alternation (for example an unterminated character class), so the filter RegExp throws a SyntaxError in the RedirectableRequest constructor and the request fails to start. That case is a loud request-time crash from the same incomplete-escaping root cause rather than a silent bypass, and the canonical escaper below fixes it as well.
For a declared sensitive header name containing an unescaped metacharacter, the alternation is broken in a fail-open way:
- A name containing
^, for exampleX-Api^Key, yields the alternativeX-Api^Keyinside the pattern. The^becomes a mid-pattern start-of-string anchor, so the alternative can never match any real header name.test("X-Api^Key")returnsfalse, and the header is not stripped. - A name containing
|, for exampleX-Token|Secret, is split into two separate alternativesX-TokenandSecret. The real headerX-Token|Secretis never matched (not stripped), while unrelated headers literally namedX-TokenorSecretwould be stripped instead.
The generated filter source, reproduced from the exact library logic, is:
^(?:Authorization|Proxy-Authorization|Cookie|X-Api^Key|X-Token|Secret|X-Control-Key)$
Direct matching results against this filter: X-Api^Key -> false, X-Token|Secret -> false, X-Control-Key (normal name) -> true, and the split-off X-Token -> true and Secret -> true (collateral wrong-stripping). The built-ins Authorization, Proxy-Authorization, Cookie all -> true.
Secondary, related weakness (filter snapshot not refreshed after beforeRedirect): the filter is built once at construction and applied at index.js:490, which runs before the beforeRedirect(this._options, ...) hook and the subsequent _sanitizeOptions at index.js:494-506. Because the strip…
- Record
GHSA-8r9p-f939-6h3c- CVSS 4.0
- 8.2 High
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-185, CWE-200
- Updated
- 2026-11-02
OSVUBUNTU-CVE-2026-111755
8.2
follow-redirects is a Node.js HTTP and HTTPS client wrapper that automatically follows redirects. From 1.16.0 until 1.16.1, escapeRegex leaves valid header-name metacharacters unescaped in sensitiveHeaders. When an application declares a sensitive header whose name contains ^ or | and follows a cross-origin or HTTPS-to-HTTP redirect, unescaped regular-expression metacharacters prevent the generated filter from matching the declared header name, and the credential header is forwarded to an attacker-controlled redirect target. This issue is fixed in version 1.16.1.
- Record
UBUNTU-CVE-2026-111755- CVSS 4.0
- 8.2 High
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N - Updated
- 2026-11-02
OSVopenSUSE-SU-2026:12424-1 No score
agama-web-ui-25+475.275dd4727-56.1 on GA media
These are all security issues fixed in the agama-web-ui-25+475.275dd4727-56.1 package on the GA media of openSUSE Tumbleweed.
- Record
openSUSE-SU-2026:12424-1- Updated
- 2026-11-06
OSVROOT-APP-NPM-CVE-2026-111755 No score
CVE-2026-111755 in follow-redirects - Patched by Root
Root has patched CVE-2026-111755 in the follow-redirects package for Root:npm. Multiple fixed versions available.
- Record
ROOT-APP-NPM-CVE-2026-111755- Updated
- 2026-11-03
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
follow-redirectsnpm |
1.16.0 up to 1.16.1 | 1.16.1 |
node-follow-redirectsDebian:12 |
All versions, plus listed versions 1.15.11+~1.14.4-11.15.11+~1.14.4-21.15.2+~1.14.1-11.15.3+~1.14.2-11.15.6+~1.14.4-1 Show 5 moreShow less1.15.6+~1.14.4-21.15.9+~1.14.4-11.16.0+~1.14.4-11.16.0+~1.14.4-21.16.1+~1.14.4-1 |
None known |
node-follow-redirectsDebian:13 |
All versions, plus listed versions 1.15.11+~1.14.4-11.15.11+~1.14.4-21.15.9+~1.14.4-11.16.0+~1.14.4-11.16.0+~1.14.4-21.16.1+~1.14.4-1 |
None known |
node-follow-redirectsDebian:14 |
before 1.16.1+~1.14.4-1, plus listed versions 1.15.11+~1.14.4-11.15.11+~1.14.4-21.15.9+~1.14.4-11.16.0+~1.14.4-11.16.0+~1.14.4-2 |
1.16.1+~1.14.4-1 |
follow-redirectsRoot:npm |
before 1.16.0-aikido.1 | 1.16.0-aikido.11.16.0-aikido.21.16.1-aikido.1 |
@rootio/follow-redirectsRoot:npm |
before 1.16.0-root.io.1 | 1.16.0-root.io.11.16.0-root.io.21.16.1-root.io.1 |
node-follow-redirectsUbuntu:Pro:18.04:LTS |
All versions, plus listed versions 1.2.4-11.2.4-1ubuntu0.18.04.1~esm11.2.4-1ubuntu0.18.04.1~esm2 |
None known |
node-follow-redirectsUbuntu:Pro:20.04:LTS |
All versions, plus listed versions 1.2.4-11.2.4-1ubuntu0.20.04.1~esm11.2.4-1ubuntu0.20.04.1~esm2 |
None known |
node-follow-redirectsUbuntu:Pro:22.04:LTS |
All versions, plus listed versions 1.13.1-11.14.5-11.14.7+~1.13.1-11.14.8+~1.14.0-11.14.9+~1.14.1-11.14.9+~1.14.1-1ubuntu0.1~esm11.14.9+~1.14.1-1ubuntu0.1~esm2 |
None known |
node-follow-redirectsUbuntu:Pro:24.04:LTS |
All versions, plus listed versions 1.15.2+~1.14.1-11.15.3+~1.14.2-11.15.6+~1.14.4-11.15.6+~1.14.4-1ubuntu0.1~esm1 |
None known |
node-follow-redirectsUbuntu:26.10 |
All versions, plus listed versions 1.15.11+~1.14.4-1build11.16.0+~1.14.4-2 |
None known |
node-follow-redirectsUbuntu:Pro:26.04:LTS |
All versions, plus listed versions 1.15.9+~1.14.4-11.15.11+~1.14.4-1build11.15.11+~1.14.4-1ubuntu0.1~esm1 |
None known |
agama-web-uiopenSUSE:Tumbleweed From an advisory covering 11 CVEs |
before 25+475.275dd4727-56.1 | 25+475.275dd4727-56.1 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected, aliases, references | OSV | |
| facts | OSV | |
| affected | OSV | |
| affected | OSV | |
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-111755 is a high vulnerability (CVSS 8.2) in Follow-redirects, published October 19, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.47%, the 40th percentile. Fixed in follow-redirects 1.16.1.
References
github.com/follow-redirects/follow-redirects/security/advisories/GHSA-8r9p-f939-6h3c
github.com/follow-redirects/follow-redirects/commit/080a76d0e125b37bf81717368a61d5dc37aa56c8
github.com/follow-redirects/follow-redirects/releases/tag/v1.16.1
nvd.nist.gov/vuln/detail/CVE-2026-111755
github.com/advisories/GHSA-8r9p-f939-6h3c
github.com/CVEProject/cvelistV5/tree/main/cves/2026/111xxx/CVE-2026-111755.json
Show 15 moreShow less
security-tracker.debian.org/tracker/CVE-2026-111755
github.com/follow-redirects/follow-redirects
ubuntu.com/security/CVE-2026-111755
cve.org/CVERecord?id=CVE-2026-111755
suse.com/security/cve/CVE-2026-102277
suse.com/security/cve/CVE-2026-110725
suse.com/security/cve/CVE-2026-111181
suse.com/security/cve/CVE-2026-111755
suse.com/security/cve/CVE-2026-111756
suse.com/security/cve/CVE-2026-115754
suse.com/security/cve/CVE-2026-115897
suse.com/security/cve/CVE-2026-116689
suse.com/security/cve/CVE-2026-75899
suse.com/security/cve/CVE-2026-84369
suse.com/security/cve/CVE-2026-86472
Left out here: the rest of 2 source descriptions. The JSON record has them.