VYPR
High severityNVD Advisory· Published Feb 9, 2026· Updated Feb 18, 2026

Axios affected by Denial of Service via __proto__ Key in mergeConfig

CVE-2026-25639

Description

Axios is a promise based HTTP client for the browser and Node.js. Prior to versions 0.30.3 and 1.13.5, the mergeConfig function in axios crashes with a TypeError when processing configuration objects containing __proto__ as an own property. An attacker can trigger this by providing a malicious configuration object created via JSON.parse(), causing complete denial of service. This vulnerability is fixed in versions 0.30.3 and 1.13.5.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
axiosnpm
>= 1.0.0, < 1.13.51.13.5
axiosnpm
< 0.30.30.30.3

Affected products

1

Patches

2
d7ff1409c681

fix: backport DOS via `__proto__` key in merge config fix to v0.x (#7388)

https://github.com/axios/axiosFelix BernhardFeb 11, 2026via ghsa
3 files changed · +234 1
  • lib/core/mergeConfig.js+4 1 modified
    @@ -94,7 +94,10 @@ module.exports = function mergeConfig(config1, config2) {
       };
     
       utils.forEach(Object.keys(config1).concat(Object.keys(config2)), function computeConfigValue(prop) {
    -    var merge = mergeMap[prop] || mergeDeepProperties;
    +    if (prop === '__proto__' || prop === 'constructor' || prop === 'prototype') {
    +      return;
    +    }
    +    var merge = utils.hasOwnProperty(mergeMap, prop) ? mergeMap[prop] : mergeDeepProperties;
         var configValue = merge(prop);
         (utils.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue);
       });
    
  • lib/utils.js+4 0 modified
    @@ -310,6 +310,10 @@ function forEach(obj, fn) {
     function merge(/* obj1, obj2, obj3, ... */) {
       var result = {};
       function assignValue(val, key) {
    +    if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
    +      return;
    +    }
    +
         if (isPlainObject(result[key]) && isPlainObject(val)) {
           result[key] = merge(result[key], val);
         } else if (isPlainObject(val)) {
    
  • test/unit/core/prototypePollution.js+226 0 added
    @@ -0,0 +1,226 @@
    +"use strict";
    +
    +var assert = require('assert');
    +var utils = require('../../../lib/utils');
    +var mergeConfig = require('../../../lib/core/mergeConfig');
    +
    +describe("Prototype Pollution Protection", function () {
    +  afterEach(function () {
    +    // Clean up any pollution that might have occurred
    +    delete Object.prototype.polluted;
    +  });
    +
    +  describe("utils.merge", function () {
    +    it("should filter __proto__ key at top level", function () {
    +      const result = utils.merge(
    +        {},
    +        { __proto__: { polluted: "yes" }, safe: "value" },
    +      );
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.safe, "value");
    +      assert.strictEqual(result.hasOwnProperty("__proto__"), false);
    +    });
    +
    +    it("should filter constructor key at top level", function () {
    +      const result = utils.merge(
    +        {},
    +        { constructor: { polluted: "yes" }, safe: "value" },
    +      );
    +
    +      assert.strictEqual(result.safe, "value");
    +      assert.strictEqual(result.hasOwnProperty("constructor"), false);
    +    });
    +
    +    it("should filter prototype key at top level", function () {
    +      const result = utils.merge(
    +        {},
    +        { prototype: { polluted: "yes" }, safe: "value" },
    +      );
    +
    +      assert.strictEqual(result.safe, "value");
    +      assert.strictEqual(result.hasOwnProperty("prototype"), false);
    +    });
    +
    +    it("should filter __proto__ key in nested objects", function () {
    +      const result = utils.merge(
    +        {},
    +        {
    +          headers: {
    +            __proto__: { polluted: "nested" },
    +            "Content-Type": "application/json",
    +          },
    +        },
    +      );
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.headers["Content-Type"], "application/json");
    +      assert.strictEqual(result.headers.hasOwnProperty("__proto__"), false);
    +    });
    +
    +    it("should filter constructor key in nested objects", function () {
    +      const result = utils.merge(
    +        {},
    +        {
    +          headers: {
    +            constructor: { prototype: { polluted: "nested" } },
    +            "Content-Type": "application/json",
    +          },
    +        },
    +      );
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.headers["Content-Type"], "application/json");
    +      assert.strictEqual(result.headers.hasOwnProperty("constructor"), false);
    +    });
    +
    +    it("should filter prototype key in nested objects", function () {
    +      const result = utils.merge(
    +        {},
    +        {
    +          headers: {
    +            prototype: { polluted: "nested" },
    +            "Content-Type": "application/json",
    +          },
    +        },
    +      );
    +
    +      assert.strictEqual(result.headers["Content-Type"], "application/json");
    +      assert.strictEqual(result.headers.hasOwnProperty("prototype"), false);
    +    });
    +
    +    it("should filter dangerous keys in deeply nested objects", function () {
    +      const result = utils.merge(
    +        {},
    +        {
    +          level1: {
    +            level2: {
    +              __proto__: { polluted: "deep" },
    +              prototype: { polluted: "deep" },
    +              safe: "value",
    +            },
    +          },
    +        },
    +      );
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.level1.level2.safe, "value");
    +      assert.strictEqual(
    +        result.level1.level2.hasOwnProperty("__proto__"),
    +        false,
    +      );
    +    });
    +
    +    it("should still merge regular properties correctly", function () {
    +      const result = utils.merge({ a: 1, b: { c: 2 } }, { b: { d: 3 }, e: 4 });
    +
    +      assert.strictEqual(result.a, 1);
    +      assert.strictEqual(result.b.c, 2);
    +      assert.strictEqual(result.b.d, 3);
    +      assert.strictEqual(result.e, 4);
    +    });
    +
    +    it("should handle JSON.parse payloads safely", function () {
    +      const malicious = JSON.parse('{"__proto__": {"polluted": "yes"}}');
    +      const result = utils.merge({}, malicious);
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.hasOwnProperty("__proto__"), false);
    +    });
    +
    +    it("should handle nested JSON.parse payloads safely", function () {
    +      const malicious = JSON.parse(
    +        '{"headers": {"constructor": {"prototype": {"polluted": "yes"}}}}',
    +      );
    +      const result = utils.merge({}, malicious);
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.headers.hasOwnProperty("constructor"), false);
    +    });
    +  });
    +
    +  describe("mergeConfig", function () {
    +    it("should filter dangerous keys at top level", function () {
    +      const result = mergeConfig(
    +        {},
    +        {
    +          __proto__: { polluted: "yes" },
    +          constructor: { polluted: "yes" },
    +          prototype: { polluted: "yes" },
    +          url: "/api/test",
    +        },
    +      );
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.url, "/api/test");
    +      assert.strictEqual(result.hasOwnProperty("__proto__"), false);
    +      assert.strictEqual(result.hasOwnProperty("constructor"), false);
    +      assert.strictEqual(result.hasOwnProperty("prototype"), false);
    +    });
    +
    +    it("should filter dangerous keys in headers", function () {
    +      const result = mergeConfig(
    +        {},
    +        {
    +          headers: {
    +            __proto__: { polluted: "yes" },
    +            "Content-Type": "application/json",
    +          },
    +        },
    +      );
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.headers["Content-Type"], "application/json");
    +      assert.strictEqual(result.headers.hasOwnProperty("__proto__"), false);
    +    });
    +
    +    it("should filter dangerous keys in custom config properties", function () {
    +      const result = mergeConfig(
    +        {},
    +        {
    +          customProp: {
    +            __proto__: { polluted: "yes" },
    +            safe: "value",
    +          },
    +        },
    +      );
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.customProp.safe, "value");
    +      assert.strictEqual(result.customProp.hasOwnProperty("__proto__"), false);
    +    });
    +
    +    it("should still merge configs correctly", function () {
    +      const config1 = {
    +        baseURL: "https://api.example.com",
    +        timeout: 1000,
    +        headers: {
    +          common: {
    +            Accept: "application/json",
    +          },
    +        },
    +      };
    +
    +      const config2 = {
    +        url: "/users",
    +        timeout: 5000,
    +        headers: {
    +          common: {
    +            "Content-Type": "application/json",
    +          },
    +        },
    +      };
    +
    +      const result = mergeConfig(config1, config2);
    +
    +      assert.strictEqual(result.baseURL, "https://api.example.com");
    +      assert.strictEqual(result.url, "/users");
    +      assert.strictEqual(result.timeout, 5000);
    +      assert.strictEqual(result.headers.common.Accept, "application/json");
    +      assert.strictEqual(
    +        result.headers.common["Content-Type"],
    +        "application/json",
    +      );
    +    });
    +  });
    +});
    
28c721588c7a

fix: Denial of Service via __proto__ Key in mergeConfig (#7369)

https://github.com/axios/axiosJayFeb 4, 2026via ghsa
3 files changed · +459 155
  • lib/core/mergeConfig.js+23 9 modified
    @@ -1,9 +1,10 @@
    -'use strict';
    +"use strict";
     
    -import utils from '../utils.js';
    +import utils from "../utils.js";
     import AxiosHeaders from "./AxiosHeaders.js";
     
    -const headersToObject = (thing) => thing instanceof AxiosHeaders ? { ...thing } : thing;
    +const headersToObject = (thing) =>
    +  thing instanceof AxiosHeaders ? { ...thing } : thing;
     
     /**
      * Config-specific merge-function which creates a new config-object
    @@ -92,14 +93,27 @@ export default function mergeConfig(config1, config2) {
         socketPath: defaultToConfig2,
         responseEncoding: defaultToConfig2,
         validateStatus: mergeDirectKeys,
    -    headers: (a, b, prop) => mergeDeepProperties(headersToObject(a), headersToObject(b), prop, true)
    +    headers: (a, b, prop) =>
    +      mergeDeepProperties(headersToObject(a), headersToObject(b), prop, true),
       };
     
    -  utils.forEach(Object.keys({ ...config1, ...config2 }), function computeConfigValue(prop) {
    -    const merge = mergeMap[prop] || mergeDeepProperties;
    -    const configValue = merge(config1[prop], config2[prop], prop);
    -    (utils.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue);
    -  });
    +  utils.forEach(
    +    Object.keys({ ...config1, ...config2 }),
    +    function computeConfigValue(prop) {
    +      if (
    +        prop === "__proto__" ||
    +        prop === "constructor" ||
    +        prop === "prototype"
    +      )
    +        return;
    +      const merge = utils.hasOwnProp(mergeMap, prop)
    +        ? mergeMap[prop]
    +        : mergeDeepProperties;
    +      const configValue = merge(config1[prop], config2[prop], prop);
    +      (utils.isUndefined(configValue) && merge !== mergeDirectKeys) ||
    +        (config[prop] = configValue);
    +    },
    +  );
     
       return config;
     }
    
  • lib/utils.js+210 146 modified
    @@ -1,24 +1,24 @@
    -'use strict';
    +"use strict";
     
    -import bind from './helpers/bind.js';
    +import bind from "./helpers/bind.js";
     
     // utils is a library of generic helper functions non-specific to axios
     
    -const {toString} = Object.prototype;
    -const {getPrototypeOf} = Object;
    -const {iterator, toStringTag} = Symbol;
    +const { toString } = Object.prototype;
    +const { getPrototypeOf } = Object;
    +const { iterator, toStringTag } = Symbol;
     
    -const kindOf = (cache => thing => {
    -    const str = toString.call(thing);
    -    return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());
    +const kindOf = ((cache) => (thing) => {
    +  const str = toString.call(thing);
    +  return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());
     })(Object.create(null));
     
     const kindOfTest = (type) => {
       type = type.toLowerCase();
    -  return (thing) => kindOf(thing) === type
    -}
    +  return (thing) => kindOf(thing) === type;
    +};
     
    -const typeOfTest = type => thing => typeof thing === type;
    +const typeOfTest = (type) => (thing) => typeof thing === type;
     
     /**
      * Determine if a value is a non-null object
    @@ -27,7 +27,7 @@ const typeOfTest = type => thing => typeof thing === type;
      *
      * @returns {boolean} True if value is an Array, otherwise false
      */
    -const {isArray} = Array;
    +const { isArray } = Array;
     
     /**
      * Determine if a value is undefined
    @@ -36,7 +36,7 @@ const {isArray} = Array;
      *
      * @returns {boolean} True if the value is undefined, otherwise false
      */
    -const isUndefined = typeOfTest('undefined');
    +const isUndefined = typeOfTest("undefined");
     
     /**
      * Determine if a value is a Buffer
    @@ -46,8 +46,14 @@ const isUndefined = typeOfTest('undefined');
      * @returns {boolean} True if value is a Buffer, otherwise false
      */
     function isBuffer(val) {
    -  return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)
    -    && isFunction(val.constructor.isBuffer) && val.constructor.isBuffer(val);
    +  return (
    +    val !== null &&
    +    !isUndefined(val) &&
    +    val.constructor !== null &&
    +    !isUndefined(val.constructor) &&
    +    isFunction(val.constructor.isBuffer) &&
    +    val.constructor.isBuffer(val)
    +  );
     }
     
     /**
    @@ -57,8 +63,7 @@ function isBuffer(val) {
      *
      * @returns {boolean} True if value is an ArrayBuffer, otherwise false
      */
    -const isArrayBuffer = kindOfTest('ArrayBuffer');
    -
    +const isArrayBuffer = kindOfTest("ArrayBuffer");
     
     /**
      * Determine if a value is a view on an ArrayBuffer
    @@ -69,10 +74,10 @@ const isArrayBuffer = kindOfTest('ArrayBuffer');
      */
     function isArrayBufferView(val) {
       let result;
    -  if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {
    +  if (typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView) {
         result = ArrayBuffer.isView(val);
       } else {
    -    result = (val) && (val.buffer) && (isArrayBuffer(val.buffer));
    +    result = val && val.buffer && isArrayBuffer(val.buffer);
       }
       return result;
     }
    @@ -84,15 +89,15 @@ function isArrayBufferView(val) {
      *
      * @returns {boolean} True if value is a String, otherwise false
      */
    -const isString = typeOfTest('string');
    +const isString = typeOfTest("string");
     
     /**
      * Determine if a value is a Function
      *
      * @param {*} val The value to test
      * @returns {boolean} True if value is a Function, otherwise false
      */
    -const isFunction = typeOfTest('function');
    +const isFunction = typeOfTest("function");
     
     /**
      * Determine if a value is a Number
    @@ -101,7 +106,7 @@ const isFunction = typeOfTest('function');
      *
      * @returns {boolean} True if value is a Number, otherwise false
      */
    -const isNumber = typeOfTest('number');
    +const isNumber = typeOfTest("number");
     
     /**
      * Determine if a value is an Object
    @@ -110,15 +115,15 @@ const isNumber = typeOfTest('number');
      *
      * @returns {boolean} True if value is an Object, otherwise false
      */
    -const isObject = (thing) => thing !== null && typeof thing === 'object';
    +const isObject = (thing) => thing !== null && typeof thing === "object";
     
     /**
      * Determine if a value is a Boolean
      *
      * @param {*} thing The value to test
      * @returns {boolean} True if value is a Boolean, otherwise false
      */
    -const isBoolean = thing => thing === true || thing === false;
    +const isBoolean = (thing) => thing === true || thing === false;
     
     /**
      * Determine if a value is a plain Object
    @@ -128,13 +133,19 @@ const isBoolean = thing => thing === true || thing === false;
      * @returns {boolean} True if value is a plain Object, otherwise false
      */
     const isPlainObject = (val) => {
    -  if (kindOf(val) !== 'object') {
    +  if (kindOf(val) !== "object") {
         return false;
       }
     
       const prototype = getPrototypeOf(val);
    -  return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(toStringTag in val) && !(iterator in val);
    -}
    +  return (
    +    (prototype === null ||
    +      prototype === Object.prototype ||
    +      Object.getPrototypeOf(prototype) === null) &&
    +    !(toStringTag in val) &&
    +    !(iterator in val)
    +  );
    +};
     
     /**
      * Determine if a value is an empty object (safely handles Buffers)
    @@ -150,12 +161,15 @@ const isEmptyObject = (val) => {
       }
     
       try {
    -    return Object.keys(val).length === 0 && Object.getPrototypeOf(val) === Object.prototype;
    +    return (
    +      Object.keys(val).length === 0 &&
    +      Object.getPrototypeOf(val) === Object.prototype
    +    );
       } catch (e) {
         // Fallback for any other objects that might cause RangeError with Object.keys()
         return false;
       }
    -}
    +};
     
     /**
      * Determine if a value is a Date
    @@ -164,7 +178,7 @@ const isEmptyObject = (val) => {
      *
      * @returns {boolean} True if value is a Date, otherwise false
      */
    -const isDate = kindOfTest('Date');
    +const isDate = kindOfTest("Date");
     
     /**
      * Determine if a value is a File
    @@ -173,7 +187,7 @@ const isDate = kindOfTest('Date');
      *
      * @returns {boolean} True if value is a File, otherwise false
      */
    -const isFile = kindOfTest('File');
    +const isFile = kindOfTest("File");
     
     /**
      * Determine if a value is a Blob
    @@ -182,7 +196,7 @@ const isFile = kindOfTest('File');
      *
      * @returns {boolean} True if value is a Blob, otherwise false
      */
    -const isBlob = kindOfTest('Blob');
    +const isBlob = kindOfTest("Blob");
     
     /**
      * Determine if a value is a FileList
    @@ -191,7 +205,7 @@ const isBlob = kindOfTest('Blob');
      *
      * @returns {boolean} True if value is a File, otherwise false
      */
    -const isFileList = kindOfTest('FileList');
    +const isFileList = kindOfTest("FileList");
     
     /**
      * Determine if a value is a Stream
    @@ -211,16 +225,17 @@ const isStream = (val) => isObject(val) && isFunction(val.pipe);
      */
     const isFormData = (thing) => {
       let kind;
    -  return thing && (
    -    (typeof FormData === 'function' && thing instanceof FormData) || (
    -      isFunction(thing.append) && (
    -        (kind = kindOf(thing)) === 'formdata' ||
    -        // detect form-data instance
    -        (kind === 'object' && isFunction(thing.toString) && thing.toString() === '[object FormData]')
    -      )
    -    )
    -  )
    -}
    +  return (
    +    thing &&
    +    ((typeof FormData === "function" && thing instanceof FormData) ||
    +      (isFunction(thing.append) &&
    +        ((kind = kindOf(thing)) === "formdata" ||
    +          // detect form-data instance
    +          (kind === "object" &&
    +            isFunction(thing.toString) &&
    +            thing.toString() === "[object FormData]"))))
    +  );
    +};
     
     /**
      * Determine if a value is a URLSearchParams object
    @@ -229,9 +244,14 @@ const isFormData = (thing) => {
      *
      * @returns {boolean} True if value is a URLSearchParams object, otherwise false
      */
    -const isURLSearchParams = kindOfTest('URLSearchParams');
    +const isURLSearchParams = kindOfTest("URLSearchParams");
     
    -const [isReadableStream, isRequest, isResponse, isHeaders] = ['ReadableStream', 'Request', 'Response', 'Headers'].map(kindOfTest);
    +const [isReadableStream, isRequest, isResponse, isHeaders] = [
    +  "ReadableStream",
    +  "Request",
    +  "Response",
    +  "Headers",
    +].map(kindOfTest);
     
     /**
      * Trim excess whitespace off the beginning and end of a string
    @@ -240,8 +260,8 @@ const [isReadableStream, isRequest, isResponse, isHeaders] = ['ReadableStream',
      *
      * @returns {String} The String freed of excess whitespace
      */
    -const trim = (str) => str.trim ?
    -  str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
    +const trim = (str) =>
    +  str.trim ? str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "");
     
     /**
      * Iterate over an Array or an Object invoking a function for each item.
    @@ -259,17 +279,17 @@ const trim = (str) => str.trim ?
      * @param {Boolean} [options.allOwnKeys = false]
      * @returns {any}
      */
    -function forEach(obj, fn, {allOwnKeys = false} = {}) {
    +function forEach(obj, fn, { allOwnKeys = false } = {}) {
       // Don't bother if no value provided
    -  if (obj === null || typeof obj === 'undefined') {
    +  if (obj === null || typeof obj === "undefined") {
         return;
       }
     
       let i;
       let l;
     
       // Force an array if not already something iterable
    -  if (typeof obj !== 'object') {
    +  if (typeof obj !== "object") {
         /*eslint no-param-reassign:0*/
         obj = [obj];
       }
    @@ -286,7 +306,9 @@ function forEach(obj, fn, {allOwnKeys = false} = {}) {
         }
     
         // Iterate over object keys
    -    const keys = allOwnKeys ? Object.getOwnPropertyNames(obj) : Object.keys(obj);
    +    const keys = allOwnKeys
    +      ? Object.getOwnPropertyNames(obj)
    +      : Object.keys(obj);
         const len = keys.length;
         let key;
     
    @@ -298,7 +320,7 @@ function forEach(obj, fn, {allOwnKeys = false} = {}) {
     }
     
     function findKey(obj, key) {
    -  if (isBuffer(obj)){
    +  if (isBuffer(obj)) {
         return null;
       }
     
    @@ -318,10 +340,15 @@ function findKey(obj, key) {
     const _global = (() => {
       /*eslint no-undef:0*/
       if (typeof globalThis !== "undefined") return globalThis;
    -  return typeof self !== "undefined" ? self : (typeof window !== 'undefined' ? window : global)
    +  return typeof self !== "undefined"
    +    ? self
    +    : typeof window !== "undefined"
    +      ? window
    +      : global;
     })();
     
    -const isContextDefined = (context) => !isUndefined(context) && context !== _global;
    +const isContextDefined = (context) =>
    +  !isUndefined(context) && context !== _global;
     
     /**
      * Accepts varargs expecting each argument to be an object, then
    @@ -342,10 +369,15 @@ const isContextDefined = (context) => !isUndefined(context) && context !== _glob
      * @returns {Object} Result of all merge properties
      */
     function merge(/* obj1, obj2, obj3, ... */) {
    -  const {caseless, skipUndefined} = isContextDefined(this) && this || {};
    +  const { caseless, skipUndefined } = (isContextDefined(this) && this) || {};
       const result = {};
       const assignValue = (val, key) => {
    -    const targetKey = caseless && findKey(result, key) || key;
    +    // Skip dangerous property names to prevent prototype pollution
    +    if (key === "__proto__" || key === "constructor" || key === "prototype") {
    +      return;
    +    }
    +
    +    const targetKey = (caseless && findKey(result, key)) || key;
         if (isPlainObject(result[targetKey]) && isPlainObject(val)) {
           result[targetKey] = merge(result[targetKey], val);
         } else if (isPlainObject(val)) {
    @@ -355,7 +387,7 @@ function merge(/* obj1, obj2, obj3, ... */) {
         } else if (!skipUndefined || !isUndefined(val)) {
           result[targetKey] = val;
         }
    -  }
    +  };
     
       for (let i = 0, l = arguments.length; i < l; i++) {
         arguments[i] && forEach(arguments[i], assignValue);
    @@ -374,26 +406,30 @@ function merge(/* obj1, obj2, obj3, ... */) {
      * @param {Boolean} [options.allOwnKeys]
      * @returns {Object} The resulting value of object a
      */
    -const extend = (a, b, thisArg, {allOwnKeys}= {}) => {
    -  forEach(b, (val, key) => {
    -    if (thisArg && isFunction(val)) {
    -      Object.defineProperty(a, key, {
    -        value: bind(val, thisArg),
    -        writable: true,
    -        enumerable: true,
    -        configurable: true
    -      });
    -    } else {
    -      Object.defineProperty(a, key, {
    -        value: val,
    -        writable: true,
    -        enumerable: true,
    -        configurable: true
    -      });
    -    }
    -  }, {allOwnKeys});
    +const extend = (a, b, thisArg, { allOwnKeys } = {}) => {
    +  forEach(
    +    b,
    +    (val, key) => {
    +      if (thisArg && isFunction(val)) {
    +        Object.defineProperty(a, key, {
    +          value: bind(val, thisArg),
    +          writable: true,
    +          enumerable: true,
    +          configurable: true,
    +        });
    +      } else {
    +        Object.defineProperty(a, key, {
    +          value: val,
    +          writable: true,
    +          enumerable: true,
    +          configurable: true,
    +        });
    +      }
    +    },
    +    { allOwnKeys },
    +  );
       return a;
    -}
    +};
     
     /**
      * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
    @@ -403,11 +439,11 @@ const extend = (a, b, thisArg, {allOwnKeys}= {}) => {
      * @returns {string} content value without BOM
      */
     const stripBOM = (content) => {
    -  if (content.charCodeAt(0) === 0xFEFF) {
    +  if (content.charCodeAt(0) === 0xfeff) {
         content = content.slice(1);
       }
       return content;
    -}
    +};
     
     /**
      * Inherit the prototype methods from one constructor into another
    @@ -419,18 +455,21 @@ const stripBOM = (content) => {
      * @returns {void}
      */
     const inherits = (constructor, superConstructor, props, descriptors) => {
    -  constructor.prototype = Object.create(superConstructor.prototype, descriptors);
    -  Object.defineProperty(constructor.prototype, 'constructor', {
    +  constructor.prototype = Object.create(
    +    superConstructor.prototype,
    +    descriptors,
    +  );
    +  Object.defineProperty(constructor.prototype, "constructor", {
         value: constructor,
         writable: true,
         enumerable: false,
    -    configurable: true
    +    configurable: true,
       });
    -  Object.defineProperty(constructor, 'super', {
    -    value: superConstructor.prototype
    +  Object.defineProperty(constructor, "super", {
    +    value: superConstructor.prototype,
       });
       props && Object.assign(constructor.prototype, props);
    -}
    +};
     
     /**
      * Resolve object with deep prototype chain to a flat object
    @@ -456,16 +495,23 @@ const toFlatObject = (sourceObj, destObj, filter, propFilter) => {
         i = props.length;
         while (i-- > 0) {
           prop = props[i];
    -      if ((!propFilter || propFilter(prop, sourceObj, destObj)) && !merged[prop]) {
    +      if (
    +        (!propFilter || propFilter(prop, sourceObj, destObj)) &&
    +        !merged[prop]
    +      ) {
             destObj[prop] = sourceObj[prop];
             merged[prop] = true;
           }
         }
         sourceObj = filter !== false && getPrototypeOf(sourceObj);
    -  } while (sourceObj && (!filter || filter(sourceObj, destObj)) && sourceObj !== Object.prototype);
    +  } while (
    +    sourceObj &&
    +    (!filter || filter(sourceObj, destObj)) &&
    +    sourceObj !== Object.prototype
    +  );
     
       return destObj;
    -}
    +};
     
     /**
      * Determines whether a string ends with the characters of a specified string
    @@ -484,8 +530,7 @@ const endsWith = (str, searchString, position) => {
       position -= searchString.length;
       const lastIndex = str.indexOf(searchString, position);
       return lastIndex !== -1 && lastIndex === position;
    -}
    -
    +};
     
     /**
      * Returns new array from array like object or null if failed
    @@ -504,7 +549,7 @@ const toArray = (thing) => {
         arr[i] = thing[i];
       }
       return arr;
    -}
    +};
     
     /**
      * Checking if the Uint8Array exists and if it does, it returns a function that checks if the
    @@ -515,12 +560,12 @@ const toArray = (thing) => {
      * @returns {Array}
      */
     // eslint-disable-next-line func-names
    -const isTypedArray = (TypedArray => {
    +const isTypedArray = ((TypedArray) => {
       // eslint-disable-next-line func-names
    -  return thing => {
    +  return (thing) => {
         return TypedArray && thing instanceof TypedArray;
       };
    -})(typeof Uint8Array !== 'undefined' && getPrototypeOf(Uint8Array));
    +})(typeof Uint8Array !== "undefined" && getPrototypeOf(Uint8Array));
     
     /**
      * For each entry in the object, call the function with the key and value.
    @@ -541,7 +586,7 @@ const forEachEntry = (obj, fn) => {
         const pair = result.value;
         fn.call(obj, pair[0], pair[1]);
       }
    -}
    +};
     
     /**
      * It takes a regular expression and a string, and returns an array of all the matches
    @@ -560,21 +605,25 @@ const matchAll = (regExp, str) => {
       }
     
       return arr;
    -}
    +};
     
     /* Checking if the kindOfTest function returns true when passed an HTMLFormElement. */
    -const isHTMLForm = kindOfTest('HTMLFormElement');
    +const isHTMLForm = kindOfTest("HTMLFormElement");
     
    -const toCamelCase = str => {
    -  return str.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,
    -    function replacer(m, p1, p2) {
    +const toCamelCase = (str) => {
    +  return str
    +    .toLowerCase()
    +    .replace(/[-_\s]([a-z\d])(\w*)/g, function replacer(m, p1, p2) {
           return p1.toUpperCase() + p2;
    -    }
    -  );
    +    });
     };
     
     /* Creating a function that will check if an object has a property. */
    -const hasOwnProperty = (({hasOwnProperty}) => (obj, prop) => hasOwnProperty.call(obj, prop))(Object.prototype);
    +const hasOwnProperty = (
    +  ({ hasOwnProperty }) =>
    +  (obj, prop) =>
    +    hasOwnProperty.call(obj, prop)
    +)(Object.prototype);
     
     /**
      * Determine if a value is a RegExp object
    @@ -583,7 +632,7 @@ const hasOwnProperty = (({hasOwnProperty}) => (obj, prop) => hasOwnProperty.call
      *
      * @returns {boolean} True if value is a RegExp object, otherwise false
      */
    -const isRegExp = kindOfTest('RegExp');
    +const isRegExp = kindOfTest("RegExp");
     
     const reduceDescriptors = (obj, reducer) => {
       const descriptors = Object.getOwnPropertyDescriptors(obj);
    @@ -597,7 +646,7 @@ const reduceDescriptors = (obj, reducer) => {
       });
     
       Object.defineProperties(obj, reducedDescriptors);
    -}
    +};
     
     /**
      * Makes all methods read-only
    @@ -607,7 +656,10 @@ const reduceDescriptors = (obj, reducer) => {
     const freezeMethods = (obj) => {
       reduceDescriptors(obj, (descriptor, name) => {
         // skip restricted props in strict mode
    -    if (isFunction(obj) && ['arguments', 'caller', 'callee'].indexOf(name) !== -1) {
    +    if (
    +      isFunction(obj) &&
    +      ["arguments", "caller", "callee"].indexOf(name) !== -1
    +    ) {
           return false;
         }
     
    @@ -617,40 +669,42 @@ const freezeMethods = (obj) => {
     
         descriptor.enumerable = false;
     
    -    if ('writable' in descriptor) {
    +    if ("writable" in descriptor) {
           descriptor.writable = false;
           return;
         }
     
         if (!descriptor.set) {
           descriptor.set = () => {
    -        throw Error('Can not rewrite read-only method \'' + name + '\'');
    +        throw Error("Can not rewrite read-only method '" + name + "'");
           };
         }
       });
    -}
    +};
     
     const toObjectSet = (arrayOrString, delimiter) => {
       const obj = {};
     
       const define = (arr) => {
    -    arr.forEach(value => {
    +    arr.forEach((value) => {
           obj[value] = true;
         });
    -  }
    +  };
     
    -  isArray(arrayOrString) ? define(arrayOrString) : define(String(arrayOrString).split(delimiter));
    +  isArray(arrayOrString)
    +    ? define(arrayOrString)
    +    : define(String(arrayOrString).split(delimiter));
     
       return obj;
    -}
    +};
     
    -const noop = () => {}
    +const noop = () => {};
     
     const toFiniteNumber = (value, defaultValue) => {
    -  return value != null && Number.isFinite(value = +value) ? value : defaultValue;
    -}
    -
    -
    +  return value != null && Number.isFinite((value = +value))
    +    ? value
    +    : defaultValue;
    +};
     
     /**
      * If the thing is a FormData object, return true, otherwise return false.
    @@ -660,14 +714,18 @@ const toFiniteNumber = (value, defaultValue) => {
      * @returns {boolean}
      */
     function isSpecCompliantForm(thing) {
    -  return !!(thing && isFunction(thing.append) && thing[toStringTag] === 'FormData' && thing[iterator]);
    +  return !!(
    +    thing &&
    +    isFunction(thing.append) &&
    +    thing[toStringTag] === "FormData" &&
    +    thing[iterator]
    +  );
     }
     
     const toJSONObject = (obj) => {
       const stack = new Array(10);
     
       const visit = (source, i) => {
    -
         if (isObject(source)) {
           if (stack.indexOf(source) >= 0) {
             return;
    @@ -678,7 +736,7 @@ const toJSONObject = (obj) => {
             return source;
           }
     
    -      if(!('toJSON' in source)) {
    +      if (!("toJSON" in source)) {
             stack[i] = source;
             const target = isArray(source) ? [] : {};
     
    @@ -694,15 +752,18 @@ const toJSONObject = (obj) => {
         }
     
         return source;
    -  }
    +  };
     
       return visit(obj, 0);
    -}
    +};
     
    -const isAsyncFn = kindOfTest('AsyncFunction');
    +const isAsyncFn = kindOfTest("AsyncFunction");
     
     const isThenable = (thing) =>
    -  thing && (isObject(thing) || isFunction(thing)) && isFunction(thing.then) && isFunction(thing.catch);
    +  thing &&
    +  (isObject(thing) || isFunction(thing)) &&
    +  isFunction(thing.then) &&
    +  isFunction(thing.catch);
     
     // original code
     // https://github.com/DigitalBrainJS/AxiosPromise/blob/16deab13710ec09779922131f3fa5954320f83ab/lib/utils.js#L11-L34
    @@ -712,32 +773,35 @@ const _setImmediate = ((setImmediateSupported, postMessageSupported) => {
         return setImmediate;
       }
     
    -  return postMessageSupported ? ((token, callbacks) => {
    -    _global.addEventListener("message", ({source, data}) => {
    -      if (source === _global && data === token) {
    -        callbacks.length && callbacks.shift()();
    -      }
    -    }, false);
    -
    -    return (cb) => {
    -      callbacks.push(cb);
    -      _global.postMessage(token, "*");
    -    }
    -  })(`axios@${Math.random()}`, []) : (cb) => setTimeout(cb);
    -})(
    -  typeof setImmediate === 'function',
    -  isFunction(_global.postMessage)
    -);
    -
    -const asap = typeof queueMicrotask !== 'undefined' ?
    -  queueMicrotask.bind(_global) : ( typeof process !== 'undefined' && process.nextTick || _setImmediate);
    +  return postMessageSupported
    +    ? ((token, callbacks) => {
    +        _global.addEventListener(
    +          "message",
    +          ({ source, data }) => {
    +            if (source === _global && data === token) {
    +              callbacks.length && callbacks.shift()();
    +            }
    +          },
    +          false,
    +        );
    +
    +        return (cb) => {
    +          callbacks.push(cb);
    +          _global.postMessage(token, "*");
    +        };
    +      })(`axios@${Math.random()}`, [])
    +    : (cb) => setTimeout(cb);
    +})(typeof setImmediate === "function", isFunction(_global.postMessage));
    +
    +const asap =
    +  typeof queueMicrotask !== "undefined"
    +    ? queueMicrotask.bind(_global)
    +    : (typeof process !== "undefined" && process.nextTick) || _setImmediate;
     
     // *********************
     
    -
     const isIterable = (thing) => thing != null && isFunction(thing[iterator]);
     
    -
     export default {
       isArray,
       isArrayBuffer,
    @@ -795,5 +859,5 @@ export default {
       isThenable,
       setImmediate: _setImmediate,
       asap,
    -  isIterable
    +  isIterable,
     };
    
  • test/unit/core/prototypePollution.js+226 0 added
    @@ -0,0 +1,226 @@
    +"use strict";
    +
    +import assert from "assert";
    +import utils from "../../../lib/utils.js";
    +import mergeConfig from "../../../lib/core/mergeConfig.js";
    +
    +describe("Prototype Pollution Protection", function () {
    +  afterEach(function () {
    +    // Clean up any pollution that might have occurred
    +    delete Object.prototype.polluted;
    +  });
    +
    +  describe("utils.merge", function () {
    +    it("should filter __proto__ key at top level", function () {
    +      const result = utils.merge(
    +        {},
    +        { __proto__: { polluted: "yes" }, safe: "value" },
    +      );
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.safe, "value");
    +      assert.strictEqual(result.hasOwnProperty("__proto__"), false);
    +    });
    +
    +    it("should filter constructor key at top level", function () {
    +      const result = utils.merge(
    +        {},
    +        { constructor: { polluted: "yes" }, safe: "value" },
    +      );
    +
    +      assert.strictEqual(result.safe, "value");
    +      assert.strictEqual(result.hasOwnProperty("constructor"), false);
    +    });
    +
    +    it("should filter prototype key at top level", function () {
    +      const result = utils.merge(
    +        {},
    +        { prototype: { polluted: "yes" }, safe: "value" },
    +      );
    +
    +      assert.strictEqual(result.safe, "value");
    +      assert.strictEqual(result.hasOwnProperty("prototype"), false);
    +    });
    +
    +    it("should filter __proto__ key in nested objects", function () {
    +      const result = utils.merge(
    +        {},
    +        {
    +          headers: {
    +            __proto__: { polluted: "nested" },
    +            "Content-Type": "application/json",
    +          },
    +        },
    +      );
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.headers["Content-Type"], "application/json");
    +      assert.strictEqual(result.headers.hasOwnProperty("__proto__"), false);
    +    });
    +
    +    it("should filter constructor key in nested objects", function () {
    +      const result = utils.merge(
    +        {},
    +        {
    +          headers: {
    +            constructor: { prototype: { polluted: "nested" } },
    +            "Content-Type": "application/json",
    +          },
    +        },
    +      );
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.headers["Content-Type"], "application/json");
    +      assert.strictEqual(result.headers.hasOwnProperty("constructor"), false);
    +    });
    +
    +    it("should filter prototype key in nested objects", function () {
    +      const result = utils.merge(
    +        {},
    +        {
    +          headers: {
    +            prototype: { polluted: "nested" },
    +            "Content-Type": "application/json",
    +          },
    +        },
    +      );
    +
    +      assert.strictEqual(result.headers["Content-Type"], "application/json");
    +      assert.strictEqual(result.headers.hasOwnProperty("prototype"), false);
    +    });
    +
    +    it("should filter dangerous keys in deeply nested objects", function () {
    +      const result = utils.merge(
    +        {},
    +        {
    +          level1: {
    +            level2: {
    +              __proto__: { polluted: "deep" },
    +              prototype: { polluted: "deep" },
    +              safe: "value",
    +            },
    +          },
    +        },
    +      );
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.level1.level2.safe, "value");
    +      assert.strictEqual(
    +        result.level1.level2.hasOwnProperty("__proto__"),
    +        false,
    +      );
    +    });
    +
    +    it("should still merge regular properties correctly", function () {
    +      const result = utils.merge({ a: 1, b: { c: 2 } }, { b: { d: 3 }, e: 4 });
    +
    +      assert.strictEqual(result.a, 1);
    +      assert.strictEqual(result.b.c, 2);
    +      assert.strictEqual(result.b.d, 3);
    +      assert.strictEqual(result.e, 4);
    +    });
    +
    +    it("should handle JSON.parse payloads safely", function () {
    +      const malicious = JSON.parse('{"__proto__": {"polluted": "yes"}}');
    +      const result = utils.merge({}, malicious);
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.hasOwnProperty("__proto__"), false);
    +    });
    +
    +    it("should handle nested JSON.parse payloads safely", function () {
    +      const malicious = JSON.parse(
    +        '{"headers": {"constructor": {"prototype": {"polluted": "yes"}}}}',
    +      );
    +      const result = utils.merge({}, malicious);
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.headers.hasOwnProperty("constructor"), false);
    +    });
    +  });
    +
    +  describe("mergeConfig", function () {
    +    it("should filter dangerous keys at top level", function () {
    +      const result = mergeConfig(
    +        {},
    +        {
    +          __proto__: { polluted: "yes" },
    +          constructor: { polluted: "yes" },
    +          prototype: { polluted: "yes" },
    +          url: "/api/test",
    +        },
    +      );
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.url, "/api/test");
    +      assert.strictEqual(result.hasOwnProperty("__proto__"), false);
    +      assert.strictEqual(result.hasOwnProperty("constructor"), false);
    +      assert.strictEqual(result.hasOwnProperty("prototype"), false);
    +    });
    +
    +    it("should filter dangerous keys in headers", function () {
    +      const result = mergeConfig(
    +        {},
    +        {
    +          headers: {
    +            __proto__: { polluted: "yes" },
    +            "Content-Type": "application/json",
    +          },
    +        },
    +      );
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.headers["Content-Type"], "application/json");
    +      assert.strictEqual(result.headers.hasOwnProperty("__proto__"), false);
    +    });
    +
    +    it("should filter dangerous keys in custom config properties", function () {
    +      const result = mergeConfig(
    +        {},
    +        {
    +          customProp: {
    +            __proto__: { polluted: "yes" },
    +            safe: "value",
    +          },
    +        },
    +      );
    +
    +      assert.strictEqual(Object.prototype.polluted, undefined);
    +      assert.strictEqual(result.customProp.safe, "value");
    +      assert.strictEqual(result.customProp.hasOwnProperty("__proto__"), false);
    +    });
    +
    +    it("should still merge configs correctly", function () {
    +      const config1 = {
    +        baseURL: "https://api.example.com",
    +        timeout: 1000,
    +        headers: {
    +          common: {
    +            Accept: "application/json",
    +          },
    +        },
    +      };
    +
    +      const config2 = {
    +        url: "/users",
    +        timeout: 5000,
    +        headers: {
    +          common: {
    +            "Content-Type": "application/json",
    +          },
    +        },
    +      };
    +
    +      const result = mergeConfig(config1, config2);
    +
    +      assert.strictEqual(result.baseURL, "https://api.example.com");
    +      assert.strictEqual(result.url, "/users");
    +      assert.strictEqual(result.timeout, 5000);
    +      assert.strictEqual(result.headers.common.Accept, "application/json");
    +      assert.strictEqual(
    +        result.headers.common["Content-Type"],
    +        "application/json",
    +      );
    +    });
    +  });
    +});
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

9

News mentions

0

No linked articles in our index yet.