Skip to content

Commit 4791514

Browse files
authored
fix: more header pollutions (#10779)
* fix: more header pollutions * fix: more header pollution issues * fix: cubic feedback * fix: prototype test
1 parent 6feafcf commit 4791514

6 files changed

Lines changed: 601 additions & 59 deletions

File tree

CHANGELOG.md

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,35 @@ This release delivers two critical security patches targeting header injection a
66

77
## 🔒 Security Fixes
88

9-
* **Header Injection (CRLF):** Rejects any header value containing `\r` or `\n` characters to block CRLF injection chains that could be used to exfiltrate cloud metadata (IMDS). Behavior change: headers with CR/LF now throw `"Invalid character in header content"`. (__#10660__)
9+
- **Header Injection (CRLF):** Rejects any header value containing `\r` or `\n` characters to block CRLF injection chains that could be used to exfiltrate cloud metadata (IMDS). Behavior change: headers with CR/LF now throw `"Invalid character in header content"`. (**#10660**)
1010

11-
* **SSRF via `no_proxy` Bypass:** Introduces a `shouldBypassProxy` helper that normalises hostnames (strips trailing dots, handles bracketed IPv6) before evaluating `no_proxy`/`NO_PROXY` rules, closing a gap that could cause loopback or internal hosts to be inadvertently proxied. (__#10661__)
11+
- **SSRF via `no_proxy` Bypass:** Introduces a `shouldBypassProxy` helper that normalises hostnames (strips trailing dots, handles bracketed IPv6) before evaluating `no_proxy`/`NO_PROXY` rules, closing a gap that could cause loopback or internal hosts to be inadvertently proxied. (**#10661**)
1212

1313
## 🚀 New Features
1414

15-
* **Deno & Bun Runtime Support:** Added full smoke test suites for Deno and Bun, with CI workflows that run both runtimes before any release is cut. (__#10652__)
15+
- **Deno & Bun Runtime Support:** Added full smoke test suites for Deno and Bun, with CI workflows that run both runtimes before any release is cut. (**#10652**)
1616

1717
## 🐛 Bug Fixes
1818

19-
* **Node.js v22 Compatibility:** Replaced deprecated `url.parse()` calls with the WHATWG `URL`/`URLSearchParams` API across examples, sandbox, and tests, eliminating `DEP0169` deprecation warnings on Node.js v22+. (__#10625__)
19+
- **Node.js v22 Compatibility:** Replaced deprecated `url.parse()` calls with the WHATWG `URL`/`URLSearchParams` API across examples, sandbox, and tests, eliminating `DEP0169` deprecation warnings on Node.js v22+. (**#10625**)
2020

2121
## 🔧 Maintenance & Chores
2222

23-
* **CI Security Hardening:** Added [zizmor](https://github.com/zizmorcore/zizmor) GitHub Actions security scanner; switched npm publish to OIDC Trusted Publishing (removing the long-lived `NODE_AUTH_TOKEN`); pinned all action references to full commit SHAs; narrowed workflow permissions to least privilege; gated the publish step behind a dedicated `npm-publish` environment; and blocked the sponsor-block workflow from running on forks. (__#10618__, __#10619__, __#10627__, __#10637__, __#10641__, __#10666__)
23+
- **CI Security Hardening:** Added [zizmor](https://github.com/zizmorcore/zizmor) GitHub Actions security scanner; switched npm publish to OIDC Trusted Publishing (removing the long-lived `NODE_AUTH_TOKEN`); pinned all action references to full commit SHAs; narrowed workflow permissions to least privilege; gated the publish step behind a dedicated `npm-publish` environment; and blocked the sponsor-block workflow from running on forks. (**#10618**, **#10619**, **#10627**, **#10637**, **#10641**, **#10666**)
2424

25-
* **Docs:** Clarified HTTP/2 support and the unsupported `httpVersion` option; added documentation for header case preservation; improved the `beforeRedirect` example to prevent accidental credential leakage. (__#10644__, __#10654__, __#10624__)
25+
- **Docs:** Clarified HTTP/2 support and the unsupported `httpVersion` option; added documentation for header case preservation; improved the `beforeRedirect` example to prevent accidental credential leakage. (**#10644**, **#10654**, **#10624**)
2626

27-
* **Dependencies:** Bumped `picomatch`, `handlebars`, `serialize-javascript`, `vite` (×3), `denoland/setup-deno`, and 4 additional dev dependencies to latest versions. (__#10564__, __#10565__, __#10567__, __#10568__, __#10572__, __#10574__, __#10663__, __#10664__, __#10665__, __#10669__, __#10670__)
27+
- **Dependencies:** Bumped `picomatch`, `handlebars`, `serialize-javascript`, `vite` (×3), `denoland/setup-deno`, and 4 additional dev dependencies to latest versions. (**#10564**, **#10565**, **#10567**, **#10568**, **#10572**, **#10574**, **#10663**, **#10664**, **#10665**, **#10669**, **#10670**)
2828

2929
## 🌟 New Contributors
3030

3131
We are thrilled to welcome our new contributors. Thank you for helping improve axios:
3232

33-
* **@Kilros0817** (__#10625__)
34-
* **@shaanmajid** (__#10616__, __#10617__, __#10618__, __#10619__, __#10637__, __#10641__, __#10666__)
35-
* **@ashstrc** (__#10624__, __#10644__)
36-
* **@Abhi3975** (__#10589__)
37-
* **@raashish1601** (__#10573__)
33+
- **@Kilros0817** (**#10625**)
34+
- **@shaanmajid** (**#10616**, **#10617**, **#10618**, **#10619**, **#10637**, **#10641**, **#10666**)
35+
- **@ashstrc** (**#10624**, **#10644**)
36+
- **@Abhi3975** (**#10589**)
37+
- **@raashish1601** (**#10573**)
3838

3939
[Full Changelog](https://github.com/axios/axios/compare/v1.14.0...v1.15.0)
4040

@@ -46,33 +46,33 @@ This release fixes a security vulnerability in the `formidable` dependency, reso
4646

4747
## 🔒 Security Fixes
4848

49-
* **Formidable Vulnerability:** Upgraded `formidable` from v2 to v3 to address a reported arbitrary-file vulnerability. Updated test server and assertions to align with the v3 API. (__#7533__)
49+
- **Formidable Vulnerability:** Upgraded `formidable` from v2 to v3 to address a reported arbitrary-file vulnerability. Updated test server and assertions to align with the v3 API. (**#7533**)
5050

5151
## 🐛 Bug Fixes
5252

53-
* **CommonJS Compatibility:** Restored `require('axios')` in Node.js by correcting the `main` field in `package.json` to point to the built CJS bundle. (__#7532__)
53+
- **CommonJS Compatibility:** Restored `require('axios')` in Node.js by correcting the `main` field in `package.json` to point to the built CJS bundle. (**#7532**)
5454

55-
* **Fetch Adapter:** Cancel the `ReadableStream` body after the request stream capability probe to prevent resource leaks. (__#7515__)
55+
- **Fetch Adapter:** Cancel the `ReadableStream` body after the request stream capability probe to prevent resource leaks. (**#7515**)
5656

57-
* **Proxy:** Upgraded `proxy-from-env` to v2 and switched to the named `getProxyForUrl` export, fixing proxy detection from environment variables and resolving CJS bundling errors. (__#7499__)
57+
- **Proxy:** Upgraded `proxy-from-env` to v2 and switched to the named `getProxyForUrl` export, fixing proxy detection from environment variables and resolving CJS bundling errors. (**#7499**)
5858

59-
* **HTTP/2:** Close detached HTTP/2 sessions on timeout to free resources when no new requests arrive. (__#7457__)
59+
- **HTTP/2:** Close detached HTTP/2 sessions on timeout to free resources when no new requests arrive. (**#7457**)
6060

61-
* **Headers:** Trim trailing CRLF characters from normalised header values. (__#7456__)
61+
- **Headers:** Trim trailing CRLF characters from normalised header values. (**#7456**)
6262

6363
## 🔧 Maintenance & Chores
6464

65-
* **Toolchain Modernisation:** Migrated test suite to Vitest, updated ESLint to v10, upgraded Rollup and `@rollup/plugin-babel`, migrated to Husky 9, upgraded TypeScript to latest, and modernised the Express test harness. (__#7484__, __#7489__, __#7498__, __#7505__, __#7506__, __#7507__, __#7508__, __#7509__, __#7510__, __#7516__, __#7522__)
65+
- **Toolchain Modernisation:** Migrated test suite to Vitest, updated ESLint to v10, upgraded Rollup and `@rollup/plugin-babel`, migrated to Husky 9, upgraded TypeScript to latest, and modernised the Express test harness. (**#7484**, **#7489**, **#7498**, **#7505**, **#7506**, **#7507**, **#7508**, **#7509**, **#7510**, **#7516**, **#7522**)
6666

67-
* **Dependencies:** Bumped `multer` to v2, `minimatch`, `tar`, `pacote`, `@babel/preset-env`, and additional dev dependencies. (__#7453__, __#7480__, __#7491__, __#7504__, __#7517__, __#7531__)
67+
- **Dependencies:** Bumped `multer` to v2, `minimatch`, `tar`, `pacote`, `@babel/preset-env`, and additional dev dependencies. (**#7453**, **#7480**, **#7491**, **#7504**, **#7517**, **#7531**)
6868

6969
## 🌟 New Contributors
7070

7171
We are thrilled to welcome our new contributors. Thank you for helping improve axios:
7272

73-
* **@penkzhou** (__#7515__)
74-
* **@aviu16** (__#7456__)
75-
* **@fedotov** (__#7457__)
73+
- **@penkzhou** (**#7515**)
74+
- **@aviu16** (**#7456**)
75+
- **@fedotov** (**#7457**)
7676

7777
[Full Changelog](https://github.com/axios/axios/compare/v1.13.6...v1.14.0)
7878

@@ -84,31 +84,31 @@ This release adds React Native Blob support, fixes several enumeration and expor
8484

8585
## 🚀 New Features
8686

87-
* **React Native Blob Support:** Axios now correctly handles native Blob objects in React Native environments. (__#5764__)
87+
- **React Native Blob Support:** Axios now correctly handles native Blob objects in React Native environments. (**#5764**)
8888

8989
## 🐛 Bug Fixes
9090

91-
* **AxiosError:** Fixed `AxiosError.from` not copying the `status` field from the source error. (__#7403__)
91+
- **AxiosError:** Fixed `AxiosError.from` not copying the `status` field from the source error. (**#7403**)
9292

93-
* **AxiosError:** Made the `message` property enumerable so it appears in `JSON.stringify` output and `Object.keys`. (__#7392__)
93+
- **AxiosError:** Made the `message` property enumerable so it appears in `JSON.stringify` output and `Object.keys`. (**#7392**)
9494

95-
* **FormData Detection:** Corrected safe FormData detection for WeChat Mini Program environments. (__#7324__)
95+
- **FormData Detection:** Corrected safe FormData detection for WeChat Mini Program environments. (**#7324**)
9696

97-
* **React Native / Browserify Export:** Fixed broken module export that caused import failures in React Native and Browserify. (__#7386__)
97+
- **React Native / Browserify Export:** Fixed broken module export that caused import failures in React Native and Browserify. (**#7386**)
9898

9999
## 🔧 Maintenance & Chores
100100

101-
* **Dependencies:** Migrated `@rollup/plugin-babel` from v5 to v6 and bumped the development dependencies group. (__#7424__, __#7432__)
101+
- **Dependencies:** Migrated `@rollup/plugin-babel` from v5 to v6 and bumped the development dependencies group. (**#7424**, **#7432**)
102102

103103
## 🌟 New Contributors
104104

105105
We are thrilled to welcome our new contributors. Thank you for helping improve axios:
106106

107-
* **@moh3n9595** (__#5764__)
108-
* **@skrtheboss** (__#7403__)
109-
* **@ybbus** (__#7392__)
110-
* **@Shiwaangee** (__#7324__)
111-
* **@Gudahtt** (__#7386__)
107+
- **@moh3n9595** (**#5764**)
108+
- **@skrtheboss** (**#7403**)
109+
- **@ybbus** (**#7392**)
110+
- **@Shiwaangee** (**#7324**)
111+
- **@Gudahtt** (**#7386**)
112112

113113
[Full Changelog](https://github.com/axios/axios/compare/v1.13.5...v1.13.6)
114114

@@ -120,29 +120,29 @@ This release patches a prototype pollution denial-of-service vulnerability, fixe
120120

121121
## 🔒 Security Fixes
122122

123-
* **Prototype Pollution (DoS):** Hardened `mergeConfig` to ignore `__proto__`, `constructor`, and `prototype` keys, preventing denial-of-service via prototype pollution when merging user-supplied config. (__#7369__)
123+
- **Prototype Pollution (DoS):** Hardened `mergeConfig` to ignore `__proto__`, `constructor`, and `prototype` keys, preventing denial-of-service via prototype pollution when merging user-supplied config. (**#7369**)
124124

125125
## 🚀 New Features
126126

127-
* **`isAbsoluteURL` Validation:** Added input validation to `isAbsoluteURL` to handle malformed or unexpected input gracefully. (__#7326__)
127+
- **`isAbsoluteURL` Validation:** Added input validation to `isAbsoluteURL` to handle malformed or unexpected input gracefully. (**#7326**)
128128

129129
## 🐛 Bug Fixes
130130

131-
* **AxiosError `status`:** Restored the `status` field on `AxiosError` instances, which was missing in v1.13.3 and later. (__#7368__)
131+
- **AxiosError `status`:** Restored the `status` field on `AxiosError` instances, which was missing in v1.13.3 and later. (**#7368**)
132132

133-
* **Interceptor Ordering:** Added a `useLegacyInterceptorOrder` option to restore pre-v1.13 interceptor execution order for applications relying on the previous behaviour. ([569f028](https://github.com/axios/axios/commit/569f028a5878faaec8d7d138ba686aac407bda4c))
133+
- **Interceptor Ordering:** Added a `useLegacyInterceptorOrder` option to restore pre-v1.13 interceptor execution order for applications relying on the previous behaviour. ([569f028](https://github.com/axios/axios/commit/569f028a5878faaec8d7d138ba686aac407bda4c))
134134

135135
## 🔧 Maintenance & Chores
136136

137-
* **CI:** Fixed run conditions and updated workflow YAMLs. (__#7372__, __#7373__)
137+
- **CI:** Fixed run conditions and updated workflow YAMLs. (**#7372**, **#7373**)
138138

139-
* **Dependencies:** Bumped `karma-sourcemap-loader` and minor package versions. (__#7356__, __#7360__)
139+
- **Dependencies:** Bumped `karma-sourcemap-loader` and minor package versions. (**#7356**, **#7360**)
140140

141141
## 🌟 New Contributors
142142

143143
We are thrilled to welcome our new contributors. Thank you for helping improve axios:
144144

145-
* **@asmitha-16** (__#7326__)
145+
- **@asmitha-16** (**#7326**)
146146

147147
[Full Changelog](https://github.com/axios/axios/compare/v1.13.4...v1.13.5)
148148

@@ -154,13 +154,13 @@ Patch release fixing regressions introduced in v1.13.3, including TypeScript exp
154154

155155
## 🐛 Bug Fixes
156156

157-
* **v1.13.3 Regressions:** Fixed multiple issues introduced by the v1.13.3 release, including broken merge configs. (__#7352__)
157+
- **v1.13.3 Regressions:** Fixed multiple issues introduced by the v1.13.3 release, including broken merge configs. (**#7352**)
158158

159-
* **TypeScript Exports:** Corrected TypeScript export declarations to restore proper type resolution. (__#4884__)
159+
- **TypeScript Exports:** Corrected TypeScript export declarations to restore proper type resolution. (**#4884**)
160160

161161
## 🔧 Maintenance & Chores
162162

163-
* **CI & Build:** Refactored CI pipeline and build configuration for stability. (__#7340__)
163+
- **CI & Build:** Refactored CI pipeline and build configuration for stability. (**#7340**)
164164

165165
[Full Changelog](https://github.com/axios/axios/compare/v1.13.3...v1.13.4)
166166

lib/adapters/http.js

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -615,9 +615,10 @@ export default isHttpAdapterSupported &&
615615

616616
// HTTP basic authentication
617617
let auth = undefined;
618-
if (config.auth) {
619-
const username = config.auth.username || '';
620-
const password = config.auth.password || '';
618+
const configAuth = own('auth');
619+
if (configAuth) {
620+
const username = configAuth.username || '';
621+
const password = configAuth.password || '';
621622
auth = username + ':' + password;
622623
}
623624

@@ -651,7 +652,10 @@ export default isHttpAdapterSupported &&
651652
false
652653
);
653654

654-
const options = {
655+
// Null-prototype to block prototype pollution gadgets on properties read
656+
// directly by Node's http.request (e.g. insecureHTTPParser, lookup).
657+
// See GHSA-q8qp-cvcw-x6jj.
658+
const options = Object.assign(Object.create(null), {
655659
path,
656660
method: method,
657661
headers: headers.toJSON(),
@@ -660,9 +664,9 @@ export default isHttpAdapterSupported &&
660664
protocol,
661665
family,
662666
beforeRedirect: dispatchBeforeRedirect,
663-
beforeRedirects: {},
667+
beforeRedirects: Object.create(null),
664668
http2Options,
665-
};
669+
});
666670

667671
// cacheable-lookup integration hotfix
668672
!utils.isUndefined(lookup) && (options.lookup = lookup);
@@ -723,8 +727,9 @@ export default isHttpAdapterSupported &&
723727
if (config.maxRedirects) {
724728
options.maxRedirects = config.maxRedirects;
725729
}
726-
if (config.beforeRedirect) {
727-
options.beforeRedirects.config = config.beforeRedirect;
730+
const configBeforeRedirect = own('beforeRedirect');
731+
if (configBeforeRedirect) {
732+
options.beforeRedirects.config = configBeforeRedirect;
728733
}
729734
transport = isHttpsRequest ? httpsFollow : httpFollow;
730735
}
@@ -737,9 +742,10 @@ export default isHttpAdapterSupported &&
737742
options.maxBodyLength = Infinity;
738743
}
739744

740-
if (config.insecureHTTPParser) {
741-
options.insecureHTTPParser = config.insecureHTTPParser;
742-
}
745+
// Always set an explicit own value so a polluted
746+
// Object.prototype.insecureHTTPParser cannot enable the lenient parser
747+
// through Node's internal options copy (GHSA-q8qp-cvcw-x6jj).
748+
options.insecureHTTPParser = Boolean(own('insecureHTTPParser'));
743749

744750
// Create the request
745751
req = transport.request(options, function handleResponse(res) {

lib/core/mergeConfig.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,18 @@ const headersToObject = (thing) => (thing instanceof AxiosHeaders ? { ...thing }
1717
export default function mergeConfig(config1, config2) {
1818
// eslint-disable-next-line no-param-reassign
1919
config2 = config2 || {};
20-
const config = {};
20+
21+
// Use a null-prototype object so that downstream reads such as `config.auth`
22+
// or `config.baseURL` cannot inherit polluted values from Object.prototype
23+
// (see GHSA-q8qp-cvcw-x6jj). `hasOwnProperty` is restored as a non-enumerable
24+
// own slot to preserve ergonomics for user code that relies on it.
25+
const config = Object.create(null);
26+
Object.defineProperty(config, 'hasOwnProperty', {
27+
value: Object.prototype.hasOwnProperty,
28+
enumerable: false,
29+
writable: true,
30+
configurable: true,
31+
});
2132

2233
function getMergedValue(target, source, prop, caseless) {
2334
if (utils.isPlainObject(target) && utils.isPlainObject(source)) {

lib/helpers/resolveConfig.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,24 @@ import buildURL from './buildURL.js';
1010
export default (config) => {
1111
const newConfig = mergeConfig({}, config);
1212

13-
let { data, withXSRFToken, xsrfHeaderName, xsrfCookieName, headers, auth } = newConfig;
13+
// Read only own properties to prevent prototype pollution gadgets
14+
// (e.g. Object.prototype.baseURL = 'https://evil.com'). See GHSA-q8qp-cvcw-x6jj.
15+
const own = (key) => (utils.hasOwnProp(newConfig, key) ? newConfig[key] : undefined);
16+
17+
const data = own('data');
18+
let withXSRFToken = own('withXSRFToken');
19+
const xsrfHeaderName = own('xsrfHeaderName');
20+
const xsrfCookieName = own('xsrfCookieName');
21+
let headers = own('headers');
22+
const auth = own('auth');
23+
const baseURL = own('baseURL');
24+
const allowAbsoluteUrls = own('allowAbsoluteUrls');
25+
const url = own('url');
1426

1527
newConfig.headers = headers = AxiosHeaders.from(headers);
1628

1729
newConfig.url = buildURL(
18-
buildFullPath(newConfig.baseURL, newConfig.url, newConfig.allowAbsoluteUrls),
30+
buildFullPath(baseURL, url, allowAbsoluteUrls),
1931
config.params,
2032
config.paramsSerializer
2133
);

lib/helpers/validator.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ function assertOptions(options, schema, allowUnknown) {
8686
let i = keys.length;
8787
while (i-- > 0) {
8888
const opt = keys[i];
89-
const validator = schema[opt];
89+
// Use hasOwnProperty so a polluted Object.prototype.<opt> cannot supply
90+
// a non-function validator and cause a TypeError. See GHSA-q8qp-cvcw-x6jj.
91+
const validator = Object.prototype.hasOwnProperty.call(schema, opt) ? schema[opt] : undefined;
9092
if (validator) {
9193
const value = options[opt];
9294
const result = value === undefined || validator(value, opt, options);

0 commit comments

Comments
 (0)