axios 1.17.0 → 1.18.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.
@@ -1,4 +1,4 @@
1
- /*! Axios v1.17.0 Copyright (c) 2026 Matt Zabriskie and contributors */
1
+ /*! Axios v1.18.1 Copyright (c) 2026 Matt Zabriskie and contributors */
2
2
  'use strict';
3
3
 
4
4
  /**
@@ -20,6 +20,57 @@ const { toString } = Object.prototype;
20
20
  const { getPrototypeOf } = Object;
21
21
  const { iterator, toStringTag } = Symbol;
22
22
 
23
+ /* Creating a function that will check if an object has a property. */
24
+ const hasOwnProperty = (
25
+ ({ hasOwnProperty }) =>
26
+ (obj, prop) =>
27
+ hasOwnProperty.call(obj, prop)
28
+ )(Object.prototype);
29
+
30
+ /**
31
+ * Walk the prototype chain (excluding the shared Object.prototype) looking for
32
+ * an own `prop`. This distinguishes genuine own/inherited members — including
33
+ * class accessors and template prototypes — from members injected via
34
+ * Object.prototype pollution (e.g. `Object.prototype.username = '...'`), which
35
+ * live on Object.prototype itself and are therefore never matched.
36
+ *
37
+ * @param {*} thing The value whose chain to inspect
38
+ * @param {string|symbol} prop The property key to look for
39
+ *
40
+ * @returns {boolean} True when `prop` is owned below Object.prototype
41
+ */
42
+ const hasOwnInPrototypeChain = (thing, prop) => {
43
+ let obj = thing;
44
+ const seen = [];
45
+
46
+ while (obj != null && obj !== Object.prototype) {
47
+ if (seen.indexOf(obj) !== -1) {
48
+ return false;
49
+ }
50
+ seen.push(obj);
51
+
52
+ if (hasOwnProperty(obj, prop)) {
53
+ return true;
54
+ }
55
+ obj = getPrototypeOf(obj);
56
+ }
57
+ return false;
58
+ };
59
+
60
+ /**
61
+ * Read `obj[prop]` only when it is safe from Object.prototype pollution. Own
62
+ * properties and members inherited from a non-Object.prototype source (a class
63
+ * instance or template object) are honored; a value reachable only through a
64
+ * polluted Object.prototype is ignored and `undefined` is returned.
65
+ *
66
+ * @param {*} obj The source object
67
+ * @param {string|symbol} prop The property key to read
68
+ *
69
+ * @returns {*} The resolved value, or undefined when unsafe/absent
70
+ */
71
+ const getSafeProp = (obj, prop) =>
72
+ obj != null && hasOwnInPrototypeChain(obj, prop) ? obj[prop] : undefined;
73
+
23
74
  const kindOf = ((cache) => (thing) => {
24
75
  const str = toString.call(thing);
25
76
  return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());
@@ -145,7 +196,7 @@ const isBoolean = (thing) => thing === true || thing === false;
145
196
  * @returns {boolean} True if value is a plain Object, otherwise false
146
197
  */
147
198
  const isPlainObject = (val) => {
148
- if (kindOf(val) !== 'object') {
199
+ if (!isObject(val)) {
149
200
  return false;
150
201
  }
151
202
 
@@ -153,9 +204,12 @@ const isPlainObject = (val) => {
153
204
  return (
154
205
  (prototype === null ||
155
206
  prototype === Object.prototype ||
156
- Object.getPrototypeOf(prototype) === null) &&
157
- !(toStringTag in val) &&
158
- !(iterator in val)
207
+ getPrototypeOf(prototype) === null) &&
208
+ // Treat any genuine (non-Object.prototype-polluted) Symbol.toStringTag or
209
+ // Symbol.iterator as evidence the value is a tagged/iterable type rather
210
+ // than a plain object, while ignoring keys injected onto Object.prototype.
211
+ !hasOwnInPrototypeChain(val, toStringTag) &&
212
+ !hasOwnInPrototypeChain(val, iterator)
159
213
  );
160
214
  };
161
215
 
@@ -682,13 +736,6 @@ const toCamelCase = (str) => {
682
736
  });
683
737
  };
684
738
 
685
- /* Creating a function that will check if an object has a property. */
686
- const hasOwnProperty = (
687
- ({ hasOwnProperty }) =>
688
- (obj, prop) =>
689
- hasOwnProperty.call(obj, prop)
690
- )(Object.prototype);
691
-
692
739
  const { propertyIsEnumerable } = Object.prototype;
693
740
 
694
741
  /**
@@ -902,6 +949,20 @@ const asap =
902
949
 
903
950
  const isIterable = (thing) => thing != null && isFunction$1(thing[iterator]);
904
951
 
952
+ /**
953
+ * Determine if a value is iterable via an iterator that is NOT sourced solely
954
+ * from a polluted Object.prototype. Use this instead of `isIterable` whenever
955
+ * the iterable comes from untrusted input (e.g. user-supplied header sources),
956
+ * so `Object.prototype[Symbol.iterator] = ...` cannot turn an ordinary object
957
+ * into an attacker-controlled entries iterator.
958
+ *
959
+ * @param {*} thing The value to test
960
+ *
961
+ * @returns {boolean} True if value has a non-polluted iterator
962
+ */
963
+ const isSafeIterable = (thing) =>
964
+ thing != null && hasOwnInPrototypeChain(thing, iterator) && isIterable(thing);
965
+
905
966
  var utils$1 = {
906
967
  isArray,
907
968
  isArrayBuffer,
@@ -946,6 +1007,8 @@ var utils$1 = {
946
1007
  isHTMLForm,
947
1008
  hasOwnProperty,
948
1009
  hasOwnProp: hasOwnProperty, // an alias to avoid ESLint no-prototype-builtins detection
1010
+ hasOwnInPrototypeChain,
1011
+ getSafeProp,
949
1012
  reduceDescriptors,
950
1013
  freezeMethods,
951
1014
  toObjectSet,
@@ -962,6 +1025,7 @@ var utils$1 = {
962
1025
  setImmediate: _setImmediate,
963
1026
  asap,
964
1027
  isIterable,
1028
+ isSafeIterable,
965
1029
  };
966
1030
 
967
1031
  // RawAxiosHeaders whose duplicates are ignored by node
@@ -1194,8 +1258,8 @@ class AxiosHeaders {
1194
1258
  setHeaders(header, valueOrRewrite);
1195
1259
  } else if (utils$1.isString(header) && (header = header.trim()) && !isValidHeaderName(header)) {
1196
1260
  setHeaders(parseHeaders(header), valueOrRewrite);
1197
- } else if (utils$1.isObject(header) && utils$1.isIterable(header)) {
1198
- let obj = {},
1261
+ } else if (utils$1.isObject(header) && utils$1.isSafeIterable(header)) {
1262
+ let obj = Object.create(null),
1199
1263
  dest,
1200
1264
  key;
1201
1265
  for (const entry of header) {
@@ -1203,11 +1267,14 @@ class AxiosHeaders {
1203
1267
  throw new TypeError('Object iterator must return a key-value pair');
1204
1268
  }
1205
1269
 
1206
- obj[(key = entry[0])] = (dest = obj[key])
1207
- ? utils$1.isArray(dest)
1208
- ? [...dest, entry[1]]
1209
- : [dest, entry[1]]
1210
- : entry[1];
1270
+ key = entry[0];
1271
+
1272
+ if (utils$1.hasOwnProp(obj, key)) {
1273
+ dest = obj[key];
1274
+ obj[key] = utils$1.isArray(dest) ? [...dest, entry[1]] : [dest, entry[1]];
1275
+ } else {
1276
+ obj[key] = entry[1];
1277
+ }
1211
1278
  }
1212
1279
 
1213
1280
  setHeaders(obj, valueOrRewrite);
@@ -1500,7 +1567,19 @@ function redactConfig(config, redactKeys) {
1500
1567
  class AxiosError extends Error {
1501
1568
  static from(error, code, config, request, response, customProps) {
1502
1569
  const axiosError = new AxiosError(error.message, code || error.code, config, request, response);
1503
- axiosError.cause = error;
1570
+ // Match native `Error` `cause` semantics: non-enumerable. The wrapped
1571
+ // error often carries circular internals (sockets, requests, agents), so
1572
+ // an enumerable `cause` makes structured loggers (pino/winston) and any
1573
+ // own-property walk throw "Converting circular structure to JSON".
1574
+ // Regression from #6982; see #7205. `__proto__: null` mirrors the
1575
+ // `message` descriptor below (prototype-pollution-safe descriptor).
1576
+ Object.defineProperty(axiosError, 'cause', {
1577
+ __proto__: null,
1578
+ value: error,
1579
+ writable: true,
1580
+ enumerable: false,
1581
+ configurable: true,
1582
+ });
1504
1583
  axiosError.name = error.name;
1505
1584
 
1506
1585
  // Preserve status from the original error if not already set from response
@@ -1601,6 +1680,10 @@ AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED = 'ERR_FORM_DATA_DEPTH_EXCEEDED';
1601
1680
  // eslint-disable-next-line strict
1602
1681
  var httpAdapter = null;
1603
1682
 
1683
+ // Default nesting limit shared with the inverse transform (formDataToJSON) so
1684
+ // the FormData <-> JSON round-trip stays symmetric.
1685
+ const DEFAULT_FORM_DATA_MAX_DEPTH = 100;
1686
+
1604
1687
  /**
1605
1688
  * Determines if the given thing is a array or js object.
1606
1689
  *
@@ -1711,8 +1794,9 @@ function toFormData(obj, formData, options) {
1711
1794
  const dots = options.dots;
1712
1795
  const indexes = options.indexes;
1713
1796
  const _Blob = options.Blob || (typeof Blob !== 'undefined' && Blob);
1714
- const maxDepth = options.maxDepth === undefined ? 100 : options.maxDepth;
1797
+ const maxDepth = options.maxDepth === undefined ? DEFAULT_FORM_DATA_MAX_DEPTH : options.maxDepth;
1715
1798
  const useBlob = _Blob && utils$1.isSpecCompliantForm(formData);
1799
+ const stack = [];
1716
1800
 
1717
1801
  if (!utils$1.isFunction(visitor)) {
1718
1802
  throw new TypeError('visitor must be a function');
@@ -1734,12 +1818,50 @@ function toFormData(obj, formData, options) {
1734
1818
  }
1735
1819
 
1736
1820
  if (utils$1.isArrayBuffer(value) || utils$1.isTypedArray(value)) {
1737
- return useBlob && typeof Blob === 'function' ? new Blob([value]) : Buffer.from(value);
1821
+ if (useBlob && typeof _Blob === 'function') {
1822
+ return new _Blob([value]);
1823
+ }
1824
+ if (typeof Buffer !== 'undefined') {
1825
+ return Buffer.from(value);
1826
+ }
1827
+ throw new AxiosError('Blob is not supported. Use a Buffer instead.', AxiosError.ERR_NOT_SUPPORT);
1738
1828
  }
1739
1829
 
1740
1830
  return value;
1741
1831
  }
1742
1832
 
1833
+ function throwIfMaxDepthExceeded(depth) {
1834
+ if (depth > maxDepth) {
1835
+ throw new AxiosError(
1836
+ 'Object is too deeply nested (' + depth + ' levels). Max depth: ' + maxDepth,
1837
+ AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED
1838
+ );
1839
+ }
1840
+ }
1841
+
1842
+ function stringifyWithDepthLimit(value, depth) {
1843
+ if (maxDepth === Infinity) {
1844
+ return JSON.stringify(value);
1845
+ }
1846
+
1847
+ const ancestors = [];
1848
+
1849
+ return JSON.stringify(value, function limitDepth(_key, currentValue) {
1850
+ if (!utils$1.isObject(currentValue)) {
1851
+ return currentValue;
1852
+ }
1853
+
1854
+ while (ancestors.length && ancestors[ancestors.length - 1] !== this) {
1855
+ ancestors.pop();
1856
+ }
1857
+
1858
+ ancestors.push(currentValue);
1859
+ throwIfMaxDepthExceeded(depth + ancestors.length - 1);
1860
+
1861
+ return currentValue;
1862
+ });
1863
+ }
1864
+
1743
1865
  /**
1744
1866
  * Default visitor.
1745
1867
  *
@@ -1763,7 +1885,7 @@ function toFormData(obj, formData, options) {
1763
1885
  // eslint-disable-next-line no-param-reassign
1764
1886
  key = metaTokens ? key : key.slice(0, -2);
1765
1887
  // eslint-disable-next-line no-param-reassign
1766
- value = JSON.stringify(value);
1888
+ value = stringifyWithDepthLimit(value, 1);
1767
1889
  } else if (
1768
1890
  (utils$1.isArray(value) && isFlatArray(value)) ||
1769
1891
  ((utils$1.isFileList(value) || utils$1.endsWith(key, '[]')) && (arr = utils$1.toArray(value)))
@@ -1796,8 +1918,6 @@ function toFormData(obj, formData, options) {
1796
1918
  return false;
1797
1919
  }
1798
1920
 
1799
- const stack = [];
1800
-
1801
1921
  const exposedHelpers = Object.assign(predicates, {
1802
1922
  defaultVisitor,
1803
1923
  convertValue,
@@ -1807,12 +1927,7 @@ function toFormData(obj, formData, options) {
1807
1927
  function build(value, path, depth = 0) {
1808
1928
  if (utils$1.isUndefined(value)) return;
1809
1929
 
1810
- if (depth > maxDepth) {
1811
- throw new AxiosError(
1812
- 'Object is too deeply nested (' + depth + ' levels). Max depth: ' + maxDepth,
1813
- AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED
1814
- );
1815
- }
1930
+ throwIfMaxDepthExceeded(depth);
1816
1931
 
1817
1932
  if (stack.indexOf(value) !== -1) {
1818
1933
  throw new Error('Circular reference detected in ' + path.join('.'));
@@ -1886,9 +2001,7 @@ prototype.append = function append(name, value) {
1886
2001
 
1887
2002
  prototype.toString = function toString(encoder) {
1888
2003
  const _encode = encoder
1889
- ? function (value) {
1890
- return encoder.call(this, value, encode$1);
1891
- }
2004
+ ? (value) => encoder.call(this, value, encode$1)
1892
2005
  : encode$1;
1893
2006
 
1894
2007
  return this._pairs
@@ -1927,8 +2040,7 @@ function buildURL(url, params, options) {
1927
2040
  if (!params) {
1928
2041
  return url;
1929
2042
  }
1930
-
1931
- const _encode = (options && options.encode) || encode;
2043
+ url = url || '';
1932
2044
 
1933
2045
  const _options = utils$1.isFunction(options)
1934
2046
  ? {
@@ -1936,7 +2048,11 @@ function buildURL(url, params, options) {
1936
2048
  }
1937
2049
  : options;
1938
2050
 
1939
- const serializeFn = _options && _options.serialize;
2051
+ // Read serializer options pollution-safely: own properties and methods on a
2052
+ // class/template prototype are honored, but values injected onto a polluted
2053
+ // Object.prototype are ignored.
2054
+ const _encode = utils$1.getSafeProp(_options, 'encode') || encode;
2055
+ const serializeFn = utils$1.getSafeProp(_options, 'serialize');
1940
2056
 
1941
2057
  let serializedParams;
1942
2058
 
@@ -2033,6 +2149,7 @@ var transitionalDefaults = {
2033
2149
  clarifyTimeoutError: false,
2034
2150
  legacyInterceptorReqResOrdering: true,
2035
2151
  advertiseZstdAcceptEncoding: false,
2152
+ validateStatusUndefinedResolves: true,
2036
2153
  };
2037
2154
 
2038
2155
  var URLSearchParams$1 = typeof URLSearchParams !== 'undefined' ? URLSearchParams : AxiosURLSearchParams;
@@ -2124,6 +2241,17 @@ function toURLEncodedForm(data, options) {
2124
2241
  });
2125
2242
  }
2126
2243
 
2244
+ const MAX_DEPTH = DEFAULT_FORM_DATA_MAX_DEPTH;
2245
+
2246
+ function throwIfDepthExceeded(index) {
2247
+ if (index > MAX_DEPTH) {
2248
+ throw new AxiosError(
2249
+ 'FormData field is too deeply nested (' + index + ' levels). Max depth: ' + MAX_DEPTH,
2250
+ AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED
2251
+ );
2252
+ }
2253
+ }
2254
+
2127
2255
  /**
2128
2256
  * It takes a string like `foo[x][y][z]` and returns an array like `['foo', 'x', 'y', 'z']
2129
2257
  *
@@ -2136,9 +2264,16 @@ function parsePropPath(name) {
2136
2264
  // foo.x.y.z
2137
2265
  // foo-x-y-z
2138
2266
  // foo x y z
2139
- return utils$1.matchAll(/\w+|\[(\w*)]/g, name).map((match) => {
2140
- return match[0] === '[]' ? '' : match[1] || match[0];
2141
- });
2267
+ const path = [];
2268
+ const pattern = /\w+|\[(\w*)]/g;
2269
+ let match;
2270
+
2271
+ while ((match = pattern.exec(name)) !== null) {
2272
+ throwIfDepthExceeded(path.length);
2273
+ path.push(match[0] === '[]' ? '' : match[1] || match[0]);
2274
+ }
2275
+
2276
+ return path;
2142
2277
  }
2143
2278
 
2144
2279
  /**
@@ -2170,6 +2305,8 @@ function arrayToObject(arr) {
2170
2305
  */
2171
2306
  function formDataToJSON(formData) {
2172
2307
  function buildPath(path, value, target, index) {
2308
+ throwIfDepthExceeded(index);
2309
+
2173
2310
  let name = path[index++];
2174
2311
 
2175
2312
  if (name === '__proto__') return true;
@@ -2655,7 +2792,11 @@ var cookies = platform.hasStandardBrowserEnv
2655
2792
  const cookie = cookies[i].replace(/^\s+/, '');
2656
2793
  const eq = cookie.indexOf('=');
2657
2794
  if (eq !== -1 && cookie.slice(0, eq) === name) {
2658
- return decodeURIComponent(cookie.slice(eq + 1));
2795
+ try {
2796
+ return decodeURIComponent(cookie.slice(eq + 1));
2797
+ } catch (e) {
2798
+ return cookie.slice(eq + 1);
2799
+ }
2659
2800
  }
2660
2801
  }
2661
2802
  return null;
@@ -2706,6 +2847,31 @@ function combineURLs(baseURL, relativeURL) {
2706
2847
  : baseURL;
2707
2848
  }
2708
2849
 
2850
+ const malformedHttpProtocol = /^https?:(?!\/\/)/i;
2851
+ const httpProtocolControlCharacters = /[\t\n\r]/g;
2852
+
2853
+ function stripLeadingC0ControlOrSpace(url) {
2854
+ let i = 0;
2855
+ while (i < url.length && url.charCodeAt(i) <= 0x20) {
2856
+ i++;
2857
+ }
2858
+ return url.slice(i);
2859
+ }
2860
+
2861
+ function normalizeURLForProtocolCheck(url) {
2862
+ return stripLeadingC0ControlOrSpace(url).replace(httpProtocolControlCharacters, '');
2863
+ }
2864
+
2865
+ function assertValidHttpProtocolURL(url, config) {
2866
+ if (typeof url === 'string' && malformedHttpProtocol.test(normalizeURLForProtocolCheck(url))) {
2867
+ throw new AxiosError(
2868
+ 'Invalid URL: missing "//" after protocol',
2869
+ AxiosError.ERR_INVALID_URL,
2870
+ config
2871
+ );
2872
+ }
2873
+ }
2874
+
2709
2875
  /**
2710
2876
  * Creates a new URL by combining the baseURL with the requestedURL,
2711
2877
  * only when the requestedURL is not already an absolute URL.
@@ -2716,9 +2882,11 @@ function combineURLs(baseURL, relativeURL) {
2716
2882
  *
2717
2883
  * @returns {string} The combined full path
2718
2884
  */
2719
- function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls) {
2885
+ function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls, config) {
2886
+ assertValidHttpProtocolURL(requestedURL, config);
2720
2887
  let isRelativeUrl = !isAbsoluteURL(requestedURL);
2721
2888
  if (baseURL && (isRelativeUrl || allowAbsoluteUrls === false)) {
2889
+ assertValidHttpProtocolURL(baseURL, config);
2722
2890
  return combineURLs(baseURL, requestedURL);
2723
2891
  }
2724
2892
  return requestedURL;
@@ -2737,6 +2905,7 @@ const headersToObject = (thing) => (thing instanceof AxiosHeaders ? { ...thing }
2737
2905
  */
2738
2906
  function mergeConfig(config1, config2) {
2739
2907
  // eslint-disable-next-line no-param-reassign
2908
+ config1 = config1 || {};
2740
2909
  config2 = config2 || {};
2741
2910
 
2742
2911
  // Use a null-prototype object so that downstream reads such as `config.auth`
@@ -2789,6 +2958,28 @@ function mergeConfig(config1, config2) {
2789
2958
  }
2790
2959
  }
2791
2960
 
2961
+ function getMergedTransitionalOption(prop) {
2962
+ const transitional2 = utils$1.hasOwnProp(config2, 'transitional') ? config2.transitional : undefined;
2963
+
2964
+ if (!utils$1.isUndefined(transitional2)) {
2965
+ if (utils$1.isPlainObject(transitional2)) {
2966
+ if (utils$1.hasOwnProp(transitional2, prop)) {
2967
+ return transitional2[prop];
2968
+ }
2969
+ } else {
2970
+ return undefined;
2971
+ }
2972
+ }
2973
+
2974
+ const transitional1 = utils$1.hasOwnProp(config1, 'transitional') ? config1.transitional : undefined;
2975
+
2976
+ if (utils$1.isPlainObject(transitional1) && utils$1.hasOwnProp(transitional1, prop)) {
2977
+ return transitional1[prop];
2978
+ }
2979
+
2980
+ return undefined;
2981
+ }
2982
+
2792
2983
  // eslint-disable-next-line consistent-return
2793
2984
  function mergeDirectKeys(a, b, prop) {
2794
2985
  if (utils$1.hasOwnProp(config2, prop)) {
@@ -2841,6 +3032,18 @@ function mergeConfig(config1, config2) {
2841
3032
  (utils$1.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue);
2842
3033
  });
2843
3034
 
3035
+ if (
3036
+ utils$1.hasOwnProp(config2, 'validateStatus') &&
3037
+ utils$1.isUndefined(config2.validateStatus) &&
3038
+ getMergedTransitionalOption('validateStatusUndefinedResolves') === false
3039
+ ) {
3040
+ if (utils$1.hasOwnProp(config1, 'validateStatus')) {
3041
+ config.validateStatus = getMergedValue(undefined, config1.validateStatus);
3042
+ } else {
3043
+ delete config.validateStatus;
3044
+ }
3045
+ }
3046
+
2844
3047
  return config;
2845
3048
  }
2846
3049
 
@@ -2852,7 +3055,7 @@ function setFormDataHeaders(headers, formHeaders, policy) {
2852
3055
  return;
2853
3056
  }
2854
3057
 
2855
- Object.entries(formHeaders).forEach(([key, val]) => {
3058
+ Object.entries(formHeaders || {}).forEach(([key, val]) => {
2856
3059
  if (FORM_DATA_CONTENT_HEADERS.includes(key.toLowerCase())) {
2857
3060
  headers.set(key, val);
2858
3061
  }
@@ -2892,18 +3095,24 @@ function resolveConfig(config) {
2892
3095
  newConfig.headers = headers = AxiosHeaders.from(headers);
2893
3096
 
2894
3097
  newConfig.url = buildURL(
2895
- buildFullPath(baseURL, url, allowAbsoluteUrls),
3098
+ buildFullPath(baseURL, url, allowAbsoluteUrls, newConfig),
2896
3099
  own('params'),
2897
3100
  own('paramsSerializer')
2898
3101
  );
2899
3102
 
2900
3103
  // HTTP basic authentication
2901
3104
  if (auth) {
2902
- headers.set(
2903
- 'Authorization',
2904
- 'Basic ' +
2905
- btoa((auth.username || '') + ':' + (auth.password ? encodeUTF8$1(auth.password) : ''))
2906
- );
3105
+ const username = utils$1.getSafeProp(auth, 'username') || '';
3106
+ const password = utils$1.getSafeProp(auth, 'password') || '';
3107
+
3108
+ try {
3109
+ headers.set(
3110
+ 'Authorization',
3111
+ 'Basic ' + btoa(username + ':' + (password ? encodeUTF8$1(password) : ''))
3112
+ );
3113
+ } catch (e) {
3114
+ throw AxiosError.from(e, AxiosError.ERR_BAD_OPTION_VALUE, config);
3115
+ }
2907
3116
  }
2908
3117
 
2909
3118
  if (utils$1.isFormData(data)) {
@@ -3154,6 +3363,7 @@ var xhrAdapter = isXHRAdapterSupported &&
3154
3363
  config
3155
3364
  )
3156
3365
  );
3366
+ done();
3157
3367
  return;
3158
3368
  }
3159
3369
 
@@ -3205,7 +3415,7 @@ const composeSignals = (signals, timeout) => {
3205
3415
  signals = null;
3206
3416
  };
3207
3417
 
3208
- signals.forEach((signal) => signal.addEventListener('abort', onabort));
3418
+ signals.forEach((signal) => signal.addEventListener('abort', onabort, { once: true }));
3209
3419
 
3210
3420
  const { signal } = controller;
3211
3421
 
@@ -3308,11 +3518,19 @@ const trackStream = (stream, chunkSize, onProgress, onFinish) => {
3308
3518
  * Estimate decoded byte length of a data:// URL *without* allocating large buffers.
3309
3519
  * - For base64: compute exact decoded size using length and padding;
3310
3520
  * handle %XX at the character-count level (no string allocation).
3311
- * - For non-base64: use UTF-8 byteLength of the encoded body as a safe upper bound.
3521
+ * - For non-base64: compute the exact percent-decoded UTF-8 byte length.
3312
3522
  *
3313
3523
  * @param {string} url
3314
3524
  * @returns {number}
3315
3525
  */
3526
+ const isHexDigit = (charCode) =>
3527
+ (charCode >= 48 && charCode <= 57) ||
3528
+ (charCode >= 65 && charCode <= 70) ||
3529
+ (charCode >= 97 && charCode <= 102);
3530
+
3531
+ const isPercentEncodedByte = (str, i, len) =>
3532
+ i + 2 < len && isHexDigit(str.charCodeAt(i + 1)) && isHexDigit(str.charCodeAt(i + 2));
3533
+
3316
3534
  function estimateDataURLDecodedBytes(url) {
3317
3535
  if (!url || typeof url !== 'string') return 0;
3318
3536
  if (!url.startsWith('data:')) return 0;
@@ -3332,9 +3550,7 @@ function estimateDataURLDecodedBytes(url) {
3332
3550
  if (body.charCodeAt(i) === 37 /* '%' */ && i + 2 < len) {
3333
3551
  const a = body.charCodeAt(i + 1);
3334
3552
  const b = body.charCodeAt(i + 2);
3335
- const isHex =
3336
- ((a >= 48 && a <= 57) || (a >= 65 && a <= 70) || (a >= 97 && a <= 102)) &&
3337
- ((b >= 48 && b <= 57) || (b >= 65 && b <= 70) || (b >= 97 && b <= 102));
3553
+ const isHex = isHexDigit(a) && isHexDigit(b);
3338
3554
 
3339
3555
  if (isHex) {
3340
3556
  effectiveLen -= 2;
@@ -3375,18 +3591,17 @@ function estimateDataURLDecodedBytes(url) {
3375
3591
  return bytes > 0 ? bytes : 0;
3376
3592
  }
3377
3593
 
3378
- if (typeof Buffer !== 'undefined' && typeof Buffer.byteLength === 'function') {
3379
- return Buffer.byteLength(body, 'utf8');
3380
- }
3381
-
3382
3594
  // Compute UTF-8 byte length directly from UTF-16 code units without allocating
3383
3595
  // a byte buffer (TextEncoder.encode would defeat the DoS guard on large bodies).
3384
- // Using body.length here would undercount non-ASCII (e.g. '€' is 1 code unit
3385
- // but 3 UTF-8 bytes).
3596
+ // Valid %XX triplets count as one decoded byte; this matches the bytes that
3597
+ // decodeURIComponent(body) would produce before Buffer re-encodes the string.
3386
3598
  let bytes = 0;
3387
3599
  for (let i = 0, len = body.length; i < len; i++) {
3388
3600
  const c = body.charCodeAt(i);
3389
- if (c < 0x80) {
3601
+ if (c === 37 /* '%' */ && isPercentEncodedByte(body, i, len)) {
3602
+ bytes += 1;
3603
+ i += 2;
3604
+ } else if (c < 0x80) {
3390
3605
  bytes += 1;
3391
3606
  } else if (c < 0x800) {
3392
3607
  bytes += 2;
@@ -3405,7 +3620,7 @@ function estimateDataURLDecodedBytes(url) {
3405
3620
  return bytes;
3406
3621
  }
3407
3622
 
3408
- const VERSION = "1.17.0";
3623
+ const VERSION = "1.18.1";
3409
3624
 
3410
3625
  const DEFAULT_CHUNK_SIZE = 64 * 1024;
3411
3626
 
@@ -3626,14 +3841,28 @@ const factory = (env) => {
3626
3841
 
3627
3842
  let requestContentLength;
3628
3843
 
3844
+ // AxiosError we raise while the request body is being streamed. Captured
3845
+ // by identity so the catch block can surface it directly, regardless of
3846
+ // how the runtime wraps the resulting fetch rejection (undici exposes it
3847
+ // as `err.cause`; some browsers drop the original error entirely).
3848
+ let pendingBodyError = null;
3849
+
3850
+ const maxBodyLengthError = () =>
3851
+ new AxiosError(
3852
+ 'Request body larger than maxBodyLength limit',
3853
+ AxiosError.ERR_BAD_REQUEST,
3854
+ config,
3855
+ request
3856
+ );
3857
+
3629
3858
  try {
3630
3859
  // HTTP basic authentication
3631
3860
  let auth = undefined;
3632
3861
  const configAuth = own('auth');
3633
3862
 
3634
3863
  if (configAuth) {
3635
- const username = configAuth.username || '';
3636
- const password = configAuth.password || '';
3864
+ const username = utils$1.getSafeProp(configAuth, 'username') || '';
3865
+ const password = utils$1.getSafeProp(configAuth, 'password') || '';
3637
3866
  auth = {
3638
3867
  username,
3639
3868
  password
@@ -3682,53 +3911,96 @@ const factory = (env) => {
3682
3911
  }
3683
3912
  }
3684
3913
 
3685
- // Enforce maxBodyLength against the outbound request body before dispatch.
3686
- // Mirrors http.js behavior (ERR_BAD_REQUEST / 'Request body larger than
3687
- // maxBodyLength limit'). Skip when the body length cannot be determined
3688
- // (e.g. a live ReadableStream supplied by the caller).
3914
+ // Enforce maxBodyLength against known-size bodies before dispatch using
3915
+ // the body's *actual* size never a caller-declared Content-Length,
3916
+ // which could under-report to slip an oversized body past the check.
3917
+ // Unknown-size streams return undefined here and are counted per-chunk
3918
+ // below as fetch consumes them.
3689
3919
  if (hasMaxBodyLength && method !== 'get' && method !== 'head') {
3690
- const outboundLength = await resolveBodyLength(headers, data);
3691
- if (
3692
- typeof outboundLength === 'number' &&
3693
- isFinite(outboundLength) &&
3694
- outboundLength > maxBodyLength
3695
- ) {
3696
- throw new AxiosError(
3697
- 'Request body larger than maxBodyLength limit',
3698
- AxiosError.ERR_BAD_REQUEST,
3699
- config,
3700
- request
3701
- );
3920
+ const outboundLength = await getBodyLength(data);
3921
+ if (typeof outboundLength === 'number' && isFinite(outboundLength)) {
3922
+ requestContentLength = outboundLength;
3923
+ if (outboundLength > maxBodyLength) {
3924
+ throw maxBodyLengthError();
3925
+ }
3702
3926
  }
3703
3927
  }
3704
3928
 
3929
+ // A streamed body under maxBodyLength must be counted as fetch consumes
3930
+ // it; its size is never trusted from a caller-declared Content-Length.
3931
+ const mustEnforceStreamBody =
3932
+ hasMaxBodyLength && (utils$1.isReadableStream(data) || utils$1.isStream(data));
3933
+
3934
+ const trackRequestStream = (stream, onProgress, flush) =>
3935
+ trackStream(
3936
+ stream,
3937
+ DEFAULT_CHUNK_SIZE,
3938
+ (loadedBytes) => {
3939
+ if (hasMaxBodyLength && loadedBytes > maxBodyLength) {
3940
+ throw (pendingBodyError = maxBodyLengthError());
3941
+ }
3942
+ onProgress && onProgress(loadedBytes);
3943
+ },
3944
+ flush
3945
+ );
3946
+
3705
3947
  if (
3706
- onUploadProgress &&
3707
3948
  supportsRequestStream &&
3708
3949
  method !== 'get' &&
3709
3950
  method !== 'head' &&
3710
- (requestContentLength = await resolveBodyLength(headers, data)) !== 0
3951
+ (onUploadProgress || mustEnforceStreamBody)
3711
3952
  ) {
3712
- let _request = new Request(url, {
3713
- method: 'POST',
3714
- body: data,
3715
- duplex: 'half',
3716
- });
3953
+ requestContentLength =
3954
+ requestContentLength == null ? await resolveBodyLength(headers, data) : requestContentLength;
3955
+
3956
+ // A declared length of 0 is only trusted to skip the wrap when we are
3957
+ // not enforcing a stream limit (which must not rely on that header).
3958
+ if (requestContentLength !== 0 || mustEnforceStreamBody) {
3959
+ let _request = new Request(url, {
3960
+ method: 'POST',
3961
+ body: data,
3962
+ duplex: 'half',
3963
+ });
3717
3964
 
3718
- let contentTypeHeader;
3965
+ let contentTypeHeader;
3719
3966
 
3720
- if (utils$1.isFormData(data) && (contentTypeHeader = _request.headers.get('content-type'))) {
3721
- headers.setContentType(contentTypeHeader);
3722
- }
3967
+ if (utils$1.isFormData(data) && (contentTypeHeader = _request.headers.get('content-type'))) {
3968
+ headers.setContentType(contentTypeHeader);
3969
+ }
3723
3970
 
3724
- if (_request.body) {
3725
- const [onProgress, flush] = progressEventDecorator(
3726
- requestContentLength,
3727
- progressEventReducer(asyncDecorator(onUploadProgress))
3728
- );
3971
+ if (_request.body) {
3972
+ const [onProgress, flush] =
3973
+ (onUploadProgress &&
3974
+ progressEventDecorator(
3975
+ requestContentLength,
3976
+ progressEventReducer(asyncDecorator(onUploadProgress))
3977
+ )) ||
3978
+ [];
3729
3979
 
3730
- data = trackStream(_request.body, DEFAULT_CHUNK_SIZE, onProgress, flush);
3980
+ data = trackRequestStream(_request.body, onProgress, flush);
3981
+ }
3731
3982
  }
3983
+ } else if (
3984
+ mustEnforceStreamBody &&
3985
+ !isRequestSupported &&
3986
+ isReadableStreamSupported &&
3987
+ method !== 'get' &&
3988
+ method !== 'head'
3989
+ ) {
3990
+ data = trackRequestStream(data);
3991
+ } else if (
3992
+ mustEnforceStreamBody &&
3993
+ isRequestSupported &&
3994
+ !supportsRequestStream &&
3995
+ method !== 'get' &&
3996
+ method !== 'head'
3997
+ ) {
3998
+ throw new AxiosError(
3999
+ 'Stream request bodies are not supported by the current fetch implementation',
4000
+ AxiosError.ERR_NOT_SUPPORT,
4001
+ config,
4002
+ request
4003
+ );
3732
4004
  }
3733
4005
 
3734
4006
  if (!utils$1.isString(withCredentials)) {
@@ -3771,10 +4043,12 @@ const factory = (env) => {
3771
4043
  ? _fetch(request, fetchOptions)
3772
4044
  : _fetch(url, resolvedOptions));
3773
4045
 
4046
+ const responseHeaders = AxiosHeaders.from(response.headers);
4047
+
3774
4048
  // Cheap pre-check: if the server honestly declares a content-length that
3775
4049
  // already exceeds the cap, reject before we start streaming.
3776
4050
  if (hasMaxContentLength) {
3777
- const declaredLength = utils$1.toFiniteNumber(response.headers.get('content-length'));
4051
+ const declaredLength = utils$1.toFiniteNumber(responseHeaders.getContentLength());
3778
4052
  if (declaredLength != null && declaredLength > maxContentLength) {
3779
4053
  throw new AxiosError(
3780
4054
  'maxContentLength size of ' + maxContentLength + ' exceeded',
@@ -3799,7 +4073,7 @@ const factory = (env) => {
3799
4073
  options[prop] = response[prop];
3800
4074
  });
3801
4075
 
3802
- const responseContentLength = utils$1.toFiniteNumber(response.headers.get('content-length'));
4076
+ const responseContentLength = utils$1.toFiniteNumber(responseHeaders.getContentLength());
3803
4077
 
3804
4078
  const [onProgress, flush] =
3805
4079
  (onDownloadProgress &&
@@ -3890,23 +4164,55 @@ const factory = (env) => {
3890
4164
  const canceledError = composedSignal.reason;
3891
4165
  canceledError.config = config;
3892
4166
  request && (canceledError.request = request);
3893
- err !== canceledError && (canceledError.cause = err);
4167
+ if (err !== canceledError) {
4168
+ // Non-enumerable to match native Error `cause` semantics so loggers
4169
+ // don't recurse into circular fetch internals (see #7205).
4170
+ Object.defineProperty(canceledError, 'cause', {
4171
+ __proto__: null,
4172
+ value: err,
4173
+ writable: true,
4174
+ enumerable: false,
4175
+ configurable: true,
4176
+ });
4177
+ }
3894
4178
  throw canceledError;
3895
4179
  }
3896
4180
 
4181
+ // Surface a maxBodyLength violation we raised while the request body was
4182
+ // being streamed. Matching by identity (rather than reading
4183
+ // `err.cause.isAxiosError`) keeps the error deterministic across runtimes
4184
+ // and avoids both prototype-pollution reads and mis-attributing a foreign
4185
+ // AxiosError that merely happened to land in `err.cause`.
4186
+ if (pendingBodyError) {
4187
+ request && !pendingBodyError.request && (pendingBodyError.request = request);
4188
+ throw pendingBodyError;
4189
+ }
4190
+
4191
+ // Re-throw AxiosErrors we raised synchronously (data: URL / content-length
4192
+ // pre-checks, response size enforcement) without re-wrapping them.
4193
+ if (err instanceof AxiosError) {
4194
+ request && !err.request && (err.request = request);
4195
+ throw err;
4196
+ }
4197
+
3897
4198
  if (err && err.name === 'TypeError' && /Load failed|fetch/i.test(err.message)) {
3898
- throw Object.assign(
3899
- new AxiosError(
3900
- 'Network Error',
3901
- AxiosError.ERR_NETWORK,
3902
- config,
3903
- request,
3904
- err && err.response
3905
- ),
3906
- {
3907
- cause: err.cause || err,
3908
- }
4199
+ const networkError = new AxiosError(
4200
+ 'Network Error',
4201
+ AxiosError.ERR_NETWORK,
4202
+ config,
4203
+ request,
4204
+ err && err.response
3909
4205
  );
4206
+ // Non-enumerable to match native Error `cause` semantics so loggers
4207
+ // don't recurse into circular fetch internals (see #7205).
4208
+ Object.defineProperty(networkError, 'cause', {
4209
+ __proto__: null,
4210
+ value: err.cause || err,
4211
+ writable: true,
4212
+ enumerable: false,
4213
+ configurable: true,
4214
+ });
4215
+ throw networkError;
3910
4216
  }
3911
4217
 
3912
4218
  throw AxiosError.from(err, err && err.code, config, request, err && err.response);
@@ -4044,7 +4350,7 @@ function getAdapter(adapters, config) {
4044
4350
 
4045
4351
  throw new AxiosError(
4046
4352
  `There is no suitable adapter to dispatch the request ` + s,
4047
- 'ERR_NOT_SUPPORT'
4353
+ AxiosError.ERR_NOT_SUPPORT
4048
4354
  );
4049
4355
  }
4050
4356
 
@@ -4225,7 +4531,7 @@ validators$1.spelling = function spelling(correctSpelling) {
4225
4531
  */
4226
4532
 
4227
4533
  function assertOptions(options, schema, allowUnknown) {
4228
- if (typeof options !== 'object') {
4534
+ if (typeof options !== 'object' || options === null) {
4229
4535
  throw new AxiosError('options must be an object', AxiosError.ERR_BAD_OPTION_VALUE);
4230
4536
  }
4231
4537
  const keys = Object.keys(options);
@@ -4349,6 +4655,7 @@ class Axios {
4349
4655
  clarifyTimeoutError: validators.transitional(validators.boolean),
4350
4656
  legacyInterceptorReqResOrdering: validators.transitional(validators.boolean),
4351
4657
  advertiseZstdAcceptEncoding: validators.transitional(validators.boolean),
4658
+ validateStatusUndefinedResolves: validators.transitional(validators.boolean),
4352
4659
  },
4353
4660
  false
4354
4661
  );
@@ -4478,7 +4785,7 @@ class Axios {
4478
4785
 
4479
4786
  getUri(config) {
4480
4787
  config = mergeConfig(this.defaults, config);
4481
- const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls);
4788
+ const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls, config);
4482
4789
  return buildURL(fullPath, config.params, config.paramsSerializer);
4483
4790
  }
4484
4791
  }
@@ -4491,7 +4798,7 @@ utils$1.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoDa
4491
4798
  mergeConfig(config || {}, {
4492
4799
  method,
4493
4800
  url,
4494
- data: (config || {}).data,
4801
+ data: config && utils$1.hasOwnProp(config, 'data') ? config.data : undefined,
4495
4802
  })
4496
4803
  );
4497
4804
  };