axios 0.31.0 → 0.31.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -83,12 +83,6 @@ Using npm:
83
83
  $ npm install axios
84
84
  ```
85
85
 
86
- Using bower:
87
-
88
- ```bash
89
- $ bower install axios
90
- ```
91
-
92
86
  Using yarn:
93
87
 
94
88
  ```bash
@@ -336,13 +330,21 @@ These are the available config options for making requests. Only the `url` is re
336
330
 
337
331
  // `params` are the URL parameters to be sent with the request
338
332
  // Must be a plain object or a URLSearchParams object
333
+ // Null bytes in param values stay percent-encoded as `%00` in the resulting query string
334
+ // (GHSA-xhjh-pmcv-23jw) — Axios does not reverse `encodeURIComponent` output for `%00`,
335
+ // so null-byte injection cannot be smuggled through the serializer.
339
336
  params: {
340
337
  ID: 12345
341
338
  },
342
339
 
343
340
  // `paramsSerializer` is an optional config in charge of serializing `params`
341
+ // Nested objects are walked with a bounded recursion depth (GHSA-62hf-57xw-28j9):
342
+ // once `maxDepth` is exceeded the serializer throws `ERR_FORM_DATA_DEPTH_EXCEEDED`
343
+ // instead of overflowing the call stack. The same cap applies to `toFormData` when
344
+ // `Content-Type: multipart/form-data` triggers automatic FormData serialization.
344
345
  paramsSerializer: {
345
- indexes: null // array indexes format (null - no brackets, false - empty brackets, true - brackets with indexes)
346
+ indexes: null, // array indexes format (null - no brackets, false - empty brackets, true - brackets with indexes)
347
+ maxDepth: 100 // maximum recursion depth for nested params (default: 100, Infinity disables the limit)
346
348
  },
347
349
 
348
350
  // `data` is the data to be sent as the request body
@@ -400,6 +402,9 @@ These are the available config options for making requests. Only the `url` is re
400
402
  xsrfHeaderName: 'X-XSRF-TOKEN', // default
401
403
 
402
404
  // `undefined` (default) - set XSRF header only for the same origin requests
405
+ // Only an explicit `true` (own property on the config) will add the XSRF header for
406
+ // cross-origin requests. Values inherited from `Object.prototype` are ignored
407
+ // (GHSA-xx6v-rp6x-q39c), so a polluted prototype cannot silently enable the token.
403
408
  withXSRFToken: boolean | undefined | ((config: AxiosRequestConfig) => boolean | undefined),
404
409
 
405
410
  // `onUploadProgress` allows handling of progress events for uploads
@@ -415,9 +420,13 @@ These are the available config options for making requests. Only the `url` is re
415
420
  },
416
421
 
417
422
  // `maxContentLength` defines the max size of the http response content in bytes allowed in node.js
423
+ // Also enforced on streamed responses (`responseType: 'stream'`): bytes are counted as they
424
+ // arrive and the stream is aborted with an error once the cap is exceeded (GHSA-vf2m-468p-8v99).
418
425
  maxContentLength: 2000,
419
426
 
420
427
  // `maxBodyLength` (Node only option) defines the max size of the http request content in bytes allowed
428
+ // Also enforced on stream uploads: uploaded bytes are tracked and the request is aborted
429
+ // once the cap is exceeded, even when the native http transport is used directly.
421
430
  maxBodyLength: 2000,
422
431
 
423
432
  // `validateStatus` defines whether to resolve or reject the promise for a given
@@ -522,6 +531,7 @@ These are the available config options for making requests. Only the `url` is re
522
531
  dots: boolean; // use dots instead of brackets format
523
532
  metaTokens: boolean; // keep special endings like {} in parameter key
524
533
  indexes: boolean; // array indexes format null - no brackets, false - empty brackets, true - brackets with indexes
534
+ maxDepth: number; // maximum recursion depth for nested objects (default: 100, Infinity disables the limit)
525
535
  }
526
536
  }
527
537
  ```
@@ -603,6 +613,8 @@ instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
603
613
 
604
614
  Config will be merged with an order of precedence. The order is library defaults found in [lib/defaults.js](https://github.com/axios/axios/blob/master/lib/defaults/index.js#L28), then `defaults` property of the instance, and finally `config` argument for the request. The latter will take precedence over the former. Here's an example.
605
615
 
616
+ > Note: the merged config object is created with a null prototype (`Object.create(null)`) and only own properties of the inputs are copied across. A polluted `Object.prototype` cannot leak values (for example `transport`, `adapter`, or `transformRequest`) into the outgoing config through inheritance, and keys such as `__proto__`, `constructor`, and `prototype` are dropped during the merge.
617
+
606
618
  ```js
607
619
  // Create an instance using the config defaults provided by the library
608
620
  // At this point the timeout config value is `0` as is the default for the library
@@ -1011,6 +1023,13 @@ The back-end body-parser could potentially use this meta-information to automati
1011
1023
  - `false`(default) - add empty brackets (`arr[]: 1`, `arr[]: 2`, `arr[]: 3`)
1012
1024
  - `true` - add brackets with indexes (`arr[0]: 1`, `arr[1]: 2`, `arr[2]: 3`)
1013
1025
 
1026
+ - `maxDepth: number = 100` - maximum recursion depth when serializing nested objects. Throws an `AxiosError` with
1027
+ code `ERR_FORM_DATA_DEPTH_EXCEEDED` if the limit is exceeded. Set to `Infinity` to disable the limit.
1028
+
1029
+ > **Security note:** If your server-side code forwards client-supplied objects to axios as request `data` or `params`,
1030
+ > keep `maxDepth` at a reasonable value (the default of 100 is sufficient for most use cases) to prevent
1031
+ > denial-of-service via deeply nested payloads.
1032
+
1014
1033
  Let's say we have an object like this one:
1015
1034
 
1016
1035
  ```js
package/UPGRADE_GUIDE.md CHANGED
@@ -159,8 +159,8 @@ axios.get('some/url')
159
159
  Previous versions of axios shipped with an AMD, CommonJS, and Global build. This has all been rolled into a single UMD build.
160
160
 
161
161
  ```js
162
- // AMD
163
- require(['bower_components/axios/dist/axios'], function (axios) {
162
+ // AMD (for example with a RequireJS path mapped to `axios/dist/axios`)
163
+ require(['axios/dist/axios'], function (axios) {
164
164
  /* ... */
165
165
  });
166
166
 
package/dist/axios.js CHANGED
@@ -1,4 +1,4 @@
1
- // axios v0.31.0 Copyright (c) 2026 Matt Zabriskie
1
+ // axios v0.31.1 Copyright (c) 2026 Matt Zabriskie
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
4
4
  typeof define === 'function' && define.amd ? define(factory) :
@@ -215,11 +215,17 @@
215
215
  */
216
216
  function isFormData(thing) {
217
217
  var pattern = '[object FormData]';
218
- return thing && (
219
- (typeof FormData === 'function' && thing instanceof FormData) ||
220
- toString.call(thing) === pattern ||
221
- (isFunction(thing.toString) && thing.toString() === pattern)
222
- );
218
+ if (!thing) return false;
219
+ if (typeof FormData === 'function' && thing instanceof FormData) return true;
220
+ // Reject non-objects (strings, numbers, booleans) up front — Object.getPrototypeOf
221
+ // throws a TypeError on primitives in ES5 environments.
222
+ if (!isObject(thing)) return false;
223
+ // Reject plain objects inheriting directly from Object.prototype so prototype-pollution gadgets can't spoof FormData (GHSA-6chq-wfr3-2hj9).
224
+ var proto = Object.getPrototypeOf(thing);
225
+ if (!proto || proto === Object.prototype) return false;
226
+ if (!isFunction(thing.append)) return false;
227
+ return toString.call(thing) === pattern ||
228
+ (isFunction(thing.toString) && thing.toString() === pattern);
223
229
  }
224
230
 
225
231
  /**
@@ -606,7 +612,8 @@
606
612
  'ERR_BAD_REQUEST',
607
613
  'ERR_CANCELED',
608
614
  'ERR_NOT_SUPPORT',
609
- 'ERR_INVALID_URL'
615
+ 'ERR_INVALID_URL',
616
+ 'ERR_FORM_DATA_DEPTH_EXCEEDED'
610
617
  // eslint-disable-next-line func-names
611
618
  ].forEach(function(code) {
612
619
  descriptors[code] = {value: code};
@@ -707,6 +714,7 @@
707
714
  var dots = options.dots;
708
715
  var indexes = options.indexes;
709
716
  var _Blob = options.Blob || typeof Blob !== 'undefined' && Blob;
717
+ var maxDepth = options.maxDepth === undefined ? 100 : options.maxDepth;
710
718
  var useBlob = _Blob && isSpecCompliant(formData);
711
719
 
712
720
  if (!utils.isFunction(visitor)) {
@@ -783,9 +791,19 @@
783
791
  isVisitable: isVisitable
784
792
  });
785
793
 
786
- function build(value, path) {
794
+ function build(value, path, depth) {
787
795
  if (utils.isUndefined(value)) return;
788
796
 
797
+ // eslint-disable-next-line no-param-reassign
798
+ depth = depth || 0;
799
+
800
+ if (depth > maxDepth) {
801
+ throw new AxiosError_1(
802
+ 'Maximum object depth of ' + maxDepth + ' exceeded (got ' + depth + ' levels)',
803
+ AxiosError_1.ERR_FORM_DATA_DEPTH_EXCEEDED
804
+ );
805
+ }
806
+
789
807
  if (stack.indexOf(value) !== -1) {
790
808
  throw Error('Circular reference detected in ' + path.join('.'));
791
809
  }
@@ -798,7 +816,7 @@
798
816
  );
799
817
 
800
818
  if (result === true) {
801
- build(el, path ? path.concat(key) : [key]);
819
+ build(el, path ? path.concat(key) : [key], depth + 1);
802
820
  }
803
821
  });
804
822
 
@@ -809,7 +827,7 @@
809
827
  throw new TypeError('data must be an object');
810
828
  }
811
829
 
812
- build(obj);
830
+ build(obj, null, 0);
813
831
 
814
832
  return formData;
815
833
  }
@@ -817,16 +835,17 @@
817
835
  var toFormData_1 = toFormData;
818
836
 
819
837
  function encode$1(str) {
838
+ // Do not map `%00` back to a raw null byte (GHSA-xhjh-pmcv-23jw): that reversed
839
+ // the safe percent-encoding from encodeURIComponent and enabled null byte injection.
820
840
  var charMap = {
821
841
  '!': '%21',
822
842
  "'": '%27',
823
843
  '(': '%28',
824
844
  ')': '%29',
825
845
  '~': '%7E',
826
- '%20': '+',
827
- '%00': '\x00'
846
+ '%20': '+'
828
847
  };
829
- return encodeURIComponent(str).replace(/[!'\(\)~]|%20|%00/g, function replacer(match) {
848
+ return encodeURIComponent(str).replace(/[!'\(\)~]|%20/g, function replacer(match) {
830
849
  return charMap[match];
831
850
  });
832
851
  }
@@ -1343,7 +1362,8 @@
1343
1362
  var requestData = config.data;
1344
1363
  var requestHeaders = config.headers;
1345
1364
  var responseType = config.responseType;
1346
- var withXSRFToken = config.withXSRFToken;
1365
+ // Guard against prototype pollution (GHSA-xx6v-rp6x-q39c): only honor own properties.
1366
+ var withXSRFToken = utils.hasOwnProperty(config, 'withXSRFToken') ? config.withXSRFToken : undefined;
1347
1367
  var onCanceled;
1348
1368
  function done() {
1349
1369
  if (config.cancelToken) {
@@ -1471,8 +1491,11 @@
1471
1491
  // Specifically not if we're in a web worker, or react-native.
1472
1492
  if (utils.isStandardBrowserEnv()) {
1473
1493
  // Add xsrf header
1474
- withXSRFToken && utils.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(config));
1475
- if (withXSRFToken || (withXSRFToken !== false && isURLSameOrigin(fullPath))) {
1494
+ if (utils.isFunction(withXSRFToken)) {
1495
+ withXSRFToken = withXSRFToken(config);
1496
+ }
1497
+ // Strict boolean check (GHSA-xx6v-rp6x-q39c): only `true` short-circuits the same-origin guard.
1498
+ if (withXSRFToken === true || (withXSRFToken !== false && isURLSameOrigin(fullPath))) {
1476
1499
  // Add xsrf header
1477
1500
  var xsrfValue = config.xsrfHeaderName && config.xsrfCookieName && cookies.read(config.xsrfCookieName);
1478
1501
  if (xsrfValue) {
@@ -1630,17 +1653,20 @@
1630
1653
  var isFileList;
1631
1654
 
1632
1655
  if (isObjectPayload) {
1656
+ var formSerializer = utils.hasOwnProperty(this, 'formSerializer') ? this.formSerializer : undefined;
1657
+ var envOption = utils.hasOwnProperty(this, 'env') ? this.env : undefined;
1658
+
1633
1659
  if (contentType.indexOf('application/x-www-form-urlencoded') !== -1) {
1634
- return toURLEncodedForm(data, this.formSerializer).toString();
1660
+ return toURLEncodedForm(data, formSerializer).toString();
1635
1661
  }
1636
1662
 
1637
1663
  if ((isFileList = utils.isFileList(data)) || contentType.indexOf('multipart/form-data') > -1) {
1638
- var _FormData = this.env && this.env.FormData;
1664
+ var _FormData = envOption && envOption.FormData;
1639
1665
 
1640
1666
  return toFormData_1(
1641
1667
  isFileList ? {'files[]': data} : data,
1642
1668
  _FormData && new _FormData(),
1643
- this.formSerializer
1669
+ formSerializer
1644
1670
  );
1645
1671
  }
1646
1672
  }
@@ -1858,7 +1884,17 @@
1858
1884
  var mergeConfig = function mergeConfig(config1, config2) {
1859
1885
  // eslint-disable-next-line no-param-reassign
1860
1886
  config2 = config2 || {};
1861
- var config = {};
1887
+ // Use a null-prototype object so a polluted Object.prototype cannot leak
1888
+ // values (e.g. transport, adapter) into the returned config via inheritance.
1889
+ var config = Object.create(null);
1890
+
1891
+ function getOwn(source, prop) {
1892
+ return utils.hasOwnProperty(source, prop) ? source[prop] : undefined;
1893
+ }
1894
+
1895
+ function hasOwn(source, prop) {
1896
+ return utils.hasOwnProperty(source, prop);
1897
+ }
1862
1898
 
1863
1899
  function getMergedValue(target, source) {
1864
1900
  if (utils.isPlainObject(target) && utils.isPlainObject(source)) {
@@ -1875,34 +1911,34 @@
1875
1911
 
1876
1912
  // eslint-disable-next-line consistent-return
1877
1913
  function mergeDeepProperties(prop) {
1878
- if (!utils.isUndefined(config2[prop])) {
1879
- return getMergedValue(config1[prop], config2[prop]);
1880
- } else if (!utils.isUndefined(config1[prop])) {
1914
+ if (hasOwn(config2, prop) && !utils.isUndefined(config2[prop])) {
1915
+ return getMergedValue(getOwn(config1, prop), config2[prop]);
1916
+ } else if (hasOwn(config1, prop) && !utils.isUndefined(config1[prop])) {
1881
1917
  return getMergedValue(undefined, config1[prop]);
1882
1918
  }
1883
1919
  }
1884
1920
 
1885
1921
  // eslint-disable-next-line consistent-return
1886
1922
  function valueFromConfig2(prop) {
1887
- if (!utils.isUndefined(config2[prop])) {
1923
+ if (hasOwn(config2, prop) && !utils.isUndefined(config2[prop])) {
1888
1924
  return getMergedValue(undefined, config2[prop]);
1889
1925
  }
1890
1926
  }
1891
1927
 
1892
1928
  // eslint-disable-next-line consistent-return
1893
1929
  function defaultToConfig2(prop) {
1894
- if (!utils.isUndefined(config2[prop])) {
1930
+ if (hasOwn(config2, prop) && !utils.isUndefined(config2[prop])) {
1895
1931
  return getMergedValue(undefined, config2[prop]);
1896
- } else if (!utils.isUndefined(config1[prop])) {
1932
+ } else if (hasOwn(config1, prop) && !utils.isUndefined(config1[prop])) {
1897
1933
  return getMergedValue(undefined, config1[prop]);
1898
1934
  }
1899
1935
  }
1900
1936
 
1901
1937
  // eslint-disable-next-line consistent-return
1902
1938
  function mergeDirectKeys(prop) {
1903
- if (prop in config2) {
1904
- return getMergedValue(config1[prop], config2[prop]);
1905
- } else if (prop in config1) {
1939
+ if (hasOwn(config2, prop)) {
1940
+ return getMergedValue(getOwn(config1, prop), config2[prop]);
1941
+ } else if (hasOwn(config1, prop)) {
1906
1942
  return getMergedValue(undefined, config1[prop]);
1907
1943
  }
1908
1944
  }
@@ -1951,7 +1987,7 @@
1951
1987
  };
1952
1988
 
1953
1989
  var data = {
1954
- "version": "0.31.0"
1990
+ "version": "0.31.1"
1955
1991
  };
1956
1992
 
1957
1993
  var VERSION = data.version;