{
  "id": "1784388139396-8150cd4f",
  "repositoryName": "axios-9d2abce4",
  "repository": "/Users/teja/Documents/Codex/2026-07-17/build/.greenhorn/sources/axios-9d2abce4",
  "source": {
    "input": "https://github.com/axios/axios.git",
    "url": "https://github.com/axios/axios.git",
    "revision": "a092bae50d1884782151b2fcea12974d6da6e376"
  },
  "startedAt": "2026-07-18T15:22:19.396Z",
  "outcome": "DEAD END",
  "ttfgb": "DEAD END",
  "runtime": "docker",
  "transport": "suggestion",
  "enforcer": "gpt",
  "isolation": "Ubuntu 24.04 container, new filesystem state, source copied inside at run start. Codex reasons in a separate empty host scratch directory; the Azure GPT-5.6 key stays on the host. Only accepted commands reach the container shell.",
  "documentation": {
    "root": "/Users/teja/Documents/Codex/2026-07-17/build/.greenhorn/sources/axios-9d2abce4",
    "docs": [
      {
        "file": "README.md",
        "absolutePath": "/Users/teja/Documents/Codex/2026-07-17/build/.greenhorn/sources/axios-9d2abce4/README.md",
        "origin": "local",
        "text": "<h3 align=\"center\">💎 Platinum sponsors <br /></h3>\n<table align=\"center\">\n    <tr>\n        <td align=\"center\" width=\"50%\">\n            <a\n                href=\"https://thanks.dev/?utm_source&#x3D;axios&amp;utm_medium&#x3D;sponsorlist&amp;utm_campaign&#x3D;sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"90px\"\n                    height=\"90px\"\n                    src=\"https://images.opencollective.com/thanks-dev/360b917/logo/256.png?height=256\"\n                    alt=\"Thanks.dev\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                We're passionate about making open source sustainable. Scan your dependency tree to better understand which open source projects need funding.\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://thanks.dev/?utm_source&#x3D;axios&amp;utm_medium&#x3D;readme_sponsorlist&amp;utm_campaign&#x3D;sponsorship\"\n                    target=\"_blank\"\n                    ><b>thanks.dev</b></a\n                >\n            </p>\n        </td>\n        <td align=\"center\" width=\"50%\">\n            <a\n                href=\"https://opencollective.com/axios/contribute\"\n                target=\"_blank\"\n                >💜 Become a sponsor</a\n            >\n        </td>\n    </tr>\n</table>\n<table align=\"center\">\n    <tr>\n        <td align=\"center\" width=\"50%\">\n            <a\n                href=\"https://opencollective.com/axios/contribute\"\n                target=\"_blank\"\n                >💜 Become a sponsor</a\n            >\n        </td>\n        <td align=\"center\" width=\"50%\">\n            <a\n                href=\"https://opencollective.com/axios/contribute\"\n                target=\"_blank\"\n                >💜 Become a sponsor</a\n            >\n        </td>\n    </tr>\n</table>\n<h3 align=\"center\">🥇 Gold sponsors <br /></h3>\n<table align=\"center\" width=\"100%\">\n    <tr width=\"33.333333333333336%\">\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://www.principal.com/about-us?utm_source&#x3D;axios&amp;utm_medium&#x3D;sponsorlist&amp;utm_campaign&#x3D;sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"90px\"\n                    height=\"90px\"\n                    src=\"https://images.opencollective.com/principal/431e690/logo.png\"\n                    alt=\"Principal Financial Group\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                Free tools to help with your financial planning needs!\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://www.principal.com/about-us?utm_source&#x3D;axios&amp;utm_medium&#x3D;readme_sponsorlist&amp;utm_campaign&#x3D;sponsorship\"\n                    target=\"_blank\"\n                    ><b>principal.com</b></a\n                >\n            </p>\n        </td>\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://opensource.sap.com?utm_source&#x3D;axios&amp;utm_medium&#x3D;sponsorlist&amp;utm_campaign&#x3D;sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"90px\"\n                    height=\"90px\"\n                    src=\"https://avatars.githubusercontent.com/u/2531208?s=200&v=4\"\n                    alt=\"SAP\"\n                />\n            </a>\n            <p\n                align=\"center\"\n                title=\"SAP SE, a global software company, is one of the largest vendors of ERP and other enterprise applications.\"\n            >\n                BSAP SE, a global software company, is one of the largest vendors of ERP and other enterprise applications.\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://opensource.sap.com?utm_source&#x3D;axios&amp;utm_medium&#x3D;readme_sponsorlist&amp;utm_campaign&#x3D;sponsorship\"\n                    target=\"_blank\"\n                    ><b>opensource.sap.com</b></a\n                >\n            </p>\n        </td>\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://www.descope.com/?utm_source&#x3D;axios&amp;utm_medium&#x3D;referral&amp;utm_campaign&#x3D;axios-oss-sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n               <img\n                    width=\"90px\"\n                    height=\"90px\"\n                    src=\"https://images.opencollective.com/descope/b53243e/logo.png\"\n                    alt=\"Descope\"\n                />\n            </a>\n            <p\n                align=\"center\"\n                title=\"Hi, we&#x27;re Descope! We are building something in the authentication space for app developers and can't wait to place it in your hands.\"\n            >\n                Reduce user friction, prevent account takeover, and get a 360° view of your customer and agentic identities with the Descope External IAM platform.\n            </p>\n              <p align=\"center\">\n                   <a\n                       href=\"https://www.descope.com/?utm_source&#x3D;axios&amp;utm_medium&#x3D;referral&amp;utm_campaign&#x3D;axios-oss-sponsorship\"\n                       target=\"_blank\"\n                       ><b>descope.com</b></a\n                   >\n              </p>\n        </td>\n    </tr>\n    <tr width=\"33.333333333333336%\">\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://stytch.com/\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n               <img\n                    width=\"90px\"\n                    height=\"90px\"\n                    src=\"https://images.opencollective.com/stytch/f84ce43/logo/256.png?height=256\"\n                    alt=\"Stytch\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                The identity platform for humans & AI agents\n            </p>\n            <p align=\"center\">\n                   <a\n                       href=\"https://stytch.com\"\n                       target=\"_blank\"\n                       ><b>stytch.com</b></a\n                   >\n              </p>\n        </td>\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://rxdb.info/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship&utm_content=logo\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"90px\"\n                    height=\"90px\"\n                    src=\"https://rxdb.info/files/logo/logo_text_white.svg\"\n                    alt=\"RxDB\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                RxDB is a NoSQL database for JavaScript that runs directly in your app.\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://rxdb.info/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship&utm_content=logo\"\n                    target=\"_blank\"\n                    ><b>rxdb.info</b></a\n                >\n            </p>\n        </td>\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://poprey.com/?utm_source&#x3D;axios&amp;utm_medium&#x3D;sponsorlist&amp;utm_campaign&#x3D;sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"70px\"\n                    height=\"70px\"\n                    src=\"https://images.opencollective.com/instagram-likes/2a72a03/avatar.png\"\n                    alt=\"Poprey\"\n                />\n            </a>\n            <p align=\"center\">\n                Buy Instagram Likes\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://poprey.com/?utm_source&#x3D;axios&amp;utm_medium&#x3D;readme_sponsorlist&amp;utm_campaign&#x3D;sponsorship\"\n                    target=\"_blank\"\n                    ><b>poprey.com</b></a\n                >\n            </p>\n        </td>\n    </tr>\n    <tr width=\"33.333333333333336%\">\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://buzzoid.com/buy-instagram-followers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"71px\"\n                    height=\"70px\"\n                    src=\"https://images.opencollective.com/buzzoid-buy-instagram-followers/56a09fe/logo.png\"\n                    alt=\"Buzzoid - Buy Instagram Followers\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                At Buzzoid, you can buy Instagram followers through a short checkout flow with safety controls. Rated world&#39;s #1 IG service since 2012.\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://buzzoid.com/buy-instagram-followers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                    target=\"_blank\"\n                    ><b>buzzoid.com</b></a\n                >\n            </p>\n        </td>\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://twicsy.com/buy-instagram-followers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"71px\"\n                    height=\"70px\"\n                    src=\"https://images.opencollective.com/buy-instagram-followers-twicsy/b4c5d7f/logo/256.png?height=256\"\n                    alt=\"Buy Instagram Followers Twicsy\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                Buy real Instagram followers from Twicsy. Twicsy has been voted the best site to buy followers from the likes of US Magazine.\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://twicsy.com/buy-instagram-followers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                    target=\"_blank\"\n                    ><b>twicsy.com</b></a\n                >\n            </p>\n        </td>\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://global.fun88.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"71px\"\n                    height=\"70px\"\n                    src=\"https://images.opencollective.com/fun88-official/bf2843c/logo.png\"\n                    alt=\"Fun 88\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                Fun88 is a global online gambling and betting brand founded in 2009, offering a wide range of services including sports betting, live casino games, slots, and virtual gaming.\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://global.fun88.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                    target=\"_blank\"\n                    ><b>global.fun88.com</b></a\n                >\n            </p>\n        </td>\n    </tr>\n    <tr width=\"33.333333333333336%\">\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://www.jbo88b.com/vn/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"71px\"\n                    height=\"70px\"\n                    src=\"https://images.opencollective.com/jbo-vietnam/3fc6159/avatar.png\"\n                    alt=\"JBO Vietnam\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                JBO Vietnam is a prominent online entertainment brand in Vietnam, offering sports betting, esports, online casino games, and a wide range of other exciting games.\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://www.jbo88b.com/vn/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                    target=\"_blank\"\n                    ><b>jbo88b.com</b></a\n                >\n            </p>\n        </td>\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://www.jbo579.com/th/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"71px\"\n                    height=\"70px\"\n                    src=\"https://images.opencollective.com/jbo-thailand/d17e84f/avatar.png\"\n                    alt=\"JBO Thailand\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                JBO Thailand is a prominent online entertainment brand in Thailand, offering sports betting, esports, online casino games, and a wide range of other exciting games.\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://www.jbo579.com/th/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                    target=\"_blank\"\n                    ><b>jbo88b.com</b></a\n                >\n            </p>\n        </td>\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://opencollective.com/axios/contribute\"\n                target=\"_blank\"\n                >💜 Become a sponsor</a\n            >\n        </td>\n    </tr>\n</table>\n\n<!--<div>marker</div>-->\n\n<br><br>\n\n<div align=\"center\">\n   <a href=\"https://axios.rest\"><img src=\"https://axios.rest/logo.svg\" alt=\"Axios\" /></a><br>\n</div>\n\n<p align=\"center\">Promise based HTTP client for the browser and node.js</p>\n\n<p align=\"center\">\n    <a href=\"https://axios.rest/\"><b>Website</b></a> •\n    <a href=\"https://axios.rest/pages/getting-started/first-steps.html\"><b>Documentation</b></a>\n</p>\n\n<div align=\"center\">\n\n[![npm version](https://img.shields.io/npm/v/axios.svg?style=flat-square)](https://www.npmjs.org/package/axios)\n[![Build status](https://img.shields.io/github/actions/workflow/status/axios/axios/ci.yml?branch=v1.x&label=CI&logo=github&style=flat-square)](https://github.com/axios/axios/actions/workflows/ci.yml)\n[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod&style=flat-square)](https://gitpod.io/#https://github.com/axios/axios)\n[![install size](https://img.shields.io/badge/dynamic/json?url=https://packagephobia.com/v2/api.json?p=axios&query=$.install.pretty&label=install%20size&style=flat-square)](https://packagephobia.now.sh/result?p=axios)\n[![npm bundle size](https://img.shields.io/bundlephobia/minzip/axios?style=flat-square)](https://bundlephobia.com/package/axios@latest)\n[![npm downloads](https://img.shields.io/npm/dm/axios.svg?style=flat-square)](https://npm-stat.com/charts.html?package=axios)\n[![gitter chat](https://img.shields.io/gitter/room/mzabriskie/axios.svg?style=flat-square)](https://gitter.im/mzabriskie/axios)\n[![code helpers](https://www.codetriage.com/axios/axios/badges/users.svg)](https://www.codetriage.com/axios/axios)\n[![Contributors](https://img.shields.io/github/contributors/axios/axios.svg?style=flat-square)](CONTRIBUTORS.md)\n[![Agent Friendly](https://agentfriendlycode.com/api/badge/github/axios/axios.svg)](https://agentfriendlycode.com/repo/32)\n\n</div>\n\n## Table of contents\n\n- [Features](#features)\n- [Browser support](#browser-support)\n- [Installing](#installing)\n  - [Package manager](#package-manager)\n  - [CDN](#cdn)\n- [Example](#example)\n- [Axios API](#axios-api)\n- [Request method aliases](#request-method-aliases)\n- [Concurrency](#concurrency-deprecated)\n- [Creating an instance](#creating-an-instance)\n- [Instance methods](#instance-methods)\n- [Request config](#request-config)\n- [Response schema](#response-schema)\n- [Config defaults](#config-defaults)\n  - [Global axios defaults](#global-axios-defaults)\n  - [Custom instance defaults](#custom-instance-defaults)\n  - [Config order of precedence](#config-order-of-precedence)\n- [Interceptors](#interceptors)\n  - [Multiple interceptors](#multiple-interceptors)\n- [Handling errors](#handling-errors)\n- [Handling timeouts](#handling-timeouts)\n- [Cancellation](#cancellation)\n  - [AbortController](#abortcontroller)\n  - [CancelToken](#canceltoken-deprecated)\n- [Using application/x-www-form-urlencoded format](#using-applicationx-www-form-urlencoded-format)\n  - [URLSearchParams](#urlsearchparams)\n  - [Query string](#query-string-older-browsers)\n  - [Automatic serialization](#automatic-serialization-to-urlsearchparams)\n- [Using multipart/form-data format](#using-multipartform-data-format)\n  - [FormData](#formdata)\n  - [Automatic serialization](#automatic-serialization-to-formdata)\n- [Posting files](#posting-files)\n- [HTML form posting](#html-form-posting-browser)\n- [Progress capturing](#progress-capturing)\n- [Rate limiting](#rate-limiting)\n- [AxiosHeaders](#axiosheaders)\n- [Fetch adapter](#fetch-adapter)\n  - [Custom fetch](#custom-fetch)\n    - [Using with Tauri](#using-with-tauri)\n    - [Using with SvelteKit](#using-with-sveltekit)\n- [HTTP/2 support](#http2-support)\n- [Semver](#semver)\n- [Promises](#promises)\n- [TypeScript](#typescript)\n- [Contributing](#contributing)\n  - [Local setup](#local-setup)\n- [Resources](#resources)\n- [Credits](#credits)\n- [License](#license)\n\n## Features\n\n- Make [XMLHttpRequests](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) from the browser.\n- Make [http](https://nodejs.org/api/http.html) requests from Node.js.\n- Use the [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) API for asynchronous request handling.\n- Intercept requests and responses to add custom logic or transform data.\n- Transform request and response data.\n- Cancel requests with built-in cancellation APIs.\n- Serialize and parse [JSON](https://www.json.org/json-en.html) data.\n- Serialize data objects to `multipart/form-data` or `application/x-www-form-urlencoded`.\n- Add client-side protection against [Cross-Site Request Forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery).\n\n## Browser support\n\n|                                                     Chrome                                                     |                                                      Firefox                                                      |                                                     Safari                                                     |                                                    Opera                                                    |                                                   Edge                                                   |\n| :------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------: |\n| ![Chrome browser logo](https://raw.githubusercontent.com/alrra/browser-logos/main/src/chrome/chrome_48x48.png) | ![Firefox browser logo](https://raw.githubusercontent.com/alrra/browser-logos/main/src/firefox/firefox_48x48.png) | ![Safari browser logo](https://raw.githubusercontent.com/alrra/browser-logos/main/src/safari/safari_48x48.png) | ![Opera browser logo](https://raw.githubusercontent.com/alrra/browser-logos/main/src/opera/opera_48x48.png) | ![Edge browser logo](https://raw.githubusercontent.com/alrra/browser-logos/main/src/edge/edge_48x48.png) |\n|                                                    Latest ✔                                                    |                                                     Latest ✔                                                      |                                                    Latest ✔                                                    |                                                  Latest ✔                                                   |                                                 Latest ✔                                                 |\n\n[![Browser Matrix](https://saucelabs.com/open_sauce/build_matrix/axios.svg)](https://saucelabs.com/u/axios)\n\n## Installing\n\n### Package manager\n\nUsing npm:\n\n```bash\n$ npm install axios\n```\n\nUsing yarn:\n\n```bash\n$ yarn add axios\n```\n\nUsing pnpm:\n\n```bash\n$ pnpm add axios\n```\n\nUsing bun:\n\n```bash\n$ bun add axios\n```\n\nUsing Deno:\n\n```bash\n$ deno add axios\n```\n\nOnce the package is installed, import it with `import` or `require`:\n\n```js\nimport axios, { isCancel, AxiosError } from 'axios';\n```\n\nYou can also use the default export, since the named export is just a re-export from the Axios factory:\n\n```js\nimport axios from 'axios';\n\nconsole.log(axios.isCancel('something'));\n```\n\nIf you use `require` for importing, **only the default export is available**:\n\n```js\nconst axios = require('axios');\n\nconsole.log(axios.isCancel('something'));\n```\n\nSome bundlers and ES6 linters need this form:\n\n```js\nimport { default as axios } from 'axios';\n```\n\nIn custom or legacy environments, you can import the bundle directly:\n\n```js\nconst axios = require('axios/dist/browser/axios.cjs'); // browser commonJS bundle (ES2017)\n// const axios = require('axios/dist/node/axios.cjs'); // node commonJS bundle (ES2017)\n```\n\n### CDN\n\nUsing jsDelivr CDN (ES5 UMD browser module):\n\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/axios@1.13.2/dist/axios.min.js\"></script>\n```\n\nUsing unpkg CDN:\n\n```html\n<script src=\"https://unpkg.com/axios@1.13.2/dist/axios.min.js\"></script>\n```\n\n## Example\n\n```js\nimport axios from 'axios';\n//const axios = require('axios'); // legacy way\n\ntry {\n  const response = await axios.get('/user?ID=12345');\n  console.log(response);\n} catch (error) {\n  console.error(error);\n}\n\n// Optionally the request above could also be done as\naxios\n  .get('/user', {\n    params: {\n      ID: 12345,\n    },\n    timeout: 5000, // 5 seconds. See \"Handling Timeouts\" below for matching error handling\n  })\n  .then(function (response) {\n    console.log(response);\n  })\n  .catch(function (error) {\n    console.log(error);\n  })\n  .finally(function () {\n    // always executed\n  });\n\n// Want to use async/await? Add the `async` keyword to your outer function/method.\nasync function getUser() {\n  try {\n    // Example: GET request with query parameters\n    const response = await axios.get('/user', {\n      params: {\n        ID: 12345,\n      },\n    });\n\n    // Using the `params` option improves readability and automatically formats query strings\n\n    console.log(response);\n  } catch (error) {\n    console.error(error);\n  }\n}\n```\n\n> Note: Set a `timeout` in production. Without one, a stalled request can hang\n> indefinitely. See [Handling Timeouts](#handling-timeouts) for the matching error handling.\n\n> Note: `async/await` is part of ECMAScript 2017 and is not supported in Internet\n> Explorer and older browsers, so use with caution.\n\nPerforming a `POST` request\n\n```js\nconst response = await axios.post('/user', {\n  firstName: 'Fred',\n  lastName: 'Flintstone',\n});\nconsole.log(response);\n```\n\nPerforming multiple concurrent requests\n\n```js\nfunction getUserAccount() {\n  return axios.get('/user/12345');\n}\n\nfunction getUserPermissions() {\n  return axios.get('/user/12345/permissions');\n}\n\nPromise.all([getUserAccount(), getUserPermissions()]).then(function (results) {\n  const acct = results[0];\n  const perm = results[1];\n});\n```\n\n## axios API\n\nRequests can be made by passing the relevant config to `axios`.\n\n##### axios(config)\n\n```js\n// Send a POST request\naxios({\n  method: 'post',\n  url: '/user/12345',\n  data: {\n    firstName: 'Fred',\n    lastName: 'Flintstone',\n  },\n});\n```\n\n```js\n// GET request for remote image in node.js\nconst response = await axios({\n  method: 'get',\n  url: 'https://bit.ly/2mTM3nY',\n  responseType: 'stream',\n});\nresponse.data.pipe(fs.createWriteStream('ada_lovelace.jpg'));\n```\n\n##### axios(url[, config])\n\n```js\n// Send a GET request (default method)\naxios('/user/12345');\n```\n\n### Request method aliases\n\nFor convenience, aliases have been provided for all common request methods.\n\n##### axios.request(config)\n\n##### axios.get(url[, config])\n\n##### axios.delete(url[, config])\n\n##### axios.head(url[, config])\n\n##### axios.options(url[, config])\n\n##### axios.post(url[, data[, config]])\n\n##### axios.put(url[, data[, config]])\n\n##### axios.patch(url[, data[, config]])\n\n###### Note\n\nWhen using the alias methods `url`, `method`, and `data` properties don't need to be specified in config.\n\n### Concurrency (deprecated)\n\nUse `Promise.all` instead of these helpers.\n\nHelper functions for dealing with concurrent requests.\n\naxios.all(iterable)\naxios.spread(callback)\n\n### Creating an instance\n\nYou can create a new instance of axios with a custom config.\n\n##### axios.create([config])\n\n```js\nconst instance = axios.create({\n  baseURL: 'https://some-domain.com/api/',\n  timeout: 1000,\n  headers: { 'X-Custom-Header': 'foobar' },\n});\n```\n\n### Instance methods\n\nThe following instance methods are available. Axios merges the specified config with the instance config.\n\n##### axios#request(config)\n\n##### axios#get(url[, config])\n\n##### axios#delete(url[, config])\n\n##### axios#head(url[, config])\n\n##### axios#options(url[, config])\n\n##### axios#post(url[, data[, config]])\n\n##### axios#put(url[, data[, config]])\n\n##### axios#patch(url[, data[, config]])\n\n##### axios#getUri([config])\n\n## Request config\n\n### Security notice: decompression-bomb protection is opt-in\n\nBy default `maxContentLength` and `maxBodyLength` are `-1` (unlimited). A malicious or compromised server can return a tiny gzip/deflate/brotli/zstd body that expands to gigabytes and exhaust the Node.js process.\n\nIf you call servers you do not fully trust, **set a cap**:\n\n```js\naxios.defaults.maxContentLength = 10 * 1024 * 1024; // 10 MB\naxios.defaults.maxBodyLength = 10 * 1024 * 1024;\n```\n\nSee the [security guide](https://axios.rest/pages/misc/security.html) for details.\n\nThese config options are available for requests. Only `url` is required. Requests default to `GET` when `method` is not set.\n\n```js\n{\n  // `url` is the server URL for the request\n  url: '/user',\n\n  // `method` is the request method to be used when making the request\n  method: 'get', // default\n\n  // Axios prepends `baseURL` to `url` unless `url` is absolute and `allowAbsoluteUrls` is set to true.\n  // It can be convenient to set `baseURL` for an instance of axios to pass relative URLs\n  // to the methods of that instance.\n  // `baseURL` is not a security boundary. If `url` is attacker-controlled, validate it\n  // before passing it to axios. Relative URLs can contain `..` segments that resolve\n  // outside an intended path prefix after the final URL is parsed.\n  baseURL: 'https://some-domain.com/api/',\n\n  // `allowAbsoluteUrls` determines whether or not absolute URLs will override a configured `baseUrl`.\n  // When set to true (default), absolute values for `url` will override `baseUrl`.\n  // When set to false, absolute values for `url` will always be prepended by `baseUrl`.\n  allowAbsoluteUrls: true,\n\n  // `transformRequest` allows changes to the request data before it is sent to the server\n  // This is only applicable for request methods 'PUT', 'POST', 'PATCH' and 'DELETE'\n  // The last function in the array must return a string or an instance of Buffer, ArrayBuffer,\n  // FormData or Stream\n  // You may modify the headers object.\n  transformRequest: [function (data, headers) {\n    // Do whatever you want to transform the data\n\n    return data;\n  }],\n\n  // `transformResponse` allows changes to the response data to be made before\n  // it is passed to then/catch\n  transformResponse: [function (data) {\n    // Do whatever you want to transform the data\n\n    return data;\n  }],\n\n  // `parseReviver` is an optional function passed as the\n  // second argument (reviver) to JSON.parse()\n  parseReviver: function (key, value, context) {\n    // In modern environments, context.source provides the raw JSON string\n    // allowing for precision-safe parsing of BigInt\n    if (typeof value === 'number' && context?.source) {\n      const isInteger = Number.isInteger(value);\n      const isUnsafe = !Number.isSafeInteger(value);\n      const isValidIntegerString = /^-?\\d+$/.test(context.source);\n\n      if (isInteger && isUnsafe && isValidIntegerString) {\n        try {\n          return BigInt(context.source);\n        } catch {\n          // Fallback: return original value if parsing fails\n        }\n      }\n    }\n    return value;\n  },\n\n  // `headers` are custom headers to be sent\n  headers: {'X-Requested-With': 'XMLHttpRequest'},\n\n  // `params` are the URL parameters to be sent with the request\n  // Must be a plain object or a URLSearchParams object\n  params: {\n    ID: 12345\n  },\n\n  // `paramsSerializer` is an optional config that allows you to customize serializing `params`.\n  paramsSerializer: {\n\n    // Custom encoder function which sends key/value pairs in an iterative fashion.\n    encode?: (param: string): string => { /* Do custom operations here and return transformed string */ },\n\n    // Custom serializer function for the entire parameter. Allows the user to mimic pre 1.x behaviour.\n    serialize?: (params: Record<string, any>, options?: ParamsSerializerOptions ),\n\n    // Configuration for formatting array indexes in the params.\n    indexes: false, // Three available options: (1) indexes: null (leads to no brackets), (2) (default) indexes: false (leads to empty brackets), (3) indexes: true (leads to brackets with indexes).\n\n    // Maximum object nesting depth when serializing params. Payloads deeper than this throw an\n    // AxiosError with code ERR_FORM_DATA_DEPTH_EXCEEDED. Default: 100. Set to Infinity to disable.\n    maxDepth: 100\n\n  },\n\n  // `data` is the data to be sent as the request body\n  // Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH'\n  // `data` is request-specific: axios does not inherit or deep-merge it from defaults.\n  // To add shared body fields, use a request interceptor or transformRequest.\n  // When no `transformRequest` is set, it must be of one of the following types:\n  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams\n  // - Browser only: FormData, File, Blob\n  // - React Native: FormData\n  // - Node only: Stream, Buffer, FormData (form-data package)\n  data: {\n    firstName: 'Fred'\n  },\n\n  // `formDataHeaderPolicy` controls how node.js FormData#getHeaders() is copied.\n  // 'legacy' (default) copies all returned headers for v1 compatibility.\n  // 'content-only' copies only Content-Type and Content-Length.\n  formDataHeaderPolicy: 'legacy',\n\n  // syntax alternative to send data into the body\n  // method post\n  // only the value is sent, not the key\n  data: 'Country=Brasil&City=Belo Horizonte',\n\n  // `timeout` specifies the number of milliseconds before the request times out.\n  // If the request takes longer than `timeout`, Axios aborts it.\n  timeout: 1000, // default is `0` (no timeout)\n\n  // `withCredentials` indicates whether or not cross-site Access-Control requests\n  // should be made using credentials\n  // This only controls whether the browser sends credentials.\n  // It does not control whether the XSRF header is added.\n  withCredentials: false, // default\n\n  // `adapter` allows custom handling of requests which makes testing easier.\n  // Return a promise and supply a valid response (see lib/adapters/README.md)\n  adapter: function (config) {\n    /* ... */\n  },\n  // Also, you can set the name of the built-in adapter, or provide an array with their names\n  // to choose the first available in the environment\n  adapter: 'xhr', // 'fetch' | 'http' | ['xhr', 'http', 'fetch']\n\n  // `auth` indicates that HTTP Basic auth should be used, and supplies credentials.\n  // This will set an `Authorization` header, overwriting any existing\n  // `Authorization` custom headers you have set using `headers`.\n  // If `auth` is omitted, the Node.js HTTP and fetch adapters can read\n  // HTTP Basic auth credentials from the request URL, for example\n  // `https://user:pass@example.com`. Axios decodes percent-encoded URL\n  // credentials, and `auth` takes precedence over URL-embedded credentials.\n  // The Node.js HTTP adapter preserves Basic auth on same-origin redirects\n  // and strips it on cross-origin redirects.\n  // Please note that only HTTP Basic auth is configurable through this parameter.\n  // For Bearer tokens and such, use `Authorization` custom headers instead.\n  auth: {\n    username: 'janedoe',\n    password: 's00pers3cret'\n  },\n\n  // `responseType` indicates the type of data that the server will respond with\n  // options are: 'arraybuffer', 'document', 'json', 'text', 'stream'\n  //   browser only: 'blob'\n  responseType: 'json', // default\n\n  // `responseEncoding` indicates encoding to use for decoding responses (Node.js only)\n  // Note: Ignored for `responseType` of 'stream' or client-side requests\n  // options are: 'ascii', 'ASCII', 'ansi', 'ANSI', 'binary', 'BINARY', 'base64', 'BASE64', 'base64url',\n  // 'BASE64URL', 'hex', 'HEX', 'latin1', 'LATIN1', 'ucs-2', 'UCS-2', 'ucs2', 'UCS2', 'utf-8', 'UTF-8',\n  // 'utf8', 'UTF8', 'utf16le', 'UTF16LE'\n  responseEncoding: 'utf8', // default\n\n  // `xsrfCookieName` is the name of the cookie to use as a value for the xsrf token\n  xsrfCookieName: 'XSRF-TOKEN', // default\n\n  // `xsrfHeaderName` is the name of the http header that carries the xsrf token value\n  xsrfHeaderName: 'X-XSRF-TOKEN', // default\n\n  // `withXSRFToken` defines whether to send the XSRF header in browser requests.\n  // `undefined` (default) - set XSRF header only for the same origin requests\n  // `true` - always set XSRF header, including for cross-origin requests\n  // `false` - never set XSRF header\n  // function - resolve with custom logic; receives the internal config object\n  withXSRFToken: boolean | undefined | ((config: InternalAxiosRequestConfig) => boolean | undefined),\n\n  // `withXSRFToken` controls whether Axios reads the XSRF cookie and sets the XSRF header.\n  // - `undefined` (default): the XSRF header is set only for same-origin requests.\n  // - `true`: attempt to set the XSRF header for all requests (including cross-origin).\n  // - `false`: never set the XSRF header.\n  // - function: a callback that receives the request `config` and returns `true`,\n  //   `false`, or `undefined` to decide per-request behavior.\n  //\n  // Note about `withCredentials`: `withCredentials` controls whether cross-site\n  // requests include credentials (cookies and HTTP auth). In older Axios versions,\n  // setting `withCredentials: true` implicitly caused Axios to set the XSRF header\n  // for cross-origin requests. Newer Axios separates these concerns: to allow the\n  // XSRF header to be sent for cross-origin requests you should set both\n  // `withCredentials: true` and `withXSRFToken: true`.\n  //\n  // Example:\n  // axios.get('/user', { withCredentials: true, withXSRFToken: true });\n\n  // `onUploadProgress` allows handling of progress events for uploads\n  // browser & node.js\n  onUploadProgress: function ({loaded, total, progress, bytes, estimated, rate, upload = true}) {\n    // Do whatever you want with the Axios progress event\n  },\n\n  // `onDownloadProgress` allows handling of progress events for downloads\n  // browser & node.js\n  onDownloadProgress: function ({loaded, total, progress, bytes, estimated, rate, download = true}) {\n    // Do whatever you want with the Axios progress event\n  },\n\n  // `maxContentLength` defines the max size of the response content in bytes.\n  // It is enforced by the Node.js HTTP adapter and the fetch adapter.\n  maxContentLength: 2000,\n\n  // `maxBodyLength` defines the max size of the request content in bytes.\n  // It is enforced by the Node.js HTTP adapter and the fetch adapter when the body length can be determined.\n  maxBodyLength: 2000,\n\n  // `redact` masks matching config keys when AxiosError#toJSON() is called.\n  // Matching is case-insensitive and recursive. It does not change the request.\n  redact: ['authorization', 'password'],\n\n  // `validateStatus` defines whether to resolve or reject the promise for a given\n  // HTTP response status code. If `validateStatus` returns `true` or is set to\n  // `null`, Axios resolves the promise; otherwise, Axios rejects it.\n  // Explicit `validateStatus: undefined` resolves every status by default for\n  // backward compatibility. Set `transitional.validateStatusUndefinedResolves`\n  // to `false` to make explicit `undefined` behave as if this option was omitted.\n  validateStatus: function (status) {\n    return status >= 200 && status < 300; // default\n  },\n\n  // `maxRedirects` defines the maximum number of redirects to follow in node.js.\n  // If set to 0, Axios follows no redirects.\n  maxRedirects: 21, // default\n\n  // `sensitiveHeaders` (Node only option) lists custom secret-bearing headers\n  // (such as `X-API-Key`) to remove from cross-origin redirects. Matching is\n  // case-insensitive. Same-origin redirects keep these headers. If\n  // `maxRedirects` is 0, this option is not used.\n  sensitiveHeaders: ['X-API-Key'],\n\n  // `beforeRedirect` defines a function that Axios calls before redirect.\n  // Use this to adjust the request options upon redirecting,\n  // to inspect the latest response headers,\n  // or to cancel the request by throwing an error\n  // If maxRedirects is set to 0, `beforeRedirect` is not used.\n\n  beforeRedirect: (options, { headers }) => {\n    if (\n      options.hostname === \"example.com\" &&\n      options.protocol === \"https:\"\n    ) {\n      options.auth = \"user:password\";\n    }\n  },\n  // Security note:\n  // The `beforeRedirect` hook runs after sensitive headers are stripped during redirects.\n  // `follow-redirects` removes credentials on protocol downgrades\n  // (HTTPS to HTTP). Because `beforeRedirect` runs after that step,\n  // re-injecting credentials without checking the destination can expose\n  // sensitive data. Only add credentials for trusted HTTPS destinations.\n\n  // `socketPath` defines a UNIX Socket to be used in node.js.\n  // e.g. '/var/run/docker.sock' to send requests to the docker daemon.\n  // Only either `socketPath` or `proxy` can be specified.\n  // If both are specified, `socketPath` is used.\n  //\n  // Security: when `socketPath` is set, hostname/port of the URL are ignored,\n  // which bypasses hostname-based SSRF protections. Never derive `socketPath`\n  // from untrusted input. Use `allowedSocketPaths` (below) to restrict accepted\n  // socket paths for defense-in-depth.\n  socketPath: null, // default\n\n  // `allowedSocketPaths` restricts which `socketPath` values are accepted.\n  // Accepts a string or array of strings. Entries and the incoming socketPath\n  // are compared after path.resolve(). A mismatch throws AxiosError with code\n  // `ERR_BAD_OPTION_VALUE`. When null/undefined, no restriction is applied.\n  allowedSocketPaths: null, // default\n\n  // `transport` determines the transport method for the request.\n  // If defined, Axios uses it. Otherwise, if `maxRedirects` is 0,\n  // Axios uses the default `http` or `https` library, depending on the protocol specified in `protocol`.\n  // Otherwise, Axios uses the `httpFollow` or `httpsFollow` library, again depending on the protocol,\n  // which can handle redirects.\n  transport: undefined, // default\n\n  // `httpAgent` and `httpsAgent` define a custom agent to be used when performing http\n  // and https requests, respectively, in node.js. This allows options to be added like\n  // `keepAlive` that are not enabled by default before Node.js v19.0.0. After Node.js\n  // v19.0.0, you no longer need to customize the agent to enable `keepAlive` because\n  // `http.globalAgent` has `keepAlive` enabled by default.\n  httpAgent: new http.Agent({ keepAlive: true }),\n  httpsAgent: new https.Agent({ keepAlive: true }),\n\n  // `proxy` defines the hostname, port, and protocol of the proxy server.\n  // You can also define your proxy using the conventional `http_proxy` and\n  // `https_proxy` environment variables. If you are using environment variables\n  // for your proxy configuration, you can also define a `no_proxy` environment\n  // variable as a comma-separated list of domains that should not be proxied.\n  // Use `false` to disable proxies, ignoring environment variables.\n  // On Node.js versions with native environment proxy support, axios defers\n  // environment proxy handling to Node when the selected agent has `proxyEnv`\n  // enabled, including processes started with `NODE_USE_ENV_PROXY=1`,\n  // `--use-env-proxy`, or `NODE_OPTIONS=--use-env-proxy`. Custom agents without\n  // `proxyEnv` continue to use axios environment proxy resolution. Explicit\n  // `proxy` config is still handled by axios.\n  // `auth` indicates that HTTP Basic auth should be used to connect to the proxy, and\n  // supplies credentials.\n  // For `http://` targets, axios sends the request to the proxy in\n  // forward-proxy mode and stamps `Proxy-Authorization` onto the request\n  // headers (overwriting any user-supplied `Proxy-Authorization` header).\n  // For `https://` targets, axios establishes a CONNECT tunnel through the\n  // proxy and performs TLS end-to-end with the origin; `Proxy-Authorization`\n  // is sent on the CONNECT request only, never on the wrapped TLS request,\n  // so the proxy never sees the URL, headers, or body. Axios forwards\n  // `httpsAgent` TLS options such as `ca`, `cert`, `key`, and\n  // `rejectUnauthorized` to the generated tunneling agent, so they still apply\n  // to the origin TLS connection.\n  // If you supply an `HttpsProxyAgent`, axios leaves tunneling to that agent.\n  // If the proxy server uses HTTPS, then you must set the protocol to `https`.\n  // A user-supplied `Host` header in `headers` is preserved when forwarding\n  // through a proxy (case-insensitive match on `host`/`Host`/`HOST`); this\n  // lets you target a virtual host that differs from the request URL, for\n  // example, hitting `127.0.0.1:4000` while having the proxy treat the\n  // request as `example.com`. If no `Host` header is supplied, axios\n  // defaults it to the request URL's `hostname:port` as before. The Host\n  // header is only set in forward-proxy mode (HTTP targets); for HTTPS\n  // tunneling the Host header is sent inside the TLS connection, not seen\n  // by the proxy.\n  proxy: {\n    protocol: 'https',\n    host: '127.0.0.1',\n    // hostname: '127.0.0.1' // Takes precedence over 'host' if both are defined\n    port: 9000,\n    auth: {\n      username: 'mikeymike',\n      password: 'rapunz3l'\n    }\n  },\n\n  // `cancelToken` specifies a cancel token that can be used to cancel the request\n  // (see Cancellation section below for details)\n  cancelToken: new CancelToken(function (cancel) {\n  }),\n\n  // an alternative way to cancel Axios requests using AbortController\n  signal: new AbortController().signal,\n\n  // `decompress` indicates whether or not the response body should be decompressed\n  // automatically. If set to `true` will also remove the 'content-encoding' header\n  // from the responses objects of all decompressed responses\n  // Axios supports gzip, deflate, brotli, and zstd when the current Node.js\n  // runtime provides the corresponding zlib decompressor.\n  // - Node only (XHR cannot turn off decompression)\n  decompress: true, // default\n\n  // `insecureHTTPParser` boolean.\n  // Indicates where to use an insecure HTTP parser that accepts invalid HTTP headers.\n  // This may allow interoperability with non-conformant HTTP implementations.\n  // Using the insecure parser should be avoided.\n  // see options https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_http_request_url_options_callback\n  // see also https://nodejs.org/en/blog/vulnerability/february-2020-security-releases/#strict-http-header-parsing-none\n  insecureHTTPParser: undefined, // default\n\n  // transitional options for backward compatibility that may be removed in the newer versions\n  transitional: {\n    // silent JSON parsing mode\n    // `true`  - ignore JSON parsing errors and set response.data to null if parsing failed (old behaviour)\n    // `false` - throw SyntaxError if JSON parsing failed\n    // Important: this option only takes effect when `responseType` is explicitly set to 'json'.\n    // When `responseType` is omitted (defaults to no value), axios uses `forcedJSONParsing`\n    // to attempt JSON parsing, but will silently return the raw string on failure regardless\n    // of this setting. To have invalid JSON throw errors, use:\n    //   { responseType: 'json', transitional: { silentJSONParsing: false } }\n    silentJSONParsing: true, // default value for the current Axios version\n\n    // try to parse the response string as JSON even if `responseType` is not 'json'\n    forcedJSONParsing: true,\n\n    // throw ETIMEDOUT error instead of generic ECONNABORTED on request timeouts\n    clarifyTimeoutError: false,\n\n    // keep explicit `validateStatus: undefined` resolving every response status\n    // for backward compatibility. Set to false to make explicit undefined behave\n    // as if validateStatus was omitted.\n    validateStatusUndefinedResolves: true,\n\n    // advertise `zstd` in the default Accept-Encoding header when the current\n    // Node.js runtime supports zstd decompression. Axios still decompresses\n    // zstd responses when support exists and `decompress` is true.\n    advertiseZstdAcceptEncoding: false,\n\n    // use the legacy interceptor request/response ordering\n    legacyInterceptorReqResOrdering: true, // default\n  },\n\n  env: {\n    // The FormData class to be used to automatically serialize the payload into a FormData object\n    FormData: window?.FormData || global?.FormData\n  },\n\n  formSerializer: {\n      visitor: (value, key, path, helpers) => {}; // custom visitor function to serialize form values\n      dots: boolean; // use dots instead of brackets format\n      metaTokens: boolean; // keep special endings like {} in parameter key\n      indexes: boolean; // array indexes format null - no brackets, false - empty brackets, true - brackets with indexes\n      maxDepth: 100; // maximum object nesting depth; throws AxiosError (ERR_FORM_DATA_DEPTH_EXCEEDED) if exceeded. Set to Infinity to disable.\n  },\n\n  // http adapter only (node.js)\n  maxRate: [\n    100 * 1024, // 100KB/s upload limit,\n    100 * 1024  // 100KB/s download limit\n  ]\n}\n```\n\nFor custom secret-bearing headers in Node.js, list them in `sensitiveHeaders` so Axios removes them when following a redirect to another origin:\n\n```js\naxios.get('https://api.example.com/users', {\n  headers: { 'X-API-Key': 'secret' },\n  sensitiveHeaders: ['X-API-Key'],\n});\n```\n\n### Strict RFC 3986 percent-encoding for query params\n\nBy default, axios decodes `%3A`, `%24`, `%2C` and `%20` back to `:`, `$`, `,` and `+` for readability (the `+` follows the `application/x-www-form-urlencoded` convention for spaces in query strings). These characters are valid in a query component under [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.4), so the default output is correct, but some backends require strict percent-encoding and reject the readable form.\n\nOverride the default encoder via `paramsSerializer.encode`:\n\n```js\n// Per-request: emit strict RFC 3986 percent-encoding for query values\naxios.get('/foo', {\n  params: { filter: JSON.stringify({ startedAt: '2026-01-23' }) },\n  paramsSerializer: { encode: encodeURIComponent },\n});\n\n// Or set it on the instance defaults\nconst client = axios.create({\n  paramsSerializer: { encode: encodeURIComponent },\n});\n```\n\n## HTTP/2 support\n\nAxios has experimental HTTP/2 support in the Node.js HTTP adapter.\n\nSupport depends on the runtime environment and Node.js version. Redirects and some adapter behavior may differ from HTTP/1.1.\n\nOptions like `httpVersion` and `http2Options` are adapter-specific and may not work the same way in every environment.\n\nIf you need HTTP/2, check runtime support or use a custom adapter.\n\n## Response schema\n\nThe response to a request contains the following information.\n\n```js\n{\n  // `data` is the response that was provided by the server\n  data: {},\n\n  // `status` is the HTTP status code from the server response\n  status: 200,\n\n  // `statusText` is the HTTP status message from the server response\n  statusText: 'OK',\n\n  // `headers` the HTTP headers that the server responded with\n  // All header names are lowercase and can be accessed using the bracket notation.\n  // Example: `response.headers['content-type']`\n  headers: {},\n\n  // `config` is the config that was provided to `axios` for the request\n  config: {},\n\n  // `request` is the request that generated this response\n  // It is the last ClientRequest instance in node.js (in redirects)\n  // and an XMLHttpRequest instance in the browser\n  request: {}\n}\n```\n\nWhen using `then`, you receive the response like this:\n\n```js\nconst response = await axios.get('/user/12345');\nconsole.log(response.data);\nconsole.log(response.status);\nconsole.log(response.statusText);\nconsole.log(response.headers);\nconsole.log(response.config);\n```\n\nWhen using `catch`, or passing a [rejection callback](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) as the second parameter of `then`, read the response from the `error` object. See [Handling errors](#handling-errors).\n\n## Config defaults\n\nConfig defaults apply to every request.\n\n### Global axios defaults\n\n```js\naxios.defaults.baseURL = 'https://api.example.com';\n\n// Important: If you use axios with multiple domains, Axios sends AUTH_TOKEN to all of them.\n// See below for an example using Custom instance defaults instead.\naxios.defaults.headers.common['Authorization'] = AUTH_TOKEN;\n\naxios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';\n```\n\n### Custom instance defaults\n\n```js\n// Set config defaults when creating the instance\nconst instance = axios.create({\n  baseURL: 'https://api.example.com',\n});\n\n// Alter defaults after instance has been created\ninstance.defaults.headers.common['Authorization'] = AUTH_TOKEN;\n```\n\n### Config order of precedence\n\nAxios merges config in this order: library defaults from [lib/defaults/index.js](https://github.com/axios/axios/blob/main/lib/defaults/index.js#L49), the instance `defaults` property, and the request `config` argument. Later values take precedence over earlier ones.\n\nSome options are request-specific and are only taken from the request `config`. `data` is one of those options: axios does not inherit or deep-merge request bodies from global or instance defaults. If every request needs shared body fields, add them with a request interceptor or `transformRequest`, and scope that logic carefully so sensitive values are not sent to the wrong endpoint.\n\n```js\n// Create an instance using the config defaults provided by the library\n// At this point the timeout config value is `0` as is the default for the library\nconst instance = axios.create();\n\n// Override timeout default for the library\n// Now all requests using this instance will wait 2.5 seconds before timing out\ninstance.defaults.timeout = 2500;\n\n// Override timeout for this request as it's known to take a long time\ninstance.get('/longRequest', {\n  timeout: 5000,\n});\n```\n\n## Interceptors\n\nYou can intercept requests or responses before methods like `.get()` or `.post()`\nresolve their promises (before code inside `then` or `catch`, or after `await`)\n\n```js\nconst instance = axios.create();\n\n// Add a request interceptor\ninstance.interceptors.request.use(\n  function (config) {\n    // Do something before the request is sent\n    return config;\n  },\n  function (error) {\n    // Do something with the request error\n    return Promise.reject(error);\n  }\n);\n\n// Add a response interceptor\ninstance.interceptors.response.use(\n  function (response) {\n    // Any status code that lies within the range of 2xx causes this function to trigger\n    // Do something with response data\n    return response;\n  },\n  function (error) {\n    // Any status codes that fall outside the range of 2xx cause this function to trigger\n    // Do something with response error\n    return Promise.reject(error);\n  }\n);\n```\n\nIf you need to remove an interceptor later you can.\n\n```js\nconst instance = axios.create();\nconst myInterceptor = instance.interceptors.request.use(function () {\n  /*...*/\n});\ninstance.interceptors.request.eject(myInterceptor);\n```\n\nYou can also clear all interceptors for requests or responses.\n\n```js\nconst instance = axios.create();\ninstance.interceptors.request.use(function () {\n  /*...*/\n});\ninstance.interceptors.request.clear(); // Removes interceptors from requests\ninstance.interceptors.response.use(function () {\n  /*...*/\n});\ninstance.interceptors.response.clear(); // Removes interceptors from responses\n```\n\nYou can add interceptors to a custom instance of axios.\n\n```js\nconst instance = axios.create();\ninstance.interceptors.request.use(function () {\n  /*...*/\n});\n```\n\nWhen you add request interceptors, they are presumed to be asynchronous by default. This can cause a delay\nin the execution of your axios request when the main thread is blocked (a promise is created under the hood for\nthe interceptor and your request gets put at the bottom of the call stack). If your request interceptors are synchronous you can add a flag\nto the options object that will tell axios to run the code synchronously and avoid any delays in request execution.\n\n```js\naxios.interceptors.request.use(\n  function (config) {\n    config.headers.test = 'I am only a header!';\n    return config;\n  },\n  null,\n  { synchronous: true }\n);\n```\n\nIf you want to execute a particular interceptor based on a runtime check,\nyou can add a `runWhen` function to the options object. The request interceptor will not run **if and only if** the return\nof `runWhen` is `false`. Axios calls the function with the config\nobject (don't forget that you can bind your own arguments to it as well.) This can be handy when you have an\nasynchronous request interceptor that only needs to run at certain times.\n\n```js\nfunction onGetCall(config) {\n  return config.method === 'get';\n}\naxios.interceptors.request.use(\n  function (config) {\n    config.headers.test = 'special get headers';\n    return config;\n  },\n  null,\n  { runWhen: onGetCall }\n);\n```\n\n> Note: The options parameter (with `synchronous` and `runWhen` properties) is only supported for request interceptors at the moment.\n\n### Interceptor execution order\n\nRequest and response interceptors use different execution orders.\n\nRequest interceptors run in reverse order (LIFO: last in, first out). The last interceptor added runs first.\n\nResponse interceptors run in the order they were added (FIFO: first in, first out). The first interceptor added runs first.\n\nExample:\n\n```js\nconst instance = axios.create();\n\nconst interceptor = (id) => (base) => {\n  console.log(id);\n  return base;\n};\n\ninstance.interceptors.request.use(interceptor('Request Interceptor 1'));\ninstance.interceptors.request.use(interceptor('Request Interceptor 2'));\ninstance.interceptors.request.use(interceptor('Request Interceptor 3'));\ninstance.interceptors.response.use(interceptor('Response Interceptor 1'));\ninstance.interceptors.response.use(interceptor('Response Interceptor 2'));\ninstance.interceptors.response.use(interceptor('Response Interceptor 3'));\n\n// Console output:\n// Request Interceptor 3\n// Request Interceptor 2\n// Request Interceptor 1\n// [HTTP request is made]\n// Response Interceptor 1\n// Response Interceptor 2\n// Response Interceptor 3\n```\n\n### Multiple interceptors\n\nWhen a response is fulfilled and multiple response interceptors are registered:\n\n- Each interceptor runs in registration order.\n- Each interceptor receives the result from the previous interceptor.\n- The chain returns the result from the last interceptor.\n- If a fulfillment interceptor throws, Axios skips the next fulfillment interceptor and calls the next rejection interceptor.\n- After the error is caught, later fulfillment interceptors run again, just like in a promise chain.\n\nRead [the interceptor tests](./test/specs/interceptors.spec.js) to see all this in code.\n\n## Error types\n\nAxios error messages include details that can help you debug the request.\n\nAxios errors use this structure:\n| Property | Definition |\n| -------- | ---------- |\n| message | A quick summary of the error message and the status it failed with. |\n| name | This defines where the error originated from. For axios, it will always be an 'AxiosError'. |\n| stack | Stack trace for the error. |\n| config | An axios config object with specific instance configurations defined by the user from when the request was made |\n| code | Axios error code. The table below lists internal Axios error codes. |\n| status | HTTP response status code. See [here](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) for common HTTP response status code meanings.\n\nThese are the internal Axios error codes:\n\n| Code                      | Definition                                                                                                                                                                                                                                                                                                                                                                                     |\n| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| ERR_BAD_OPTION_VALUE      | Invalid value provided in axios configuration.                                                                                                                                                                                                                                                                                                                                                 |\n| ERR_BAD_OPTION            | Invalid option provided in axios configuration.                                                                                                                                                                                                                                                                                                                                                |\n| ERR_NOT_SUPPORT           | Feature or method not supported in the current axios environment.                                                                                                                                                                                                                                                                                                                              |\n| ERR_DEPRECATED            | Deprecated feature or method used in axios.                                                                                                                                                                                                                                                                                                                                                    |\n| ERR_INVALID_URL           | Invalid URL provided for axios request.                                                                                                                                                                                                                                                                                                                                                        |\n| ECONNABORTED              | Typically indicates that the request has been timed out (unless `transitional.clarifyTimeoutError` is set) or aborted by the browser or its plugin.                                                                                                                                                                                                                                            |\n| ERR_CANCELED              | The user explicitly canceled the request with an AbortSignal or CancelToken.                                                                                                                                                                                                                                                                                                                   |\n| ETIMEDOUT                 | Request timed out after exceeding the configured Axios timeout. Set `transitional.clarifyTimeoutError` to `true`; otherwise Axios throws a generic `ECONNABORTED` error.                                                                                                                                                                                                                       |\n| ERR_NETWORK               | Network-related issue. In the browser, this error can also be caused by a [CORS](https://developer.mozilla.org/ru/docs/Web/HTTP/Guides/CORS) or [Mixed Content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content) policy violation. The browser does not allow the JS code to clarify the real reason for the error caused by security issues, so please check the console. |\n| ERR_FR_TOO_MANY_REDIRECTS | Request exceeded the configured maximum number of redirects.                                                                                                                                                                                                                                                                                                                                   |\n| ERR_BAD_RESPONSE          | Response cannot be parsed properly or is in an unexpected format. Usually related to a response with `5xx` status code.                                                                                                                                                                                                                                                                        |\n| ERR_BAD_REQUEST           | The request has an unexpected format or is missing required parameters. Usually related to a response with `4xx` status code.                                                                                                                                                                                                                                                                  |\n\n## Handling errors\n\nBy default, Axios rejects responses with status codes outside the 2xx range.\n\n```js\naxios.get('/user/12345').catch(function (error) {\n  if (error.response) {\n    // The request was made and the server responded with a status code\n    // that falls out of the range of 2xx\n    console.log(error.response.data);\n    console.log(error.response.status);\n    console.log(error.response.headers);\n  } else if (error.request) {\n    // The request was made but no response was received\n    // `error.request` is an instance of XMLHttpRequest in the browser and an instance of\n    // http.ClientRequest in node.js\n    console.log(error.request);\n  } else {\n    // Something happened in setting up the request that triggered an Error\n    console.log('Error', error.message);\n  }\n  console.log(error.config);\n});\n```\n\nUse `validateStatus` to override the default condition (`status >= 200 && status < 300`) and choose which HTTP status codes should reject.\n\n```js\naxios.get('/user/12345', {\n  validateStatus: function (status) {\n    return status < 500; // Resolve only if the status code is less than 500\n  },\n});\n```\n\nBy default, explicit `validateStatus: undefined` keeps legacy behavior and resolves every response status because `transitional.validateStatusUndefinedResolves` defaults to `true`. Set it to `false` to make explicit `validateStatus: undefined` behave like the option was omitted, so Axios uses the configured/default validator and rejects non-2xx responses by default.\n\n`validateStatus: null` still accepts every response status. If you disable the transitional behavior and intentionally want all statuses to resolve, use `null` or `() => true`.\n\n```js\naxios.get('/user/12345', {\n  validateStatus: undefined,\n  transitional: {\n    validateStatusUndefinedResolves: false,\n  },\n});\n```\n\nUse `toJSON` to get more information about the HTTP error.\n\n```js\naxios.get('/user/12345').catch(function (error) {\n  console.log(error.toJSON());\n});\n```\n\nTo avoid logging secrets from `error.config`, pass a `redact` array in the request config. Matching config keys are masked case-insensitively at any depth when `AxiosError#toJSON()` is called.\n\n```js\naxios\n  .get('/user/12345', {\n    headers: { Authorization: 'Bearer token' },\n    redact: ['authorization'],\n  })\n  .catch(function (error) {\n    console.log(error.toJSON().config.headers.Authorization); // [REDACTED ****]\n  });\n```\n\n## Handling timeouts\n\n```js\nasync function fetchWithTimeout() {\n  try {\n    const response = await axios.get('https://example.com/data', {\n      timeout: 5000, // 5 seconds\n      transitional: {\n        // set to true if you prefer ETIMEDOUT over ECONNABORTED\n        clarifyTimeoutError: false,\n      },\n    });\n\n    console.log('Response:', response.data);\n  } catch (error) {\n    if (axios.isAxiosError(error)) {\n      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT') {\n        console.error('Request timed out. Please try again.');\n        return;\n      }\n\n      console.error('Axios error:', error.message);\n      return;\n    }\n\n    console.error('Unexpected error:', error);\n  }\n}\n```\n\n## Cancellation\n\n### AbortController\n\nSince `v0.22.0`, Axios supports AbortController:\n\n```js\nconst controller = new AbortController();\n\naxios\n  .get('/foo/bar', {\n    signal: controller.signal,\n  })\n  .then(function (response) {\n    //...\n  });\n// cancel the request\ncontroller.abort();\n```\n\n### CancelToken (deprecated)\n\nYou can also cancel a request using a _CancelToken_.\n\n> The axios cancel token API is based on the withdrawn [cancellable promises proposal](https://github.com/tc39/proposal-cancelable-promises).\n\n> This API is deprecated since v0.22.0 and should not be used in new projects.\n\nCreate a cancel token with the `CancelToken.source` factory:\n\n```js\nconst CancelToken = axios.CancelToken;\nconst source = CancelToken.source();\n\naxios\n  .get('/user/12345', {\n    cancelToken: source.token,\n  })\n  .catch(function (thrown) {\n    if (axios.isCancel(thrown)) {\n      console.log('Request canceled', thrown.message);\n    } else {\n      // handle error\n    }\n  });\n\naxios.post(\n  '/user/12345',\n  {\n    name: 'new name',\n  },\n  {\n    cancelToken: source.token,\n  }\n);\n\n// cancel the request (the message parameter is optional)\nsource.cancel('Operation canceled by the user.');\n```\n\nYou can also pass an executor function to the `CancelToken` constructor:\n\n```js\nconst CancelToken = axios.CancelToken;\nlet cancel;\n\naxios.get('/user/12345', {\n  cancelToken: new CancelToken(function executor(c) {\n    // An executor function receives a cancel function as a parameter\n    cancel = c;\n  }),\n});\n\n// cancel the request\ncancel();\n```\n\n`CancelToken` also exposes low-level helpers for legacy integrations:\n\n```js\nconst source = axios.CancelToken.source();\n\nconst listener = (cancel) => {\n  console.log(cancel.message);\n};\n\nsource.token.subscribe(listener);\n\nconst signal = source.token.toAbortSignal();\n// Pass `signal` to APIs that accept AbortSignal.\n\nsource.cancel('Operation canceled by the user.');\nsource.token.unsubscribe(listener);\n```\n\nCanceled requests reject with `axios.CanceledError`. The legacy `axios.Cancel` export is an alias of `axios.CanceledError`, and cancellation errors include `__CANCEL__` for `axios.isCancel` compatibility.\n\n> Note: You can cancel several requests with the same cancel token or abort controller.\n> If a cancellation token is already cancelled when an Axios request starts, Axios cancels the request immediately without making a real request.\n\n> During the transition period, you can use both cancellation APIs, even for the same request:\n\n```js\nconst controller = new AbortController();\nconst source = axios.CancelToken.source();\n\naxios.get('/user/12345', {\n  cancelToken: source.token,\n  signal: controller.signal,\n});\n\ncontroller.abort();\nsource.cancel('Operation canceled by the user.');\n```\n\n## Using `application/x-www-form-urlencoded` format\n\n### URLSearchParams\n\nBy default, axios serializes JavaScript objects to `JSON`. To send data as [`application/x-www-form-urlencoded`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST), use the [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) API. It works in most browsers and in [Node](https://nodejs.org/api/url.html#url_class_urlsearchparams) v10 and later.\n\n```js\nconst params = new URLSearchParams({ foo: 'bar' });\nparams.append('extraparam', 'value');\naxios.post('/foo', params);\n```\n\n### Query string (older browsers)\n\nFor very old browsers, use a [polyfill](https://github.com/WebReflection/url-search-params) and make sure it patches the global environment.\n\nAlternatively, you can encode data using the [`qs`](https://github.com/ljharb/qs) library:\n\n```js\nconst qs = require('qs');\naxios.post('/foo', qs.stringify({ bar: 123 }));\n```\n\nWith ES modules:\n\n```js\nimport qs from 'qs';\nconst data = { bar: 123 };\nconst options = {\n  method: 'POST',\n  headers: { 'content-type': 'application/x-www-form-urlencoded' },\n  data: qs.stringify(data),\n  url,\n};\naxios(options);\n```\n\n### Older Node.js versions\n\nFor older Node.js engines, use the [`querystring`](https://nodejs.org/api/querystring.html) module:\n\n```js\nconst querystring = require('querystring');\naxios.post('https://something.com/', querystring.stringify({ foo: 'bar' }));\n```\n\nYou can also use the [`qs`](https://github.com/ljharb/qs) library.\n\n> Note: The `qs` library is preferable if you need to stringify nested objects, as the `querystring` method has [known issues](https://github.com/nodejs/node-v0.x-archive/issues/1665) with that use case.\n\n### Automatic serialization to URLSearchParams\n\nAxios automatically serializes the data object to urlencoded format if the content-type header is set to \"application/x-www-form-urlencoded\".\n\n```js\nconst data = {\n  x: 1,\n  arr: [1, 2, 3],\n  arr2: [1, [2], 3],\n  users: [\n    { name: 'Peter', surname: 'Griffin' },\n    { name: 'Thomas', surname: 'Anderson' },\n  ],\n};\n\nawait axios.postForm('https://postman-echo.com/post', data, {\n  headers: { 'content-type': 'application/x-www-form-urlencoded' },\n});\n```\n\nThe server receives these fields:\n\n```js\n  {\n    x: '1',\n    'arr[]': [ '1', '2', '3' ],\n    'arr2[0]': '1',\n    'arr2[1][0]': '2',\n    'arr2[2]': '3',\n    'arr3[]': [ '1', '2', '3' ],\n    'users[0][name]': 'Peter',\n    'users[0][surname]': 'griffin',\n    'users[1][name]': 'Thomas',\n    'users[1][surname]': 'Anderson'\n  }\n```\n\nIf your backend body parser, such as `body-parser` for `express.js`, supports nested object decoding, the server receives the same object structure:\n\n```js\nconst app = express();\n\napp.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies\n\napp.post('/', function (req, res, next) {\n  // echo body as JSON\n  res.send(JSON.stringify(req.body));\n});\n\nserver = app.listen(3000);\n```\n\n## Using `multipart/form-data` format\n\n### FormData\n\nTo send data as `multipart/form-data`, pass a FormData instance as the payload.\nYou do not need to set the `Content-Type` header. Axios detects it from the payload type.\nFor browser, web worker, and React Native `FormData`, leave `Content-Type` unset so the runtime can add the multipart boundary.\n\n```js\nconst formData = new FormData();\nformData.append('foo', 'bar');\n\naxios.post('https://httpbin.org/post', formData);\n```\n\nIn node.js, use the [`form-data`](https://github.com/form-data/form-data) library:\n\n```js\nconst FormData = require('form-data');\n\nconst form = new FormData();\nform.append('my_field', 'my value');\nform.append('my_buffer', Buffer.alloc(10));\nform.append('my_file', fs.createReadStream('/foo/bar.jpg'));\n\naxios.post('https://example.com', form);\n```\n\nIn node.js, when a `FormData` object provides `getHeaders()`, axios copies all returned headers by default for v1 compatibility. If the `FormData` object is custom or not fully trusted, set `formDataHeaderPolicy: 'content-only'` to copy only `Content-Type` and `Content-Length`, and set any other request headers explicitly with the request `headers` config.\n\n### Automatic serialization to FormData\n\nSince `v0.27.0`, Axios can serialize an object to FormData if the request `Content-Type`\nheader is set to `multipart/form-data`.\n\nThis request submits data as FormData in browsers and Node.js:\n\n```js\nimport axios from 'axios';\n\naxios\n  .post(\n    'https://httpbin.org/post',\n    { x: 1 },\n    {\n      headers: {\n        'Content-Type': 'multipart/form-data',\n      },\n    }\n  )\n  .then(({ data }) => console.log(data));\n```\n\nThe Node.js build uses the [`form-data`](https://github.com/form-data/form-data) polyfill by default.\n\nYou can override the FormData class with the `env.FormData` config option, but most applications do not need this:\n\n```js\nconst axios = require('axios');\nvar FormData = require('form-data');\n\naxios\n  .post(\n    'https://httpbin.org/post',\n    { x: 1, buf: Buffer.alloc(10) },\n    {\n      headers: {\n        'Content-Type': 'multipart/form-data',\n      },\n    }\n  )\n  .then(({ data }) => console.log(data));\n```\n\nThe Axios FormData serializer supports these special endings:\n\n- `{}` - serialize the value with JSON.stringify\n- `[]` - unwrap the array-like object as separate fields with the same key\n\n> Note: Arrays and FileList objects are unwrapped by default.\n\nFormData serializer supports additional options via `config.formSerializer: object` property to handle rare cases:\n\n- `visitor: Function` - user-defined visitor function that Axios calls recursively to serialize the data object\n  to a `FormData` object by following custom rules.\n\n- `dots: boolean = false` - use dot notation instead of brackets to serialize arrays and objects;\n\n- `metaTokens: boolean = true` - add the special ending (e.g `user{}: '{\"name\": \"John\"}'`) in the FormData key.\n  A backend body parser can use this meta-information to parse the value as JSON.\n\n- `indexes: null|false|true = false` - controls how Axios adds indexes to unwrapped keys of `flat` array-like objects.\n  - `null` - don't add brackets (`arr: 1`, `arr: 2`, `arr: 3`)\n  - `false`(default) - add empty brackets (`arr[]: 1`, `arr[]: 2`, `arr[]: 3`)\n  - `true` - add brackets with indexes (`arr[0]: 1`, `arr[1]: 2`, `arr[2]: 3`)\n- `maxDepth: number = 100` - maximum object nesting depth the serializer will recurse into. If the\n  input object exceeds this depth, an `AxiosError` with `code: 'ERR_FORM_DATA_DEPTH_EXCEEDED'` is\n  thrown instead of overflowing the call stack. This protects server applications from DoS\n  attacks via deeply nested payloads. Set to `Infinity` to disable the limit and restore pre-fix behaviour.\n- `Blob: typeof Blob` - Blob constructor used when converting ArrayBuffer-like values for spec-compliant\n  `FormData`. Override it only for runtimes that provide a compatible `Blob` constructor under a\n  different binding.\n\n```js\n// Raise the limit for a schema that genuinely nests deeper than 100 levels:\naxios.postForm('/api', data, { formSerializer: { maxDepth: 200 } });\n\n// Same protection applies to params serialization:\naxios.get('/api', { params: data, paramsSerializer: { maxDepth: 200 } });\n```\n\nGiven this object:\n\n```js\nconst obj = {\n  x: 1,\n  arr: [1, 2, 3],\n  arr2: [1, [2], 3],\n  users: [\n    { name: 'Peter', surname: 'Griffin' },\n    { name: 'Thomas', surname: 'Anderson' },\n  ],\n  'obj2{}': [{ x: 1 }],\n};\n```\n\nThe Axios serializer appends these fields:\n\n```js\nconst formData = new FormData();\nformData.append('x', '1');\nformData.append('arr[]', '1');\nformData.append('arr[]', '2');\nformData.append('arr[]', '3');\nformData.append('arr2[0]', '1');\nformData.append('arr2[1][0]', '2');\nformData.append('arr2[2]', '3');\nformData.append('users[0][name]', 'Peter');\nformData.append('users[0][surname]', 'Griffin');\nformData.append('users[1][name]', 'Thomas');\nformData.append('users[1][surname]', 'Anderson');\nformData.append('obj2{}', '[{\"x\":1}]');\n```\n\nAxios supports `postForm`, `putForm`, and `patchForm` as shortcuts for the matching HTTP methods with the `Content-Type` header preset to `multipart/form-data`.\n\n## Posting files\n\nSubmit a single file:\n\n```js\nawait axios.postForm('https://httpbin.org/post', {\n  myVar: 'foo',\n  file: document.querySelector('#fileInput').files[0],\n});\n```\n\nor multiple files as `multipart/form-data`:\n\n```js\nawait axios.postForm('https://httpbin.org/post', {\n  'files[]': document.querySelector('#fileInput').files,\n});\n```\n\n`FileList` object can be passed directly:\n\n```js\nawait axios.postForm('https://httpbin.org/post', document.querySelector('#fileInput').files);\n```\n\nAxios sends all files with the same field name: `files[]`.\n\n## HTML form posting (browser)\n\nPass an HTML Form element as a payload to submit it as `multipart/form-data` content.\n\n```js\nawait axios.postForm('https://httpbin.org/post', document.querySelector('#htmlForm'));\n```\n\n`FormData` and `HTMLForm` objects can also be posted as `JSON` by explicitly setting the `Content-Type` header to `application/json`:\n\n```js\nawait axios.post('https://httpbin.org/post', document.querySelector('#htmlForm'), {\n  headers: {\n    'Content-Type': 'application/json',\n  },\n});\n```\n\nFor example, the Form\n\n```html\n<form id=\"form\">\n  <input type=\"text\" name=\"foo\" value=\"1\" />\n  <input type=\"text\" name=\"deep.prop\" value=\"2\" />\n  <input type=\"text\" name=\"deep prop spaced\" value=\"3\" />\n  <input type=\"text\" name=\"baz\" value=\"4\" />\n  <input type=\"text\" name=\"baz\" value=\"5\" />\n\n  <select name=\"user.age\">\n    <option value=\"value1\">Value 1</option>\n    <option value=\"value2\" selected>Value 2</option>\n    <option value=\"value3\">Value 3</option>\n  </select>\n\n  <input type=\"submit\" value=\"Save\" />\n</form>\n```\n\nsubmits this JSON object:\n\n```js\n{\n  \"foo\": \"1\",\n  \"deep\": {\n    \"prop\": {\n      \"spaced\": \"3\"\n    }\n  },\n  \"baz\": [\n    \"4\",\n    \"5\"\n  ],\n  \"user\": {\n    \"age\": \"value2\"\n  }\n}\n```\n\nSending `Blobs`/`Files` as JSON (`base64`) is not currently supported.\n\n## Progress capturing\n\nAxios can capture request upload and download progress in browsers and Node.js.\nProgress events are limited to `3` times per second.\n\n```js\nawait axios.post(url, data, {\n  onUploadProgress: function (axiosProgressEvent) {\n    /*{\n      loaded: number;\n      total?: number;\n      progress?: number; // in range [0..1]\n      bytes: number; // how many bytes have been transferred since the last trigger (delta)\n      estimated?: number; // estimated time in seconds\n      rate?: number; // upload speed in bytes\n      upload: true; // upload sign\n    }*/\n  },\n\n  onDownloadProgress: function (axiosProgressEvent) {\n    /*{\n      loaded: number;\n      total?: number;\n      progress?: number;\n      bytes: number;\n      estimated?: number;\n      rate?: number; // download speed in bytes\n      download: true; // download sign\n    }*/\n  },\n});\n```\n\nYou can also track stream upload/download progress in node.js:\n\n```js\nconst { data } = await axios.post(SERVER_URL, readableStream, {\n  onUploadProgress: ({ progress }) => {\n    console.log((progress * 100).toFixed(2));\n  },\n\n  headers: {\n    'Content-Length': contentLength,\n  },\n\n  maxRedirects: 0, // avoid buffering the entire stream\n});\n```\n\n> Note:\n> Capturing FormData upload progress is not currently supported in node.js environments.\n\n> Warning:\n> Set `maxRedirects: 0` when uploading streams in node.js.\n> The follow-redirects package buffers the entire stream in RAM and does not follow the \"backpressure\" algorithm.\n\n## Rate limiting\n\nDownload and upload rate limits can only be set for the http adapter (node.js):\n\n```js\nconst { data } = await axios.post(LOCAL_SERVER_URL, myBuffer, {\n  onUploadProgress: ({ progress, rate }) => {\n    console.log(`Upload [${(progress * 100).toFixed(2)}%]: ${(rate / 1024).toFixed(2)}KB/s`);\n  },\n\n  maxRate: [100 * 1024], // 100KB/s limit\n});\n```\n\n## AxiosHeaders\n\nAxios includes an `AxiosHeaders` class for working with headers through a Map-like API.\nHTTP header names are case-insensitive, but Axios keeps the original header case for style and for servers that incorrectly depend on case.\nDirectly manipulating the headers object still works, but it is deprecated.\n\n### Working with headers\n\nAn `AxiosHeaders` instance can contain several internal value types that control setting and merging.\nAxios gets the final headers object with string values by calling `toJSON`.\n\n> Note: By JSON here we mean an object consisting only of string values intended to be sent over the network.\n\nThe header value can be one of the following types:\n\n- `string` - normal string value sent to the server\n- `null` - skip header when rendering to JSON\n- `false` - skip header when rendering to JSON. Also indicates that the `set` method must be called with `rewrite` set to `true`\n  to overwrite this value (Axios uses this internally to allow users to opt out of installing certain headers like `User-Agent` or `Content-Type`)\n- `undefined` - value is not set\n\n> Note: The header value is considered set if it is not equal to undefined.\n\nThe headers object is always initialized inside interceptors and transformers:\n\n```ts\naxios.interceptors.request.use((request: InternalAxiosRequestConfig) => {\n  request.headers.set('My-header', 'value');\n\n  request.headers.set({\n    'My-set-header1': 'my-set-value1',\n    'My-set-header2': 'my-set-value2',\n  });\n\n  request.headers.set('User-Agent', false); // prevent Axios from setting this header later\n\n  request.headers.setContentType('text/plain');\n\n  request.headers['My-set-header2'] = 'newValue'; // direct access is deprecated\n\n  return request;\n});\n```\n\nYou can iterate over an `AxiosHeaders` instance using a `for...of` statement:\n\n```js\nconst headers = new AxiosHeaders({\n  foo: '1',\n  bar: '2',\n  baz: '3',\n});\n\nfor (const [header, value] of headers) {\n  console.log(header, value);\n}\n\n// foo 1\n// bar 2\n// baz 3\n```\n\n### Preserving a specific header case\n\nHeader names are case-insensitive, but `AxiosHeaders` keeps the case of the first matching key it sees.\nIf you need a specific case for non-standard case-sensitive servers, define a case preset with `undefined` and then set the value later:\n\n```js\nconst api = axios.create();\n\napi.defaults.headers.common = {\n  'content-type': undefined,\n  accept: undefined,\n};\n\nawait api.put(url, data, {\n  headers: {\n    'Content-Type': 'application/octet-stream',\n    Accept: 'application/json',\n  },\n});\n```\n\nYou can also compose the same behavior with `AxiosHeaders.concat`:\n\n```js\nconst headers = axios.AxiosHeaders.concat(\n  { 'content-type': undefined },\n  { 'Content-Type': 'application/octet-stream' }\n);\n\nawait axios.put(url, data, { headers });\n```\n\n### new AxiosHeaders(headers?)\n\nConstructs a new `AxiosHeaders` instance.\n\n```\nconstructor(headers?: RawAxiosHeaders | AxiosHeaders | string);\n```\n\nIf the headers object is a string, Axios parses it as raw HTTP headers.\n\n```js\nconst headers = new AxiosHeaders(`\nHost: www.bing.com\nUser-Agent: curl/7.54.0\nAccept: */*`);\n\nconsole.log(headers);\n\n// Object [AxiosHeaders] {\n//   host: 'www.bing.com',\n//   'user-agent': 'curl/7.54.0',\n//   accept: '*/*'\n// }\n```\n\n### AxiosHeaders#set\n\n```ts\nset(headerName, value: Axios, rewrite?: boolean);\nset(headerName, value, rewrite?: (this: AxiosHeaders, value: string, name: string, headers: RawAxiosHeaders) => boolean);\nset(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean);\nset(headers?: Iterable<[string, AxiosHeaderValue]>, rewrite?: boolean);\n```\n\nThe `rewrite` argument controls the overwriting behavior:\n\n- `false` - do not overwrite if the header's value is set (is not `undefined`)\n- `undefined` (default) - overwrite the header unless its value is set to `false`\n- `true` - rewrite anyway\n\nThe option can also accept a user-defined function that determines whether to overwrite the value.\n\nEmpty or whitespace-only header names are ignored.\n\nIterable key/value pairs, such as a `Map`, are accepted:\n\n```js\nconst headers = new AxiosHeaders();\n\nheaders.set(\n  new Map([\n    ['X-Trace-Id', 'abc123'],\n    ['Accept', 'application/json'],\n  ])\n);\n```\n\nReturns `this`.\n\n### AxiosHeaders#get(header)\n\n```\n  get(headerName: string, matcher?: true | AxiosHeaderMatcher): AxiosHeaderValue;\n  get(headerName: string, parser: RegExp): RegExpExecArray | null;\n```\n\nReturns the internal value of the header. It can take an extra argument to parse the header's value with `RegExp.exec`,\nmatcher function or internal key-value parser.\n\n```ts\nconst headers = new AxiosHeaders({\n  'Content-Type': 'multipart/form-data; boundary=Asrf456BGe4h',\n});\n\nconsole.log(headers.get('Content-Type'));\n// multipart/form-data; boundary=Asrf456BGe4h\n\nconsole.log(headers.get('Content-Type', true)); // parse key-value pairs from a string separated with \\s,;= delimiters:\n// [Object: null prototype] {\n//   'multipart/form-data': undefined,\n//    boundary: 'Asrf456BGe4h'\n// }\n\nconsole.log(\n  headers.get('Content-Type', (value, name, headers) => {\n    return String(value).replace(/a/g, 'ZZZ');\n  })\n);\n// multipZZZrt/form-dZZZtZZZ; boundZZZry=Asrf456BGe4h\n\nconsole.log(headers.get('Content-Type', /boundary=(\\w+)/)?.[0]);\n// boundary=Asrf456BGe4h\n```\n\nReturns the value of the header.\n\n### AxiosHeaders#has(header, matcher?)\n\n```\nhas(header: string, matcher?: AxiosHeaderMatcher): boolean;\n```\n\nReturns `true` if the header is set (has no `undefined` value).\n\n### AxiosHeaders#delete(header, matcher?)\n\n```\ndelete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean;\n```\n\nReturns `true` if at least one header has been removed.\n\n### AxiosHeaders#clear(matcher?)\n\n```\nclear(matcher?: AxiosHeaderMatcher): boolean;\n```\n\nRemoves all headers.\nUnlike the `delete` method matcher, this optional matcher matches the header name rather than the value.\n\n```ts\nconst headers = new AxiosHeaders({\n  foo: '1',\n  'x-foo': '2',\n  'x-bar': '3',\n});\n\nconsole.log(headers.clear(/^x-/)); // true\n\nconsole.log(headers.toJSON()); // [Object: null prototype] { foo: '1' }\n```\n\nReturns `true` if at least one header has been cleared.\n\n### AxiosHeaders#normalize(format);\n\nIf the headers object was changed directly, it can have duplicates with the same name but in different cases.\nThis method normalizes the headers object by combining duplicate keys into one.\nAxios uses this method internally after calling each interceptor.\nSet `format` to true for converting header names to lowercase and capitalizing the initial letters (`cOntEnt-type` => `Content-Type`)\n\n```js\nconst headers = new AxiosHeaders({\n  foo: '1',\n});\n\nheaders.Foo = '2';\nheaders.FOO = '3';\n\nconsole.log(headers.toJSON()); // [Object: null prototype] { foo: '1', Foo: '2', FOO: '3' }\nconsole.log(headers.normalize().toJSON()); // [Object: null prototype] { foo: '3' }\nconsole.log(headers.normalize(true).toJSON()); // [Object: null prototype] { Foo: '3' }\n```\n\nReturns `this`.\n\n### AxiosHeaders#concat(...targets)\n\n```\nconcat(...targets: Array<AxiosHeaders | RawAxiosHeaders | string | undefined | null>): AxiosHeaders;\n```\n\nMerges the instance with targets into a new `AxiosHeaders` instance. If the target is a string, Axios parses it as raw HTTP headers.\n\nReturns a new `AxiosHeaders` instance.\n\n### AxiosHeaders#toJSON(asStrings?)\n\n```\ntoJSON(asStrings: true): Record<string, string>;\ntoJSON(asStrings?: false): Record<string, string | string[]>;\n```\n\nResolves all internal header values into a new null prototype object.\nSet `asStrings` to true to resolve arrays as a string containing all elements, separated by commas.\n\n### AxiosHeaders#toString()\n\n```\ntoString(): string;\n```\n\nReturns the headers as a CRLF-free HTTP header block, one `name: value` pair per line.\n\n### AxiosHeaders.from(thing?)\n\n```\nfrom(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders;\n```\n\nReturns a new `AxiosHeaders` instance created from the raw headers passed in,\nor returns the given headers object if it's already an `AxiosHeaders` instance.\n\n### AxiosHeaders.concat(...targets)\n\n```\nconcat(...targets: Array<AxiosHeaders | RawAxiosHeaders | string | undefined | null>): AxiosHeaders;\n```\n\nReturns a new `AxiosHeaders` instance created by merging the target objects.\n\n### Shortcuts\n\nThe following shortcuts are available:\n\n- `setContentType`, `getContentType`, `hasContentType`\n\n- `setContentLength`, `getContentLength`, `hasContentLength`\n\n- `setAccept`, `getAccept`, `hasAccept`\n\n- `setUserAgent`, `getUserAgent`, `hasUserAgent`\n\n- `setContentEncoding`, `getContentEncoding`, `hasContentEncoding`\n\n## Fetch adapter\n\nAxios introduced the fetch adapter in `v1.7.0`. By default, Axios uses it when the `xhr` and `http` adapters are not available in the build or not supported by the environment.\nTo use it by default, select it explicitly:\n\n```js\nconst { data } = axios.get(url, {\n  adapter: 'fetch', // by default ['xhr', 'http', 'fetch']\n});\n```\n\nYou can create a separate instance for this:\n\n```js\nconst fetchAxios = axios.create({\n  adapter: 'fetch',\n});\n\nconst { data } = fetchAxios.get(url);\n```\n\nThe adapter supports the same features as the `xhr` adapter, including upload and download progress capturing.\nIt also supports response types such as `stream` and `formdata` when the environment supports them.\n\nWhen `auth` is omitted, the fetch adapter can read HTTP Basic auth credentials from the request URL, for example `https://user:pass@example.com`. Percent-encoded URL credentials are decoded before the `Authorization` header is generated, and `auth` takes precedence over URL-embedded credentials.\n\n### Custom fetch\n\nSince `v1.12.0`, you can configure the fetch adapter to use a custom fetch API instead of environment globals.\nPass a custom `fetch` function, `Request`, and `Response` constructors through `env` config.\nThis helps in custom environments and app frameworks.\n\nWhen using a custom fetch, you may also need to set custom `Request` and `Response` constructors. If you do not set them, Axios uses the global objects.\nIf your custom fetch API does not provide these objects and the globals are incompatible with it, pass `null` to disable them inside the fetch adapter.\n\n> Note: Setting `Request` and `Response` to `null` prevents the fetch adapter from capturing upload and download progress.\n\nBasic example:\n\n```js\nimport customFetchFunction from 'customFetchModule';\n\nconst instance = axios.create({\n  adapter: 'fetch',\n  onDownloadProgress(e) {\n    console.log('downloadProgress', e);\n  },\n  env: {\n    fetch: customFetchFunction,\n    Request: null, // undefined -> use the global constructor\n    Response: null,\n  },\n});\n```\n\n#### Using with Tauri\n\nA minimal example of setting up Axios for use in a [Tauri](https://tauri.app/plugin/http-client/) app with a platform fetch function that ignores CORS policy for requests.\n\n```js\nimport { fetch } from '@tauri-apps/plugin-http';\nimport axios from 'axios';\n\nconst instance = axios.create({\n  adapter: 'fetch',\n  onDownloadProgress(e) {\n    console.log('downloadProgress', e);\n  },\n  env: {\n    fetch,\n  },\n});\n\nconst { data } = await instance.get('https://google.com');\n```\n\n#### Using with SvelteKit\n\n[SvelteKit](https://svelte.dev/docs/kit/web-standards#Fetch-APIs) uses a custom fetch function for server rendering in `load` functions. It also uses relative paths, which are incompatible with the standard URL API. Configure Axios to use SvelteKit's custom fetch API:\n\n```js\nexport async function load({ fetch }) {\n  const { data: post } = await axios.get('https://jsonplaceholder.typicode.com/posts/1', {\n    adapter: 'fetch',\n    env: {\n      fetch,\n      Request: null,\n      Response: null,\n    },\n  });\n\n  return { post };\n}\n```\n\n#### HTTP/2 support\n\nAxios supports HTTP/2 through the Node.js `http` adapter, introduced in v1.13.0.\n\nSupport depends on the runtime environment. Axios relies on Node.js APIs, so HTTP/2 works in supported Node.js versions but may not work in other environments such as Bun or Deno.\n\nOptions like `httpVersion` and `http2Options` are adapter-specific and may not behave the same way in every environment.\n\nNote: HTTP/2 redirects are currently not supported by the HTTP/2 adapter.\n\n```js\nconst form = new FormData();\n\nform.append('foo', '123');\n\nconst { data, headers, status } = await axios.post('https://httpbin.org/post', form, {\n  onUploadProgress(e) {\n    console.log('upload progress', e);\n  },\n  onDownloadProgress(e) {\n    console.log('download progress', e);\n  },\n  responseType: 'arraybuffer',\n});\n```\n\n## Semver\n\nAxios follows [semver](https://semver.org/) since `v1.0.0`.\n\n## Promises\n\naxios depends on a native ES6 Promise implementation to be [supported](https://caniuse.com/promises).\nIf your environment doesn't support ES6 Promises, you can [polyfill](https://github.com/jakearchibald/es6-promise).\n\n## TypeScript\n\naxios includes [TypeScript](https://typescriptlang.org) definitions and a type guard for axios errors.\n\n```typescript\nlet user: User = null;\ntry {\n  const { data } = await axios.get('/user?ID=12345');\n  user = data.userDetails;\n} catch (error) {\n  if (axios.isAxiosError(error)) {\n    handleAxiosError(error);\n  } else {\n    handleUnexpectedError(error);\n  }\n}\n```\n\nUse `axios.isCancel<T>()` to narrow cancellation errors to `CanceledError<T>`:\n\n```typescript\nconst controller = new AbortController();\n\ntry {\n  await axios.get<User>('/user?ID=12345', { signal: controller.signal });\n} catch (error) {\n  if (axios.isCancel<User>(error)) {\n    handleCancellation(error);\n  }\n}\n```\n\nBecause axios publishes an ESM default export and a CJS `module.exports`, TypeScript has a few caveats.\nThe recommended setting is `\"moduleResolution\": \"node16\"`, which is implied by `\"module\": \"node16\"`. This requires TypeScript 4.7 or greater.\nIf you use ESM, your settings should be fine.\nIf you compile TypeScript to CJS and can't use `\"moduleResolution\": \"node 16\"`, enable `esModuleInterop`.\nIf you use TypeScript to type check CJS JavaScript code, your only option is to use `\"moduleResolution\": \"node16\"`.\n\nYou can also create a custom instance with typed interceptors:\n\n```typescript\nimport axios, { AxiosInstance, InternalAxiosRequestConfig } from 'axios';\n\nconst apiClient: AxiosInstance = axios.create({\n  baseURL: 'https://api.example.com',\n  timeout: 10000,\n});\n\napiClient.interceptors.request.use((config: InternalAxiosRequestConfig) => {\n  // Add auth token\n  return config;\n});\n```\n\n## Online one-click setup\n\nYou can use Gitpod, a free online IDE for open source projects, to contribute or run the examples online.\n\n[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/axios/axios/blob/main/examples/server.js)\n\n## Contributing\n\n### Local setup\n\nAs a supply-chain hardening measure, this repository ships a project-level `.npmrc` that sets `ignore-scripts=true`. This blocks npm lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency when you run `npm install` or `npm ci` inside the repo. See [THREATMODEL.md](./THREATMODEL.md) (threat T-S2) for the rationale.\n\nOne consequence: the repository's own `prepare` hook (which installs Husky's git hooks) will **not** run automatically. After your first install, enable the git hooks manually:\n\n```bash\nnpm ci\nnpm rebuild husky && npx husky\n```\n\nRun those two commands once per fresh checkout. You do **not** need to re-run them after every subsequent `npm install`.\n\nDo not remove `ignore-scripts=true` from `.npmrc` to \"fix\" this. That reopens the lifecycle-script attack surface for every other package in the tree. All CI workflows already invoke npm with `--ignore-scripts`, so local behaviour matches CI.\n\n## Resources\n\n- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)\n- [Ecosystem](https://github.com/axios/axios/blob/v1.x/ECOSYSTEM.md)\n- [Contributing Guide](https://github.com/axios/axios/blob/v1.x/CONTRIBUTING.md)\n- [Code of Conduct](https://github.com/axios/axios/blob/v1.x/CODE_OF_CONDUCT.md)\n\n## Credits\n\naxios is heavily inspired by the [$http service](https://docs.angularjs.org/api/ng/service/$http) in [AngularJS](https://angularjs.org/). It provides a standalone `$http`-like service for use outside AngularJS.\n\n## License\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n"
      },
      {
        "file": "THREATMODEL.md",
        "absolutePath": "/Users/teja/Documents/Codex/2026-07-17/build/.greenhorn/sources/axios-9d2abce4/THREATMODEL.md",
        "origin": "local",
        "text": "# Axios threat model\n\nThis document describes the threat model for axios: a library used at runtime by millions of applications, and an open-source project with a build pipeline, release infrastructure, and human maintainers.\n\nIt is for maintainers, security researchers, and downstream consumers doing supply chain due diligence. If you find a gap, open a security advisory rather than a public issue.\n\n---\n\n## 1. Scope and methodology\n\nWe model two distinct systems:\n\n| System             | What is being protected                     | Who attacks it                                                    |\n| ------------------ | ------------------------------------------- | ----------------------------------------------------------------- |\n| Runtime            | Applications that `import axios`            | Malicious servers, network attackers, malicious application input |\n| Project / SDLC     | The integrity of what gets published to npm | Supply-chain attackers, phishers, malicious contributors          |\n\nFor each system, we list assets, trust boundaries, threat actors, and threats, rated by likelihood x impact. When mitigations exist in the codebase, we cite the file. When they do not, we say so.\n\nThe runtime model is general by design. axios is a transport library and cannot know what its callers consider sensitive. The project model is specific and actionable.\n\n---\n\n## 2. Runtime threat model\n\n### 2.1 System overview\n\n```\n  ┌─────────────────┐\n  │  Application    │  ← trusted: writes the config, owns the secrets\n  │  (caller code)  │\n  └────────┬────────┘\n           │ axios(config)\n  ┌────────▼────────┐\n  │  Interceptors   │  ← caller-supplied code, runs in-process\n  ├─────────────────┤\n  │  Config merge   │  ← lib/core/mergeConfig.js\n  │  URL build      │  ← lib/core/buildFullPath.js, lib/helpers/buildURL.js\n  │  Header build   │  ← lib/core/AxiosHeaders.js\n  ├─────────────────┤\n  │  Adapter        │  ← http.js / xhr.js / fetch.js\n  └────────┬────────┘\n           │\n  ═════════▼═════════  ← TRUST BOUNDARY (network)\n           │\n  ┌────────▼────────┐\n  │  Proxy (opt.)   │  ← partially trusted (sees plaintext if HTTP)\n  └────────┬────────┘\n  ┌────────▼────────┐\n  │  Origin server  │  ← UNTRUSTED in the general case\n  │  + redirects    │\n  └─────────────────┘\n```\n\n### 2.2 Assets\n\n| Asset                          | Why it matters                                               |\n| ------------------------------ | ------------------------------------------------------------ |\n| Credentials in transit         | `config.auth`, `Authorization` headers, cookies, XSRF tokens |\n| Request/response bodies        | May contain PII, business secrets                            |\n| The caller's process integrity | Prototype pollution can lead to RCE in some downstream gadgets |\n| The caller's internal network  | SSRF can pivot through the host running axios                |\n| Availability                   | Decompression bombs, redirect loops, slow-loris responses    |\n\n### 2.3 Trust boundaries\n\n1. Caller to axios. The caller is fully trusted. Anything the caller passes in `config` is assumed intentional. axios does not defend against a malicious caller; that is a non-goal.\n2. axios to network. Everything past the socket is untrusted: response status, headers, body, redirect `Location`, proxy responses.\n3. axios to environment variables. `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` are read by `proxy-from-env`. An attacker who controls the environment can redirect all traffic. This is treated as trusted because it has the same privilege as the process, but it is a relevant pivot in container-escape and CI scenarios.\n4. Caller-supplied hooks to axios internals. Interceptors, `transformRequest`, `transformResponse`, `paramsSerializer`, `beforeRedirect`, and custom adapters run with full process privilege. axios does not sandbox them.\n\n### 2.4 Threat actors\n\n| Actor                         | Capability                                                                                                           |\n| ----------------------------- | -------------------------------------------------------------------------------------------------------------------- |\n| Malicious server              | Controls every byte of the response. Most common.                                                                    |\n| On-path network attacker      | MITM. Mitigated by TLS unless the caller disabled validation.                                                        |\n| Malicious redirect target     | A trusted server redirects to an attacker. The attacker sees whatever axios forwards.                                |\n| Application user              | Controls part of the request (e.g. a URL path segment, a query param, a header value) via the calling application.   |\n\n### 2.5 Threats\n\n> Severity = Likelihood x Impact, rated for a typical server-side deployment. Browser deployments inherit the browser's same-origin policy and are generally lower risk for SSRF and credential leakage.\n\n---\n\n#### T-R1: SSRF via caller-controlled URL\n\n|                   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |\n| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Application interpolates user input into `config.url` or `config.baseURL`. Attacker supplies `http://169.254.169.254/`, `http://localhost:6379/`, `file://`, `gopher://`, etc.                                                                                                                                                                                                                                                                                                                 |\n| **Likelihood**    | **High.** This is the #1 real-world axios misuse pattern.                                                                                                                                                                                                                                                                                                                                                                                                                                      |\n| **Impact**        | **High.** Cloud metadata theft, internal service access.                                                                                                                                                                                                                                                                                                                                                                                                                                       |\n| **In scope?**     | **Partially.** axios cannot know which URLs the caller intends to allow.                                                                                                                                                                                                                                                                                                                                                                                                                       |\n| **Mitigations**   | • `allowAbsoluteUrls: false` prevents a relative `url` from overriding `baseURL` (`lib/core/buildFullPath.js`). Defaults to `true` for back-compat. <br>• The HTTP adapter only speaks `http:`/`https:`/`file:`/`data:` (Node) or `http:`/`https:`/`file:`/`blob:`/`url:`/`data:` (browser); exotic schemes like `gopher:` are rejected (`lib/platform/node/index.js`, `lib/platform/browser/index.js`). <br>• No built-in host allowlist. Callers must validate destinations themselves. |\n| **Residual risk** | Substantial. This is documented as caller responsibility.                                                                                                                                                                                                                                                                                                                                                                                                                                      |\n\n---\n\n#### T-R2: Credential leakage on cross-origin redirect\n\n|                   |                                                                                                                                                                                                                                                                                                                                                                                                                                          |\n| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Caller sets `Authorization: Bearer …` and requests `https://api.trusted.com/x`. Server responds `302 Location: https://evil.com/`. Does the bearer token go to evil.com?                                                                                                                                                                                                                                                                 |\n| **Likelihood**    | Medium                                                                                                                                                                                                                                                                                                                                                                                                                                   |\n| **Impact**        | High (full credential theft)                                                                                                                                                                                                                                                                                                                                                                                                             |\n| **Mitigations**   | • Node adapter delegates to `follow-redirects@^1.16.0`, which strips `Authorization`, `Cookie`, and `Proxy-Authorization` on cross-host redirects and on HTTPS→HTTP downgrades. <br>• `sensitiveHeaders` lets callers list custom secret-bearing headers (for example `X-API-Key`) that axios strips on cross-origin redirects. <br>• `maxRedirects` defaults to 5; set to `0` to handle redirects manually. <br>• `beforeRedirect` callback allows custom inspection. <br>• Browser adapters (XHR/fetch) delegate to the browser, which applies its own cross-origin credential rules. |\n| **Residual risk** | Low for standard credential headers and configured custom secret headers. We inherit `follow-redirects`' security posture - it is a critical transitive dependency and its CVEs are our CVEs. Callers must list any custom secret headers they want stripped.                                                                                                                                                                                                                                                                                                                 |\n\n---\n\n#### T-R3: Header injection (CRLF)\n\n|                   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |\n| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Application puts user input into a header value: `headers: { 'X-User': req.query.name }`. Attacker supplies `foo\\r\\nX-Injected: bar\\r\\n\\r\\n<body>`. A related surface is multipart per-part headers: attacker-controlled `blob.type` or `blob.name` flowing into the multipart body.                                                                                                                                                                                                                              |\n| **Likelihood**    | Low                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |\n| **Impact**        | Medium to High (request smuggling, response splitting, multipart parser confusion)                                                                                                                                                                                                                                                                                                                                                                                                                          |\n| **Mitigations**   | • `lib/core/AxiosHeaders.js` rejects header values containing `\\r` or `\\n`, and validates header names against an RFC-7230-shaped charset. Node's own `http` module also rejects these. <br>• `lib/helpers/formDataToStream.js` strips CRLF from `value.type` and percent-encodes CRLF/`\"` in `value.name` via `escapeName()` before interpolating them into per-part headers (GHSA-445q-vr5w-6q77). Node's `http` module does not defend here; multipart injection is in body bytes, not request headers. |\n| **Residual risk** | Very low for HTTP headers (defense in depth: axios + Node). Low for multipart body headers (single layer of defense; regressions here would be silent).                                                                                                                                                                                                                                                                                                                                                         |\n\n---\n\n#### T-R4: Prototype pollution, write side (polluting response / merge into a target object)\n\n|                   |                                                                                                                                                                                                                                                                                                                                                                                                   |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Server returns `{\"__proto__\": {\"isAdmin\": true}}`. If axios merged this into an object naively, every `{}` in the process would gain `.isAdmin`.                                                                                                                                                                                                                                                  |\n| **Likelihood**    | Low (requires a downstream gadget to be exploitable)                                                                                                                                                                                                                                                                                                                                              |\n| **Impact**        | High (process-wide state corruption, sometimes RCE)                                                                                                                                                                                                                                                                                                                                               |\n| **Mitigations**   | • `JSON.parse` itself does not pollute (it creates own-properties named `__proto__`, not prototype links). <br>• Internal merge paths filter dangerous keys: `lib/utils.js` and `lib/core/mergeConfig.js` filter `__proto__` / `constructor` / `prototype`; `lib/helpers/formDataToJSON.js` filters `__proto__`. <br>• These were added in response to past advisories. A regression here is a P0. |\n| **Residual risk** | Low, but this is an area of active attacker interest. New merge helpers must go through the same filtering.                                                                                                                                                                                                                                                                                       |\n\n---\n\n#### T-R4b: Prototype pollution, read-side gadgets (polluted `Object.prototype` drives axios behavior)\n\n|                   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |\n| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | A _different_ library in the caller's dependency tree pollutes `Object.prototype` (e.g. `Object.prototype.validateStatus = () => true`). axios code that reads a config property through the prototype chain then picks up the attacker's value and executes the associated behavior. Each reachable property is a distinct **gadget**: `validateStatus` (bypass HTTP error handling), `parseReviver` (silently tamper JSON response bodies), `transport` / `httpAgent` / `lookup` (MITM / intercept), `withXSRFToken` (leak XSRF token cross-origin), `transformResponse` (response replacement), and so on.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |\n| **Likelihood**    | Low to Medium (requires a polluted prototype somewhere in the process, historically common).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |\n| **Impact**        | High. Arbitrary behavior change across every axios call (auth bypass, response tampering, credential leakage). Unlike T-R4, this does not require axios itself to pollute; any polluted process is enough.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |\n| **Mitigations**   | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |\n| **Residual risk** | Low, but the surface is every config property read. Any new code path that reads `config.foo` / `this.foo` / destructures from a merged config must use a `hasOwnProp` guard. The non-goal that axios does not defend a caller with a polluted prototype is narrower than it sounds. The pollution typically comes from a transitive dependency, not from the caller's own intent, and the above mitigations neutralize the reachable gadgets even when the prototype is polluted.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |\n\n---\n\n#### T-R5: Decompression bomb\n\n|                   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Server sends `Content-Encoding: gzip` with a 10 KB body that decompresses to 10 GB.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |\n| **Likelihood**    | Low                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |\n| **Impact**        | Medium (DoS, OOM kill of the calling process)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |\n| **Mitigations**   | • `maxContentLength` bounds the decompressed response size in the Node adapter (`lib/adapters/http.js`), enforced chunk-by-chunk on the decompressed stream for both buffered and `responseType: 'stream'` responses (stream path fixed in GHSA-vf2m-468p-8v99). <br>• `maxBodyLength` bounds the request side, including when `maxRedirects === 0` (previously bypassed). <br>• Both default to `-1` (unlimited). Callers handling untrusted servers should set these. The README carries a top-level \"security notice\" call-out and `docs/pages/misc/security.md` documents the exact mitigation snippet in all four locales. <br>• Decompression uses Node's `zlib`, which streams. Memory is bounded by the limit, not the full expansion. |\n| **Residual risk** | Medium when limits are not configured. The defaults favor compatibility over safety; the reasoning is that tightening the default would silently break every legitimate download larger than whatever cap were chosen.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |\n\n---\n\n#### T-R6: TLS validation bypass\n\n|                   |                                                                                                                                   |\n| ----------------- | --------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Caller passes `httpsAgent: new https.Agent({ rejectUnauthorized: false })` to \"fix\" a certificate error in dev, ships it to prod. |\n| **Likelihood**    | Medium (very common copy-paste anti-pattern)                                                                                      |\n| **Impact**        | High (silent MITM)                                                                                                                |\n| **In scope?**     | **No.** axios delegates TLS entirely to Node's `https` module / the browser. We do not inspect or warn on agent configuration.    |\n| **Mitigations**   | None at the axios layer. Documentation responsibility only.                                                                       |\n| **Residual risk** | High, but explicitly out of scope. This is caller misconfiguration, not an axios vulnerability.                                   |\n\n---\n\n#### T-R7: XSRF token sent cross-origin\n\n|                   |                                                                                                                                                                                       |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Browser deployment. `xsrfCookieName` is set; attacker tricks the app into requesting `https://evil.com` and the XSRF token cookie value is attached as a header.                      |\n| **Likelihood**    | Low                                                                                                                                                                                   |\n| **Impact**        | Medium                                                                                                                                                                                |\n| **Mitigations**   | `lib/helpers/resolveConfig.js` only attaches the XSRF header when `isURLSameOrigin()` passes (or when `withXSRFToken` is explicitly forced). This was the fix for **CVE-2023-45857**. |\n| **Residual risk** | Low. The same-origin check uses the WHATWG `URL` parser (`lib/helpers/isURLSameOrigin.js`), which is robust against parser-differential attacks.                                      |\n\n---\n\n#### T-R8: Sensitive data in error objects\n\n|                   |                                                                                                                                                                                                                                                                                                    |\n| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Request fails. `AxiosError` includes `config`, which includes `config.auth`, `config.headers.Authorization`, `config.httpsAgent` (with embedded client cert/key). Caller logs the error, exposing secrets in logs.                                                                                  |\n| **Likelihood**    | **High**                                                                                                                                                                                                                                                                                           |\n| **Impact**        | Medium to High                                                                                                                                                                                                                                                                                     |\n| **Mitigations**   | `AxiosError.toJSON()` (`lib/core/AxiosError.js`) produces a reduced view, but the live error object still carries the full config by reference.                                                                                                                                                    |\n| **Residual risk** | Medium. Callers using structured loggers that walk object graphs (Winston, Pino with serializers, Sentry) will capture credentials unless they configure redaction. This is a documented risk, not a vulnerability, but it is the most common way axios users leak secrets in practice. |\n\n---\n\n#### T-R9: Proxy environment variable hijack\n\n|                   |                                                                                                                                                                                                                                                                                                                                                                                                  |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| **Description**   | Attacker controls the process environment (compromised CI step, container escape, `.env` injection) and sets `HTTPS_PROXY=http://evil.com:8080`. All axios traffic is now MITM'd.                                                                                                                                                                                                                |\n| **Likelihood**    | Low (requires prior foothold)                                                                                                                                                                                                                                                                                                                                                                    |\n| **Impact**        | High                                                                                                                                                                                                                                                                                                                                                                                             |\n| **Mitigations**   | • `config.proxy: false` disables environment-based proxy detection entirely. <br>• `NO_PROXY` is honored (`lib/helpers/shouldBypassProxy.js`), with recent hardening for CIDR ranges, IPv6 literals, and wildcard patterns to close parser-differential edge cases. <br>• HTTPS through any proxy uses CONNECT tunneling via `https-proxy-agent` so the origin's cert is validated end-to-end and the proxy sees only SNI, never the URL, headers, or body. `Proxy-Authorization` is sent on the CONNECT request only, never on the wrapped TLS-protected request. |\n| **Residual risk** | Low for HTTPS. High for plain HTTP: the proxy sees and can modify everything.                                                                                                                                                                                                                                                                                                                   |\n\n---\n\n#### T-R10: Malicious interceptor / adapter\n\n|                   |                                                                                                                                                        |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| **Description**   | Caller installs a third-party \"axios plugin\" from npm that registers an interceptor exfiltrating every `Authorization` header.                         |\n| **Likelihood**    | Low to Medium                                                                                                                                          |\n| **Impact**        | High                                                                                                                                                   |\n| **In scope?**     | **No.** Interceptors are caller-supplied code running in the caller's process. axios provides the hook; vetting what goes into it is the caller's job. |\n| **Residual risk** | Out of scope, but worth documenting: there is no meaningful difference between `axios.interceptors.request.use(evil)` and `require('evil')`.           |\n\n---\n\n#### T-R11: Form-data recursion DoS (deeply nested input)\n\n|                   |                                                                                                                                                                                                                                                                                                                                                                             |\n| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Caller passes untrusted object input as request `data` in a context that serializes to `multipart/form-data` or `application/x-www-form-urlencoded`. A pathological input with thousands of nesting levels causes `lib/helpers/toFormData.js` to recurse until stack overflow or the process is killed.                                                                     |\n| **Likelihood**    | Low (requires the caller to serialize attacker-controlled object input without validation)                                                                                                                                                                                                                                                                                  |\n| **Impact**        | Medium (DoS, stack overflow / process termination)                                                                                                                                                                                                                                                                                                                          |\n| **Mitigations**   | • `formSerializer.maxDepth` caps recursion depth; default is 100, can be set to `Infinity` to disable. <br>• Exceeding the cap throws `AxiosError` with code `ERR_FORM_DATA_DEPTH_EXCEEDED` rather than crashing the process. <br>• Documented per locale in `docs/pages/advanced/multipart-form-data-format.md` and `docs/pages/advanced/x-www-form-urlencoded-format.md`. |\n| **Residual risk** | Low when callers leave the default in place. Setting `maxDepth: Infinity` reintroduces the risk.                                                                                                                                                                                                                                                                            |\n\n---\n\n### 2.6 Explicit non-goals (runtime)\n\naxios will not:\n\n- Sandbox or validate caller-supplied functions (interceptors, transforms, adapters, serializers).\n- Validate that `config.url` points somewhere \"safe.\" We don't know what safe means for your application.\n- Warn when TLS validation is disabled via a custom agent.\n- Redact `config` from thrown errors. The caller may legitimately need it for retry logic.\n- Defend against a fully compromised caller process (e.g. attacker-controlled code running inside the caller). For the narrower case of a polluted `Object.prototype` arriving via a transitive dependency, axios does defend the reachable config-read gadgets (see T-R4b), but any new config-read path must continue to use `hasOwnProp` guards to stay on this side of the line.\n- Defend against monkey-patched JavaScript or Node.js runtime APIs (`Object.keys`, `http.request`, `ClientRequest.prototype.setHeader`, `fetch`, etc.). If attacker-controlled code is already running in the same process, it can observe or alter requests below axios and this is outside axios' security boundary.\n\n---\n\n## 3. Project / supply chain threat model\n\nThis model protects what gets published as `axios` on npm. A successful attack here compromises every downstream consumer at once. Given axios' install base, this is the higher-risk half of the document.\n\n### 3.1 System overview\n\n```\n  ┌──────────────────┐    ┌──────────────────┐    ┌──────────────────┐\n  │  Maintainer's    │    │  Contributor's   │    │  GitHub.com      │\n  │  workstation     │    │  fork + PR       │    │  (source of      │\n  │                  │    │                  │    │   truth)         │\n  │  ! npm token?    │    │  untrusted code  │    │                  │\n  │  ! SSH keys      │    │                  │    │                  │\n  │  ! GPG keys      │    │                  │    │                  │\n  └────────┬─────────┘    └────────┬─────────┘    └────────▲─────────┘\n           │                       │                       │\n           │  git push             │  PR                   │\n           └───────────────────────┴───────────────────────┘\n                                                           │\n                                              tag push: v1.x.y\n                                                           │\n                                            ┌──────────────▼─────────────┐\n                                            │  GitHub Actions            │\n                                            │  .github/workflows/        │\n                                            │    publish.yml             │\n                                            │                            │\n                                            │  • npm ci --ignore-scripts │\n                                            │  • npm run build           │\n                                            │  • npm publish             │\n                                            │      --provenance          │\n                                            │                            │\n                                            │  OIDC to npm (no token)    │\n                                            └──────────────┬─────────────┘\n                                                           │\n                                            ═══════════════▼═══════════════\n                                                  registry.npmjs.org\n                                                    axios@1.x.y\n                                                  + provenance attestation\n```\n\n### 3.2 Assets\n\n| Asset                                 | Compromise means…                                                                                                                        |\n| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |\n| **The npm `axios` package name**      | Attacker can publish malware as `axios@1.x.y+1`. Game over for the ecosystem.                                                            |\n| **npm publish capability**            | Whether via token, OIDC trust, or account takeover.                                                                                      |\n| **GitHub `axios/axios` write access** | Attacker can push a tag, which triggers publish. Or modify `publish.yml` itself.                                                         |\n| **Maintainer GitHub accounts**        | Transitively grants the above.                                                                                                           |\n| **Maintainer workstation secrets**    | SSH keys (GitHub push), `~/.npmrc` token if present (direct publish), GPG keys (signed commits), cloud creds (lateral movement).         |\n| **Build determinism**                 | If `dist/` doesn't match `lib/`, a backdoor can hide in the minified bundle.                                                             |\n| **Runtime dependency integrity**      | `follow-redirects`, `form-data`, `proxy-from-env`, `https-proxy-agent` ship inside every axios install.                                  |\n\n### 3.3 Trust boundaries\n\n1. Contributor PRs to main branch. PRs from forks are untrusted. CI runs them, but `pull_request` workflows have no access to secrets and use a read-only `GITHUB_TOKEN`.\n2. Main branch to release tag. Pushing to `v1.x` does not publish. Only pushing a `v1.*.*` tag does. Tag push requires write access.\n3. GitHub Actions to npm. This boundary is crossed via OIDC (`id-token: write` to npm trusted publisher). The repo has no long-lived `NPM_TOKEN` secret.\n4. Maintainer workstation to everything else. This is the softest boundary. A maintainer's laptop is a high-value, low-assurance environment. See §3.5.\n\n### 3.4 Threat actors\n\n| Actor                                           | Capability                                                                                                       | Motivation                              |\n| ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | --------------------------------------- |\n| Drive-by contributor                            | Open a PR. No secrets, no write.                                                                                 | Sneak a backdoor past review.           |\n| Compromised dependency                          | Attempt to run code on `npm install` via lifecycle scripts. Blocked on maintainer workstations (project `.npmrc`) and in CI (`--ignore-scripts` on every job). Residual execution path: plugin code under `npm run build` / `test` / `lint`. | Steal tokens, inject into build.        |\n| Phisher                                         | Send convincing emails/DMs. No technical access.                                                                 | Maintainer GitHub/npm credential theft. |\n| Compromised maintainer account                  | Full write. Can push tags. Can edit workflows.                                                                   | Direct publish of malware.              |\n| GitHub / npm insider or platform compromise     | Out of scope. We trust the platforms.                                                                            | -                                       |\n\n### 3.5 Threats\n\n---\n\n#### T-S1: Malicious code in a contributor PR\n\n|                 |                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description** | Attacker opens a PR with a subtle backdoor: an obfuscated payload in a test fixture, a Unicode homoglyph in a comparison, or a malicious `rollup` plugin in the config.                                                                                                                                                                                                                                                                                                |\n| **Likelihood**  | **High** (attempts are constant on high-profile repos)                                                                                                                                                                                                                                                                                                                                                                                                                 |\n| **Impact**      | Critical, _if_ it lands                                                                                                                                                                                                                                                                                                                                                                                                                                                |\n| **Mitigations** | • Mandatory review before merge. <br>• `pull_request` workflows run with no secrets and a read-only token, so a malicious test cannot exfiltrate anything from CI. <br>• `pull_request_target` is not used because it would grant secrets to fork code. <br>• `zizmor` lints workflow files for known-dangerous patterns. <br>• Branch protection on `v1.x`. <br>• Package, lockfile, and GitHub Actions update PRs are maintainer/bot-only; outside-collaborator PRs for those updates are closed. <br>• Path-scoped `.github/CODEOWNERS` flags sensitive paths explicitly: runtime source (`/lib/`, `/index.*`), build/release infrastructure (`rollup.config.js`, `package.json`, `package-lock.json`, `.npmrc`), CI automation (`.github/workflows/`, `.github/dependabot.yml`, `CODEOWNERS` itself), and security-critical docs (`THREATMODEL.md`, `SECURITY.md`). Changes to these paths surface the scoped ownership rule in the PR review UI distinct from the catch-all. The audit trail shows that the PR touched a sensitive path.                                                                                                               |\n| **Gaps**        | • Review is human and fallible. Obfuscated changes to `dist/` (if checked in) or to large test fixtures are hard to spot. <br>• No automated diffing of `lib/` to `dist/` to catch build-output tampering. <br>Single-maintainer constraint: with `@jasonsaayman` as sole owner on every scoped path, CODEOWNERS cannot enforce a second reviewer. Two-person review on sensitive paths remains unavailable until a co-maintainer is added. Path-scoping is pre-staged for that event. |\n\n---\n\n#### T-S2: Compromised dev dependency steals maintainer keys\n\n> Historically the weakest link. The project-level `.npmrc` and hardware-backed maintainer keys materially improve it, but build-tool plugin execution (Rollup/Babel/Vitest/ESLint) is still the top residual investment area. `ignore-scripts` does not affect those tools, and they run whenever a maintainer builds or tests.\n\n|                            |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |\n| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**            | One of the ~45 direct dev dependencies, or one of their thousands of transitive dependencies, is compromised (maintainer account takeover, expired domain re-registration, the usual). It ships a `postinstall` script that reads `~/.npmrc`, `~/.ssh/id_*`, `~/.config/gh/hosts.yml`, `~/.aws/credentials`, `~/.gnupg/` and POSTs them to an attacker. <br><br>The next time a maintainer runs `npm install` on their workstation, the script runs as the maintainer's user, with full filesystem access. No exploit needed. This is npm working as designed. |\n| **Likelihood**             | Medium and rising. This exact pattern has hit `event-stream`, `ua-parser-js`, `coa`, `rc`, `node-ipc`, `@solana/web3.js`, the Ledger connect-kit, the 2024 polyfill.io incident, and dozens more. axios' dev tree includes Babel, Rollup, Gulp, ESLint, Vitest, and Playwright, each pulling hundreds of transitives. The attack surface is enormous and refreshes on every `npm install`.                                                                                                                                                                                   |\n| **Impact**                 | Critical. A stolen npm token with publish rights means direct malware publish. A stolen SSH key with GitHub push rights means tag push, then publish via CI. Either path ends the same way.                                                                                                                                                                                                                                                                                                                                                                                |\n| **Current mitigations**    | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build. <br>• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal. <br>• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update. <br>• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency. <br>• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README \"Contributing / Local setup\" section.                                                                     |\n| **Gaps: workstation**      | `ignore-scripts=true` neutralizes the lifecycle-script path, but it does not neutralize build-time code execution. A malicious Rollup / Babel / Terser / ESLint / Vitest plugin still runs when a maintainer executes `npm run build` / `npm test` / `npm run lint`. Those are not lifecycle scripts; they are tools the maintainer explicitly invoked. <br><br>The lockfile pins which packages install, but if one of those pinned packages was already malicious when the lock was generated, or the maintainer runs `npm update` / `npm install <new-pkg>` without re-setting `ignore-scripts`, fresh lifecycle scripts can land. <br><br>The development environment still has full read access to every credential the maintainer's user can read once a build tool runs. Isolation (devcontainer / VM) remains the strongest control.                                                                                                                                      |\n\nMitigations adopted and recommended. Adopted items are enforced via the repo; others depend on per-maintainer discipline.\n\n1. Don't keep a publish-capable npm token on your workstation.\n   Publishing happens via GitHub Actions OIDC. There is no workflow that requires `npm publish` from a laptop. If `~/.npmrc` has a token, it should be read-only or scoped to unrelated packages. If there is nothing to steal, this attack path is defanged.\n\n2. Run `npm install` / `npm ci` with `--ignore-scripts` locally. Adopted: project ships a `.npmrc` with `ignore-scripts=true`.\n   All `npm install` / `npm ci` runs in a contributor or maintainer checkout skip lifecycle scripts by default. To set up git hooks after install, run the one trusted script manually:\n\n   ```\n   npm rebuild husky && npx husky\n   ```\n\n   The minor inconvenience of manually running known-good post-install steps is the price of not running thousands of unknown ones. Contributors adding a new dev dependency must not override this flag.\n\n3. Develop in an isolated environment.\n   A devcontainer, VM, or sandbox profile that does not have:\n   - `~/.ssh/` mounted (use a separate deploy key or SSH agent forwarding only when pushing)\n   - `~/.npmrc` with publish tokens\n   - `~/.config/gh/` with a `repo`-scoped GitHub token\n   - `~/.aws/`, `~/.config/gcloud/`, etc.\n\n   The dev environment should be able to read/write the repo working tree and reach the network for tests. Nothing else.\n\n4. Use hardware-backed keys for GitHub. Adopted project-wide.\n   All maintainers use FIDO2/WebAuthn for GitHub auth and `sk-ssh-ed25519@openssh.com` for git push. A stolen `~/.ssh/id_ed25519_sk` is useless without the physical key. This converts \"steal a file\" into \"steal a file and a physical object.\" Each maintainer should keep a backup key registered and stored separately.\n\n5. Audit lockfile diffs on dependency-update PRs as carefully as code.\n   A 4000-line `package-lock.json` diff hides a lot. Tooling: `npm diff`, `lockfile-lint`, Socket.dev's PR integration. Pay particular attention to new packages with install scripts (`hasInstallScript: true` in the lockfile).\n\n6. Don't add dev dependencies casually.\n   Each one is a recurring trust decision delegated to a stranger. Prefer tools that can run via `npx` on demand (not in `node_modules`) or that are already in the tree.\n\n---\n\n#### T-S3: Phishing to maintainer account takeover\n\n|                 |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description** | Maintainer receives a convincing email: <br>• \"npm security alert: your axios package has been flagged, log in to verify ownership\" links to a fake npm login; password + TOTP are captured and replayed in real time. <br>• \"GitHub: @axios has been added to a new organization, review access\" links to a fake GitHub OAuth consent screen; the attacker app gets `repo` scope. <br>• Social: a \"recruiter\" asks the maintainer to clone and `npm install` a \"take-home assignment\" repo. <br><br>npm and GitHub credentials for axios maintainers have been specifically targeted by these campaigns in the past. This is not theoretical. |\n| **Likelihood**  | High. These campaigns are continuous.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |\n| **Impact**      | Critical. GitHub account to push tag to publish. npm account to publish directly.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |\n| **Mitigations** | • npm 2FA is required for publish on the `axios` package. <br>• OIDC publishing means there is no maintainer npm session involved in a normal release. This narrows the attack to GitHub. <br>• All maintainers authenticate to GitHub with hardware-backed WebAuthn/passkeys (FIDO2 security keys / platform authenticators). Origin-bound credentials cannot be relayed by a phishing proxy (Evilginx, Modlishka). TOTP alone is not permitted for maintainer accounts. <br>• Git push uses `sk-ssh-ed25519@openssh.com` hardware-resident SSH keys where supported. A stolen key file is useless without the physical device.                                                                                                                           |\n| **Gaps**        | • Enforcement is per-account policy, not verifiable from the repo itself. Onboarding/offboarding checklist should confirm hardware-key status. <br>• Incident-response runbook is documented in §3.7 and needs periodic rehearsal to stay useful. <br>• Each maintainer should register at least 2 hardware keys (primary + backup stored separately) to avoid lockout-driven fallback to weaker recovery methods.                                                                                                                                                                                                                                                                                                                                                             |\n\n---\n\n#### T-S4: Compromised runtime dependency\n\n|                 |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| **Description** | `follow-redirects`, `form-data`, `proxy-from-env`, or `https-proxy-agent` ships a malicious version. Unlike T-S2, this code ends up in the published axios bundle / runtime rather than being limited to maintainer machines. Every axios consumer runs it.                                                                                                                                                                                                                                                                                                                                                                                            |\n| **Likelihood**  | Low (only 4 deps; all are mature, narrowly-scoped, and watched)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |\n| **Impact**      | Critical                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |\n| **Mitigations** | • Three runtime deps total, minimal by design. <br>• `^` ranges in `package.json` mean consumers may get newer patch versions than the lockfile pins. This is intentional, because consumers get security fixes, but it also means a malicious patch release of `follow-redirects` propagates without an axios release. <br>• `follow-redirects` is security-conscious and well-maintained; we track its advisories closely (multiple past axios releases were just `follow-redirects` bumps). <br>• Dependabot is configured (`.github/dependabot.yml`) for both npm and GitHub Actions, running weekly with grouped updates for production and development dependencies. The 7-day cooldown stays in place unless a critical vulnerability requires a maintainer-led manual update. |\n| **Gaps**        | • No vendoring/inlining considered. The deps are small enough that vendoring is plausible, but it would forfeit upstream security fixes. Current judgment: not worth it.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |\n\n---\n\n#### T-S5: Build-output tampering (`dist/` != `lib/`)\n\n|                 |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |\n| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description** | The published tarball contains a `dist/axios.min.js` that does not match what `rollup` would produce from `lib/`. Nobody reads minified bundles. A backdoor here is invisible to source review. <br><br>Vectors: a malicious dev-dep Rollup/Babel/Terser plugin injects code at build time (T-S2 applied to CI), or a maintainer with a compromised workstation accidentally publishes a tampered local build.                                                                                                                                                                                                                                                                                                        |\n| **Likelihood**  | Low                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |\n| **Impact**      | Critical                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |\n| **Mitigations** | • Builds run only in CI as part of `publish.yml`, from a clean `npm ci --ignore-scripts` checkout. There is no \"publish from laptop\" path. <br>• `--ignore-scripts` means a malicious dev dependency cannot tamper with `node_modules` before the build, but it can still tamper during the build if it is a Rollup/Babel plugin. Those run as part of `npm run build`, not as lifecycle scripts. <br>• npm provenance (`--provenance`) cryptographically attests which workflow on which commit produced the tarball. Consumers can verify with `npm audit signatures`. This proves the build ran in GitHub Actions on a known SHA. It does not prove the build is correct, only that it is traceable. |\n| **Gaps**        | • The build is not currently reproducible in the strict sense. A third party cannot independently rebuild and get a byte-identical `dist/`. Timestamps, plugin ordering, and minifier nondeterminism would need to be locked down. <br>• `.github/workflows/verify-build-reproducibility.yml` performs a two-pass build-and-diff on PRs that touch build-related paths (`lib/**`, `rollup.config.js`, `package.json`, `package-lock.json`, and the workflow itself). It is currently non-blocking (`continue-on-error: true`). It surfaces divergence in the CI summary so reproducibility regressions are visible, without gating merges until the build is deterministic. Once divergence is eliminated, remove `continue-on-error` to promote this to a hard gate. |\n\n---\n\n#### T-S6: Workflow file tampering\n\n|                 |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description** | Attacker with write access (or a merged PR that was not reviewed carefully) modifies `.github/workflows/publish.yml` to `curl` the OIDC token somewhere, or to add a step that patches `dist/` after the build.                                                                                                                                                                                                                                                                                                                           |\n| **Likelihood**  | Low                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |\n| **Impact**      | Critical                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |\n| **Mitigations** | • All actions are pinned to full commit SHAs, not tags: `actions/checkout@de0fac...`, not `@v6`. A compromised action tag can't silently change behavior. <br>• `permissions:` are minimal (`contents: read`, `id-token: write`). <br>• `persist-credentials: false` on checkout, so the build steps cannot push back to the repo. <br>• `zizmor` lints workflows on every PR and push to `v1.x` (`.github/workflows/zizmor.yml`); results surface as GitHub code-scanning alerts via the `security-events: write` permission on that job. This job must remain in the required-checks set on `v1.x` branch protection for the mitigation to be binding. <br>• The `npm-publish` GitHub Environment can require designated reviewers before the job runs; a tampered workflow still pauses for human approval. <br>• CODEOWNERS carries a path-scoped rule for `/.github/workflows/` and `/.github/CODEOWNERS` itself, so workflow and ownership changes surface in the review UI as touching a scoped path rather than being folded into the default approval. |\n| **Gaps**        | • Single-maintainer constraint (see T-S1): with one owner, the path-scoped rule cannot enforce a second reviewer on workflow changes. The rule surfaces the sensitivity but does not block single-maintainer approval. Closing this requires adding a co-maintainer.                                                                                                                                                                                                          |\n\n---\n\n#### T-S7: Tag confusion / replay\n\n|                 |                                                                                                                                                                                                                                                                                                      |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description** | Attacker with write access force-pushes an existing tag to point at a malicious commit, or pushes `v1.99.99` so that a release is published out of band.                                                                                                                                             |\n| **Likelihood**  | Low (requires write access; assumed compromised at that point)                                                                                                                                                                                                                                      |\n| **Impact**      | High                                                                                                                                                                                                                                                                                                 |\n| **Mitigations** | • npm rejects re-publishing an existing version. Re-tagging cannot overwrite the published `1.15.0`. <br>• Provenance attestation records the commit SHA the tag pointed to at publish time, which is forensically verifiable. Consumers can confirm with `npm audit signatures axios` (documented in SECURITY.md). <br>• Tag protection rules: repository setting must forbid tag deletion and force-push for the `v1.*.*` pattern. This is a GitHub UI setting (Settings > Tags > rulesets), not file-based; enforcement is auditable via the Rulesets REST API. |\n| **Gaps**        | A new malicious version (`v1.x.x`) is still publishable by anyone with tag-push rights. This collapses back into T-S3 (account security).                                                                                                                                                           |\n\n---\n\n#### T-S8: Typosquatting / dependency confusion\n\n|                 |                                                                                                                                                                                                                                                                                      |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| **Description** | Attacker publishes `axois`, `axios-http`, `@axios/core`, etc., and waits for typos. Or publishes a package shadowing an internal name used in a consumer's monorepo.                                                                                                                 |\n| **Likelihood**  | High (these packages already exist)                                                                                                                                                                                                                                                  |\n| **Impact**      | Medium. Affects confused consumers, not axios itself                                                                                                                                                                                                                                  |\n| **In scope?**   | Mostly out of scope; the axios project cannot police the npm namespace.                                                                                                                                                                                                              |\n| **Mitigations** | • npm has typosquat detection at publish time (imperfect). <br>• The `@axios/` npm scope is not owned by the project. `@axios/anything` can be registered by anyone. This is a gap, not a mitigation. <br>• Provenance gives consumers a way to verify they got the real thing. |\n\n---\n\n### 3.6 Summary: project risk posture\n\n| Threat                       | Likelihood | Impact       | Current Posture | Priority Gap                                                          |\n| ---------------------------- | ---------- | ------------ | --------------- | --------------------------------------------------------------------- |\n| T-S1 Malicious PR            | High       | Critical     | Good         | Second maintainer to enable two-person review on scoped paths         |\n| T-S2 Dev-dep steals keys     | Medium     | Critical     | Partial      | Isolated dev environment (devcontainer/VM); no publish tokens on workstations. Lifecycle scripts now blocked via project `.npmrc`, but build-tool plugins still execute |\n| T-S3 Phishing                | High       | Critical     | Good         | Document phish-response runbook; require registered backup hardware key |\n| T-S4 Runtime dep compromise  | Low        | Critical     | Good         | -                                                                     |\n| T-S5 Build tampering         | Low        | Critical     | Adequate     | Eliminate build non-determinism, then promote reproducibility check to blocking |\n| T-S6 Workflow tampering      | Low        | Critical     | Good         | Second maintainer (two-person review) for `/.github/workflows/`       |\n| T-S7 Tag replay              | Low        | High         | Good         | -                                                                     |\n| T-S8 Typosquat               | High       | Medium       | Out of scope | -                                                                     |\n\nThe top remaining investment is T-S2 (dev-dependency compromise of maintainer workstations). Lifecycle-script execution is now blocked by the project-level `.npmrc`, and T-S3 phishing risk dropped materially once all maintainers moved to hardware-backed WebAuthn. Real-time credential relay no longer works. The residual T-S2 gap is build-tool plugin execution (Rollup/Babel/Vitest/ESLint), which `ignore-scripts` does not cover. Closing it requires running builds in an isolated environment without access to long-lived credentials.\n\n---\n\n### 3.7 Incident response runbook\n\nIf a maintainer suspects credential compromise (phish clicked, lost hardware key, unexpected tag/publish, leaked token in logs), execute the steps below in order. Speed matters more than completeness. A published malicious version affects every downstream consumer.\n\n#### 1. Contain, minutes 0 to 15\n\n- GitHub: revoke all active sessions (`https://github.com/settings/sessions`), revoke all OAuth/PAT tokens (`/settings/tokens`, `/settings/applications`), review authorized SSH keys and remove any unrecognised. If a PAT with `repo` or `admin:org` scope existed, assume leak.\n- npm: run `npm token list` and `npm token revoke <token>` for any publish-capable token. If no CLI access, revoke via `https://www.npmjs.com/settings/<user>/tokens`. Rotate npm password and force sign-out of all sessions.\n- Workstation: if a build/install ran malicious code, assume full-user compromise of the laptop. Unplug from trusted networks. Do not rely on AV; move to a clean machine for rotation steps.\n\n#### 2. Assess, minutes 15 to 60\n\n- Check `https://github.com/axios/axios/settings/security-log` and `https://github.com/<maintainer>/security/log` for unrecognised events (key adds, org changes, force-pushes, new tags).\n- Verify recent tags match intent: `git log --tags --oneline -n 20`. Compare with `https://www.npmjs.com/package/axios?activeTab=versions`.\n- For each recent publish, verify provenance: `npm audit signatures axios@<version>` and cross-check the `sourceCommit` in the provenance attestation against the tag's SHA. Divergence = investigate.\n- Review `~/.npmrc`, `~/.ssh/`, `~/.config/gh/hosts.yml`, `~/.gnupg/` for tampering and unexpected files.\n\n#### 3. Rotate, hour 1 to 4\n\n- Generate new SSH keys on clean hardware. Remove old keys from GitHub. If using `sk-ssh-ed25519@openssh.com`, register new hardware key first, then deregister the old one. Do not leave the account with zero registered keys.\n- Re-enrol WebAuthn authenticators (both primary and backup). Deregister lost/compromised authenticators.\n- Rotate GPG keys if signed commits are used; upload new key to GitHub.\n- Rotate any cloud credentials (`~/.aws/`, `~/.config/gcloud/`) and any tokens present on the compromised machine.\n\n#### 4. Notify, hour 1 onward\n\n- npm security: `security@npmjs.com`. Include package name, suspected versions, timeline.\n- GitHub security: `https://github.com/contact`, Security category. Request an investigation of the account.\n- Downstream: open a GitHub security advisory (`https://github.com/axios/axios/security/advisories/new`) as soon as a malicious version is confirmed published. Do not wait for a fix. Users need to pin away from the bad version.\n- Co-maintainers (when present): notify via out-of-band channel (phone/Signal), not through the compromised channel.\n\n#### 5. Unpublish / deprecate, hour 1 to 24\n\n- npm allows `npm unpublish <pkg>@<version>` within 72 hours of publish. After that, use `npm deprecate <pkg>@<version> \"<reason>\"` with a message pointing to the advisory.\n- Publish a patched version that bumps semver above the malicious one, so `^` consumers move forward automatically.\n\n#### 6. Post-mortem, within 1 week\n\n- Write up timeline: initial vector, dwell time, scope, mitigations applied.\n- Update this threat model if the incident reveals a gap not captured here.\n- File a PR if any mitigation can be codified (new CI check, new lint rule, new CODEOWNERS path).\n\nKeep this runbook current. A runbook no one has rehearsed is a document, not a control.\n\n---\n\n_This document describes intent and current understanding. It does not constitute a security guarantee. To report a gap in the model itself, use the same private advisory channel as for code vulnerabilities._\n"
      }
    ],
    "maxDepth": 2,
    "maxDocs": 6,
    "truncated": false,
    "followExternalDocs": false,
    "externalFailures": [],
    "commandMentions": [
      {
        "command": "import",
        "citation": "Once the package is installed, import it with `import` or `require`:",
        "file": "README.md"
      },
      {
        "command": "require",
        "citation": "Once the package is installed, import it with `import` or `require`:",
        "file": "README.md"
      },
      {
        "command": "require",
        "citation": "If you use `require` for importing, **only the default export is available**:",
        "file": "README.md"
      },
      {
        "command": "async",
        "citation": "// Want to use async/await? Add the `async` keyword to your outer function/method.",
        "file": "README.md"
      },
      {
        "command": "params",
        "citation": "// Using the `params` option improves readability and automatically formats query strings",
        "file": "README.md"
      },
      {
        "command": "timeout",
        "citation": "> Note: Set a `timeout` in production. Without one, a stalled request can hang",
        "file": "README.md"
      },
      {
        "command": "POST",
        "citation": "Performing a `POST` request",
        "file": "README.md"
      },
      {
        "command": "axios",
        "citation": "Requests can be made by passing the relevant config to `axios`.",
        "file": "README.md"
      },
      {
        "command": "url",
        "citation": "When using the alias methods `url`, `method`, and `data` properties don't need to be specified in config.",
        "file": "README.md"
      },
      {
        "command": "method",
        "citation": "When using the alias methods `url`, `method`, and `data` properties don't need to be specified in config.",
        "file": "README.md"
      },
      {
        "command": "data",
        "citation": "When using the alias methods `url`, `method`, and `data` properties don't need to be specified in config.",
        "file": "README.md"
      },
      {
        "command": "Promise.all",
        "citation": "Use `Promise.all` instead of these helpers.",
        "file": "README.md"
      },
      {
        "command": "maxContentLength",
        "citation": "By default `maxContentLength` and `maxBodyLength` are `-1` (unlimited). A malicious or compromised server can return a tiny gzip/deflate/brotli/zstd body that expands to gigabytes and exhaust the Node.js process.",
        "file": "README.md"
      },
      {
        "command": "maxBodyLength",
        "citation": "By default `maxContentLength` and `maxBodyLength` are `-1` (unlimited). A malicious or compromised server can return a tiny gzip/deflate/brotli/zstd body that expands to gigabytes and exhaust the Node.js process.",
        "file": "README.md"
      },
      {
        "command": "-1",
        "citation": "By default `maxContentLength` and `maxBodyLength` are `-1` (unlimited). A malicious or compromised server can return a tiny gzip/deflate/brotli/zstd body that expands to gigabytes and exhaust the Node.js process.",
        "file": "README.md"
      },
      {
        "command": "url",
        "citation": "These config options are available for requests. Only `url` is required. Requests default to `GET` when `method` is not set.",
        "file": "README.md"
      },
      {
        "command": "GET",
        "citation": "These config options are available for requests. Only `url` is required. Requests default to `GET` when `method` is not set.",
        "file": "README.md"
      },
      {
        "command": "method",
        "citation": "These config options are available for requests. Only `url` is required. Requests default to `GET` when `method` is not set.",
        "file": "README.md"
      },
      {
        "command": "url",
        "citation": "// `url` is the server URL for the request",
        "file": "README.md"
      },
      {
        "command": "method",
        "citation": "// `method` is the request method to be used when making the request",
        "file": "README.md"
      },
      {
        "command": "baseURL",
        "citation": "// Axios prepends `baseURL` to `url` unless `url` is absolute and `allowAbsoluteUrls` is set to true.",
        "file": "README.md"
      },
      {
        "command": "url",
        "citation": "// Axios prepends `baseURL` to `url` unless `url` is absolute and `allowAbsoluteUrls` is set to true.",
        "file": "README.md"
      },
      {
        "command": "url",
        "citation": "// Axios prepends `baseURL` to `url` unless `url` is absolute and `allowAbsoluteUrls` is set to true.",
        "file": "README.md"
      },
      {
        "command": "allowAbsoluteUrls",
        "citation": "// Axios prepends `baseURL` to `url` unless `url` is absolute and `allowAbsoluteUrls` is set to true.",
        "file": "README.md"
      },
      {
        "command": "baseURL",
        "citation": "// It can be convenient to set `baseURL` for an instance of axios to pass relative URLs",
        "file": "README.md"
      },
      {
        "command": "baseURL",
        "citation": "// `baseURL` is not a security boundary. If `url` is attacker-controlled, validate it",
        "file": "README.md"
      },
      {
        "command": "url",
        "citation": "// `baseURL` is not a security boundary. If `url` is attacker-controlled, validate it",
        "file": "README.md"
      },
      {
        "command": "..",
        "citation": "// before passing it to axios. Relative URLs can contain `..` segments that resolve",
        "file": "README.md"
      },
      {
        "command": "allowAbsoluteUrls",
        "citation": "// `allowAbsoluteUrls` determines whether or not absolute URLs will override a configured `baseUrl`.",
        "file": "README.md"
      },
      {
        "command": "baseUrl",
        "citation": "// `allowAbsoluteUrls` determines whether or not absolute URLs will override a configured `baseUrl`.",
        "file": "README.md"
      },
      {
        "command": "url",
        "citation": "// When set to true (default), absolute values for `url` will override `baseUrl`.",
        "file": "README.md"
      },
      {
        "command": "baseUrl",
        "citation": "// When set to true (default), absolute values for `url` will override `baseUrl`.",
        "file": "README.md"
      },
      {
        "command": "url",
        "citation": "// When set to false, absolute values for `url` will always be prepended by `baseUrl`.",
        "file": "README.md"
      },
      {
        "command": "baseUrl",
        "citation": "// When set to false, absolute values for `url` will always be prepended by `baseUrl`.",
        "file": "README.md"
      },
      {
        "command": "transformRequest",
        "citation": "// `transformRequest` allows changes to the request data before it is sent to the server",
        "file": "README.md"
      },
      {
        "command": "transformResponse",
        "citation": "// `transformResponse` allows changes to the response data to be made before",
        "file": "README.md"
      },
      {
        "command": "parseReviver",
        "citation": "// `parseReviver` is an optional function passed as the",
        "file": "README.md"
      },
      {
        "command": "headers",
        "citation": "// `headers` are custom headers to be sent",
        "file": "README.md"
      },
      {
        "command": "params",
        "citation": "// `params` are the URL parameters to be sent with the request",
        "file": "README.md"
      },
      {
        "command": "paramsSerializer",
        "citation": "// `paramsSerializer` is an optional config that allows you to customize serializing `params`.",
        "file": "README.md"
      },
      {
        "command": "params",
        "citation": "// `paramsSerializer` is an optional config that allows you to customize serializing `params`.",
        "file": "README.md"
      },
      {
        "command": "data",
        "citation": "// `data` is the data to be sent as the request body",
        "file": "README.md"
      },
      {
        "command": "data",
        "citation": "// `data` is request-specific: axios does not inherit or deep-merge it from defaults.",
        "file": "README.md"
      },
      {
        "command": "transformRequest",
        "citation": "// When no `transformRequest` is set, it must be of one of the following types:",
        "file": "README.md"
      },
      {
        "command": "formDataHeaderPolicy",
        "citation": "// `formDataHeaderPolicy` controls how node.js FormData#getHeaders() is copied.",
        "file": "README.md"
      },
      {
        "command": "timeout",
        "citation": "// `timeout` specifies the number of milliseconds before the request times out.",
        "file": "README.md"
      },
      {
        "command": "timeout",
        "citation": "// If the request takes longer than `timeout`, Axios aborts it.",
        "file": "README.md"
      },
      {
        "command": "0",
        "citation": "timeout: 1000, // default is `0` (no timeout)",
        "file": "README.md"
      },
      {
        "command": "withCredentials",
        "citation": "// `withCredentials` indicates whether or not cross-site Access-Control requests",
        "file": "README.md"
      },
      {
        "command": "adapter",
        "citation": "// `adapter` allows custom handling of requests which makes testing easier.",
        "file": "README.md"
      },
      {
        "command": "auth",
        "citation": "// `auth` indicates that HTTP Basic auth should be used, and supplies credentials.",
        "file": "README.md"
      },
      {
        "command": "Authorization",
        "citation": "// This will set an `Authorization` header, overwriting any existing",
        "file": "README.md"
      },
      {
        "command": "Authorization",
        "citation": "// `Authorization` custom headers you have set using `headers`.",
        "file": "README.md"
      },
      {
        "command": "headers",
        "citation": "// `Authorization` custom headers you have set using `headers`.",
        "file": "README.md"
      },
      {
        "command": "auth",
        "citation": "// If `auth` is omitted, the Node.js HTTP and fetch adapters can read",
        "file": "README.md"
      },
      {
        "command": "auth",
        "citation": "// credentials, and `auth` takes precedence over URL-embedded credentials.",
        "file": "README.md"
      },
      {
        "command": "Authorization",
        "citation": "// For Bearer tokens and such, use `Authorization` custom headers instead.",
        "file": "README.md"
      },
      {
        "command": "responseType",
        "citation": "// `responseType` indicates the type of data that the server will respond with",
        "file": "README.md"
      },
      {
        "command": "responseEncoding",
        "citation": "// `responseEncoding` indicates encoding to use for decoding responses (Node.js only)",
        "file": "README.md"
      },
      {
        "command": "responseType",
        "citation": "// Note: Ignored for `responseType` of 'stream' or client-side requests",
        "file": "README.md"
      },
      {
        "command": "xsrfCookieName",
        "citation": "// `xsrfCookieName` is the name of the cookie to use as a value for the xsrf token",
        "file": "README.md"
      },
      {
        "command": "xsrfHeaderName",
        "citation": "// `xsrfHeaderName` is the name of the http header that carries the xsrf token value",
        "file": "README.md"
      },
      {
        "command": "withXSRFToken",
        "citation": "// `withXSRFToken` defines whether to send the XSRF header in browser requests.",
        "file": "README.md"
      },
      {
        "command": "undefined",
        "citation": "// `undefined` (default) - set XSRF header only for the same origin requests",
        "file": "README.md"
      },
      {
        "command": "true",
        "citation": "// `true` - always set XSRF header, including for cross-origin requests",
        "file": "README.md"
      },
      {
        "command": "false",
        "citation": "// `false` - never set XSRF header",
        "file": "README.md"
      },
      {
        "command": "withXSRFToken",
        "citation": "// `withXSRFToken` controls whether Axios reads the XSRF cookie and sets the XSRF header.",
        "file": "README.md"
      },
      {
        "command": "undefined",
        "citation": "// - `undefined` (default): the XSRF header is set only for same-origin requests.",
        "file": "README.md"
      },
      {
        "command": "true",
        "citation": "// - `true`: attempt to set the XSRF header for all requests (including cross-origin).",
        "file": "README.md"
      },
      {
        "command": "false",
        "citation": "// - `false`: never set the XSRF header.",
        "file": "README.md"
      },
      {
        "command": "config",
        "citation": "// - function: a callback that receives the request `config` and returns `true`,",
        "file": "README.md"
      },
      {
        "command": "true",
        "citation": "// - function: a callback that receives the request `config` and returns `true`,",
        "file": "README.md"
      },
      {
        "command": "false",
        "citation": "// `false`, or `undefined` to decide per-request behavior.",
        "file": "README.md"
      },
      {
        "command": "undefined",
        "citation": "// `false`, or `undefined` to decide per-request behavior.",
        "file": "README.md"
      },
      {
        "command": "withCredentials",
        "citation": "// Note about `withCredentials`: `withCredentials` controls whether cross-site",
        "file": "README.md"
      },
      {
        "command": "withCredentials",
        "citation": "// Note about `withCredentials`: `withCredentials` controls whether cross-site",
        "file": "README.md"
      },
      {
        "command": "withCredentials: true",
        "citation": "// setting `withCredentials: true` implicitly caused Axios to set the XSRF header",
        "file": "README.md"
      },
      {
        "command": "withCredentials: true",
        "citation": "// `withCredentials: true` and `withXSRFToken: true`.",
        "file": "README.md"
      },
      {
        "command": "withXSRFToken: true",
        "citation": "// `withCredentials: true` and `withXSRFToken: true`.",
        "file": "README.md"
      },
      {
        "command": "onUploadProgress",
        "citation": "// `onUploadProgress` allows handling of progress events for uploads",
        "file": "README.md"
      },
      {
        "command": "onDownloadProgress",
        "citation": "// `onDownloadProgress` allows handling of progress events for downloads",
        "file": "README.md"
      },
      {
        "command": "maxContentLength",
        "citation": "// `maxContentLength` defines the max size of the response content in bytes.",
        "file": "README.md"
      },
      {
        "command": "maxBodyLength",
        "citation": "// `maxBodyLength` defines the max size of the request content in bytes.",
        "file": "README.md"
      },
      {
        "command": "redact",
        "citation": "// `redact` masks matching config keys when AxiosError#toJSON() is called.",
        "file": "README.md"
      },
      {
        "command": "validateStatus",
        "citation": "// `validateStatus` defines whether to resolve or reject the promise for a given",
        "file": "README.md"
      },
      {
        "command": "validateStatus",
        "citation": "// HTTP response status code. If `validateStatus` returns `true` or is set to",
        "file": "README.md"
      },
      {
        "command": "true",
        "citation": "// HTTP response status code. If `validateStatus` returns `true` or is set to",
        "file": "README.md"
      },
      {
        "command": "null",
        "citation": "// `null`, Axios resolves the promise; otherwise, Axios rejects it.",
        "file": "README.md"
      },
      {
        "command": "validateStatus: undefined",
        "citation": "// Explicit `validateStatus: undefined` resolves every status by default for",
        "file": "README.md"
      },
      {
        "command": "transitional.validateStatusUndefinedResolves",
        "citation": "// backward compatibility. Set `transitional.validateStatusUndefinedResolves`",
        "file": "README.md"
      },
      {
        "command": "false",
        "citation": "// to `false` to make explicit `undefined` behave as if this option was omitted.",
        "file": "README.md"
      },
      {
        "command": "undefined",
        "citation": "// to `false` to make explicit `undefined` behave as if this option was omitted.",
        "file": "README.md"
      },
      {
        "command": "maxRedirects",
        "citation": "// `maxRedirects` defines the maximum number of redirects to follow in node.js.",
        "file": "README.md"
      },
      {
        "command": "sensitiveHeaders",
        "citation": "// `sensitiveHeaders` (Node only option) lists custom secret-bearing headers",
        "file": "README.md"
      },
      {
        "command": "X-API-Key",
        "citation": "// (such as `X-API-Key`) to remove from cross-origin redirects. Matching is",
        "file": "README.md"
      },
      {
        "command": "maxRedirects",
        "citation": "// `maxRedirects` is 0, this option is not used.",
        "file": "README.md"
      },
      {
        "command": "beforeRedirect",
        "citation": "// `beforeRedirect` defines a function that Axios calls before redirect.",
        "file": "README.md"
      },
      {
        "command": "beforeRedirect",
        "citation": "// If maxRedirects is set to 0, `beforeRedirect` is not used.",
        "file": "README.md"
      },
      {
        "command": "beforeRedirect",
        "citation": "// The `beforeRedirect` hook runs after sensitive headers are stripped during redirects.",
        "file": "README.md"
      },
      {
        "command": "follow-redirects",
        "citation": "// `follow-redirects` removes credentials on protocol downgrades",
        "file": "README.md"
      },
      {
        "command": "beforeRedirect",
        "citation": "// (HTTPS to HTTP). Because `beforeRedirect` runs after that step,",
        "file": "README.md"
      },
      {
        "command": "socketPath",
        "citation": "// `socketPath` defines a UNIX Socket to be used in node.js.",
        "file": "README.md"
      },
      {
        "command": "socketPath",
        "citation": "// Only either `socketPath` or `proxy` can be specified.",
        "file": "README.md"
      },
      {
        "command": "proxy",
        "citation": "// Only either `socketPath` or `proxy` can be specified.",
        "file": "README.md"
      },
      {
        "command": "socketPath",
        "citation": "// If both are specified, `socketPath` is used.",
        "file": "README.md"
      },
      {
        "command": "socketPath",
        "citation": "// Security: when `socketPath` is set, hostname/port of the URL are ignored,",
        "file": "README.md"
      },
      {
        "command": "socketPath",
        "citation": "// which bypasses hostname-based SSRF protections. Never derive `socketPath`",
        "file": "README.md"
      },
      {
        "command": "allowedSocketPaths",
        "citation": "// from untrusted input. Use `allowedSocketPaths` (below) to restrict accepted",
        "file": "README.md"
      },
      {
        "command": "allowedSocketPaths",
        "citation": "// `allowedSocketPaths` restricts which `socketPath` values are accepted.",
        "file": "README.md"
      },
      {
        "command": "socketPath",
        "citation": "// `allowedSocketPaths` restricts which `socketPath` values are accepted.",
        "file": "README.md"
      },
      {
        "command": "ERR_BAD_OPTION_VALUE",
        "citation": "// `ERR_BAD_OPTION_VALUE`. When null/undefined, no restriction is applied.",
        "file": "README.md"
      },
      {
        "command": "transport",
        "citation": "// `transport` determines the transport method for the request.",
        "file": "README.md"
      },
      {
        "command": "maxRedirects",
        "citation": "// If defined, Axios uses it. Otherwise, if `maxRedirects` is 0,",
        "file": "README.md"
      },
      {
        "command": "http",
        "citation": "// Axios uses the default `http` or `https` library, depending on the protocol specified in `protocol`.",
        "file": "README.md"
      },
      {
        "command": "https",
        "citation": "// Axios uses the default `http` or `https` library, depending on the protocol specified in `protocol`.",
        "file": "README.md"
      },
      {
        "command": "protocol",
        "citation": "// Axios uses the default `http` or `https` library, depending on the protocol specified in `protocol`.",
        "file": "README.md"
      },
      {
        "command": "httpFollow",
        "citation": "// Otherwise, Axios uses the `httpFollow` or `httpsFollow` library, again depending on the protocol,",
        "file": "README.md"
      },
      {
        "command": "httpsFollow",
        "citation": "// Otherwise, Axios uses the `httpFollow` or `httpsFollow` library, again depending on the protocol,",
        "file": "README.md"
      },
      {
        "command": "httpAgent",
        "citation": "// `httpAgent` and `httpsAgent` define a custom agent to be used when performing http",
        "file": "README.md"
      },
      {
        "command": "httpsAgent",
        "citation": "// `httpAgent` and `httpsAgent` define a custom agent to be used when performing http",
        "file": "README.md"
      },
      {
        "command": "keepAlive",
        "citation": "// `keepAlive` that are not enabled by default before Node.js v19.0.0. After Node.js",
        "file": "README.md"
      },
      {
        "command": "keepAlive",
        "citation": "// v19.0.0, you no longer need to customize the agent to enable `keepAlive` because",
        "file": "README.md"
      },
      {
        "command": "http.globalAgent",
        "citation": "// `http.globalAgent` has `keepAlive` enabled by default.",
        "file": "README.md"
      },
      {
        "command": "keepAlive",
        "citation": "// `http.globalAgent` has `keepAlive` enabled by default.",
        "file": "README.md"
      },
      {
        "command": "proxy",
        "citation": "// `proxy` defines the hostname, port, and protocol of the proxy server.",
        "file": "README.md"
      },
      {
        "command": "http_proxy",
        "citation": "// You can also define your proxy using the conventional `http_proxy` and",
        "file": "README.md"
      },
      {
        "command": "https_proxy",
        "citation": "// `https_proxy` environment variables. If you are using environment variables",
        "file": "README.md"
      },
      {
        "command": "no_proxy",
        "citation": "// for your proxy configuration, you can also define a `no_proxy` environment",
        "file": "README.md"
      },
      {
        "command": "false",
        "citation": "// Use `false` to disable proxies, ignoring environment variables.",
        "file": "README.md"
      },
      {
        "command": "proxyEnv",
        "citation": "// environment proxy handling to Node when the selected agent has `proxyEnv`",
        "file": "README.md"
      },
      {
        "command": "--use-env-proxy",
        "citation": "// `--use-env-proxy`, or `NODE_OPTIONS=--use-env-proxy`. Custom agents without",
        "file": "README.md"
      },
      {
        "command": "proxyEnv",
        "citation": "// `proxyEnv` continue to use axios environment proxy resolution. Explicit",
        "file": "README.md"
      },
      {
        "command": "proxy",
        "citation": "// `proxy` config is still handled by axios.",
        "file": "README.md"
      },
      {
        "command": "auth",
        "citation": "// `auth` indicates that HTTP Basic auth should be used to connect to the proxy, and",
        "file": "README.md"
      },
      {
        "command": "Proxy-Authorization",
        "citation": "// forward-proxy mode and stamps `Proxy-Authorization` onto the request",
        "file": "README.md"
      },
      {
        "command": "Proxy-Authorization",
        "citation": "// headers (overwriting any user-supplied `Proxy-Authorization` header).",
        "file": "README.md"
      },
      {
        "command": "Proxy-Authorization",
        "citation": "// proxy and performs TLS end-to-end with the origin; `Proxy-Authorization`",
        "file": "README.md"
      },
      {
        "command": "httpsAgent",
        "citation": "// `httpsAgent` TLS options such as `ca`, `cert`, `key`, and",
        "file": "README.md"
      },
      {
        "command": "ca",
        "citation": "// `httpsAgent` TLS options such as `ca`, `cert`, `key`, and",
        "file": "README.md"
      },
      {
        "command": "cert",
        "citation": "// `httpsAgent` TLS options such as `ca`, `cert`, `key`, and",
        "file": "README.md"
      },
      {
        "command": "key",
        "citation": "// `httpsAgent` TLS options such as `ca`, `cert`, `key`, and",
        "file": "README.md"
      },
      {
        "command": "rejectUnauthorized",
        "citation": "// `rejectUnauthorized` to the generated tunneling agent, so they still apply",
        "file": "README.md"
      },
      {
        "command": "HttpsProxyAgent",
        "citation": "// If you supply an `HttpsProxyAgent`, axios leaves tunneling to that agent.",
        "file": "README.md"
      },
      {
        "command": "https",
        "citation": "// If the proxy server uses HTTPS, then you must set the protocol to `https`.",
        "file": "README.md"
      },
      {
        "command": "Host",
        "citation": "// A user-supplied `Host` header in `headers` is preserved when forwarding",
        "file": "README.md"
      },
      {
        "command": "headers",
        "citation": "// A user-supplied `Host` header in `headers` is preserved when forwarding",
        "file": "README.md"
      },
      {
        "command": "host",
        "citation": "// through a proxy (case-insensitive match on `host`/`Host`/`HOST`); this",
        "file": "README.md"
      },
      {
        "command": "Host",
        "citation": "// through a proxy (case-insensitive match on `host`/`Host`/`HOST`); this",
        "file": "README.md"
      },
      {
        "command": "HOST",
        "citation": "// through a proxy (case-insensitive match on `host`/`Host`/`HOST`); this",
        "file": "README.md"
      },
      {
        "command": "example.com",
        "citation": "// request as `example.com`. If no `Host` header is supplied, axios",
        "file": "README.md"
      },
      {
        "command": "Host",
        "citation": "// request as `example.com`. If no `Host` header is supplied, axios",
        "file": "README.md"
      },
      {
        "command": "cancelToken",
        "citation": "// `cancelToken` specifies a cancel token that can be used to cancel the request",
        "file": "README.md"
      },
      {
        "command": "decompress",
        "citation": "// `decompress` indicates whether or not the response body should be decompressed",
        "file": "README.md"
      },
      {
        "command": "true",
        "citation": "// automatically. If set to `true` will also remove the 'content-encoding' header",
        "file": "README.md"
      },
      {
        "command": "insecureHTTPParser",
        "citation": "// `insecureHTTPParser` boolean.",
        "file": "README.md"
      },
      {
        "command": "true",
        "citation": "// `true` - ignore JSON parsing errors and set response.data to null if parsing failed (old behaviour)",
        "file": "README.md"
      },
      {
        "command": "false",
        "citation": "// `false` - throw SyntaxError if JSON parsing failed",
        "file": "README.md"
      },
      {
        "command": "responseType",
        "citation": "// Important: this option only takes effect when `responseType` is explicitly set to 'json'.",
        "file": "README.md"
      },
      {
        "command": "responseType",
        "citation": "// When `responseType` is omitted (defaults to no value), axios uses `forcedJSONParsing`",
        "file": "README.md"
      },
      {
        "command": "forcedJSONParsing",
        "citation": "// When `responseType` is omitted (defaults to no value), axios uses `forcedJSONParsing`",
        "file": "README.md"
      },
      {
        "command": "responseType",
        "citation": "// try to parse the response string as JSON even if `responseType` is not 'json'",
        "file": "README.md"
      },
      {
        "command": "validateStatus: undefined",
        "citation": "// keep explicit `validateStatus: undefined` resolving every response status",
        "file": "README.md"
      },
      {
        "command": "zstd",
        "citation": "// advertise `zstd` in the default Accept-Encoding header when the current",
        "file": "README.md"
      },
      {
        "command": "decompress",
        "citation": "// zstd responses when support exists and `decompress` is true.",
        "file": "README.md"
      },
      {
        "command": "sensitiveHeaders",
        "citation": "For custom secret-bearing headers in Node.js, list them in `sensitiveHeaders` so Axios removes them when following a redirect to another origin:",
        "file": "README.md"
      },
      {
        "command": "paramsSerializer.encode",
        "citation": "Override the default encoder via `paramsSerializer.encode`:",
        "file": "README.md"
      },
      {
        "command": "httpVersion",
        "citation": "Options like `httpVersion` and `http2Options` are adapter-specific and may not work the same way in every environment.",
        "file": "README.md"
      },
      {
        "command": "http2Options",
        "citation": "Options like `httpVersion` and `http2Options` are adapter-specific and may not work the same way in every environment.",
        "file": "README.md"
      },
      {
        "command": "data",
        "citation": "// `data` is the response that was provided by the server",
        "file": "README.md"
      },
      {
        "command": "status",
        "citation": "// `status` is the HTTP status code from the server response",
        "file": "README.md"
      },
      {
        "command": "statusText",
        "citation": "// `statusText` is the HTTP status message from the server response",
        "file": "README.md"
      },
      {
        "command": "headers",
        "citation": "// `headers` the HTTP headers that the server responded with",
        "file": "README.md"
      },
      {
        "command": "config",
        "citation": "// `config` is the config that was provided to `axios` for the request",
        "file": "README.md"
      },
      {
        "command": "axios",
        "citation": "// `config` is the config that was provided to `axios` for the request",
        "file": "README.md"
      },
      {
        "command": "request",
        "citation": "// `request` is the request that generated this response",
        "file": "README.md"
      },
      {
        "command": "then",
        "citation": "When using `then`, you receive the response like this:",
        "file": "README.md"
      },
      {
        "command": "catch",
        "citation": "When using `catch`, or passing a [rejection callback](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) as the second parameter of `then`, read the response from the `error` object. See [Handling errors](#handling-errors).",
        "file": "README.md"
      },
      {
        "command": "then",
        "citation": "When using `catch`, or passing a [rejection callback](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) as the second parameter of `then`, read the response from the `error` object. See [Handling errors](#handling-errors).",
        "file": "README.md"
      },
      {
        "command": "error",
        "citation": "When using `catch`, or passing a [rejection callback](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) as the second parameter of `then`, read the response from the `error` object. See [Handling errors](#handling-errors).",
        "file": "README.md"
      },
      {
        "command": "defaults",
        "citation": "Axios merges config in this order: library defaults from [lib/defaults/index.js](https://github.com/axios/axios/blob/main/lib/defaults/index.js#L49), the instance `defaults` property, and the request `config` argument. Later values take precedence over earlier ones.",
        "file": "README.md"
      },
      {
        "command": "config",
        "citation": "Axios merges config in this order: library defaults from [lib/defaults/index.js](https://github.com/axios/axios/blob/main/lib/defaults/index.js#L49), the instance `defaults` property, and the request `config` argument. Later values take precedence over earlier ones.",
        "file": "README.md"
      },
      {
        "command": "config",
        "citation": "Some options are request-specific and are only taken from the request `config`. `data` is one of those options: axios does not inherit or deep-merge request bodies from global or instance defaults. If every request needs shared body fields, add them with a request interceptor or `transformRequest`, and scope that logic carefully so sensitive values are not sent to the wrong endpoint.",
        "file": "README.md"
      },
      {
        "command": "data",
        "citation": "Some options are request-specific and are only taken from the request `config`. `data` is one of those options: axios does not inherit or deep-merge request bodies from global or instance defaults. If every request needs shared body fields, add them with a request interceptor or `transformRequest`, and scope that logic carefully so sensitive values are not sent to the wrong endpoint.",
        "file": "README.md"
      },
      {
        "command": "transformRequest",
        "citation": "Some options are request-specific and are only taken from the request `config`. `data` is one of those options: axios does not inherit or deep-merge request bodies from global or instance defaults. If every request needs shared body fields, add them with a request interceptor or `transformRequest`, and scope that logic carefully so sensitive values are not sent to the wrong endpoint.",
        "file": "README.md"
      },
      {
        "command": "0",
        "citation": "// At this point the timeout config value is `0` as is the default for the library",
        "file": "README.md"
      },
      {
        "command": "then",
        "citation": "resolve their promises (before code inside `then` or `catch`, or after `await`)",
        "file": "README.md"
      },
      {
        "command": "catch",
        "citation": "resolve their promises (before code inside `then` or `catch`, or after `await`)",
        "file": "README.md"
      },
      {
        "command": "await",
        "citation": "resolve their promises (before code inside `then` or `catch`, or after `await`)",
        "file": "README.md"
      },
      {
        "command": "runWhen",
        "citation": "you can add a `runWhen` function to the options object. The request interceptor will not run **if and only if** the return",
        "file": "README.md"
      },
      {
        "command": "runWhen",
        "citation": "of `runWhen` is `false`. Axios calls the function with the config",
        "file": "README.md"
      },
      {
        "command": "false",
        "citation": "of `runWhen` is `false`. Axios calls the function with the config",
        "file": "README.md"
      },
      {
        "command": "synchronous",
        "citation": "> Note: The options parameter (with `synchronous` and `runWhen` properties) is only supported for request interceptors at the moment.",
        "file": "README.md"
      },
      {
        "command": "runWhen",
        "citation": "> Note: The options parameter (with `synchronous` and `runWhen` properties) is only supported for request interceptors at the moment.",
        "file": "README.md"
      },
      {
        "command": "transitional.clarifyTimeoutError",
        "citation": "| ECONNABORTED | Typically indicates that the request has been timed out (unless `transitional.clarifyTimeoutError` is set) or aborted by the browser or its plugin. |",
        "file": "README.md"
      },
      {
        "command": "transitional.clarifyTimeoutError",
        "citation": "| ETIMEDOUT | Request timed out after exceeding the configured Axios timeout. Set `transitional.clarifyTimeoutError` to `true`; otherwise Axios throws a generic `ECONNABORTED` error. |",
        "file": "README.md"
      },
      {
        "command": "true",
        "citation": "| ETIMEDOUT | Request timed out after exceeding the configured Axios timeout. Set `transitional.clarifyTimeoutError` to `true`; otherwise Axios throws a generic `ECONNABORTED` error. |",
        "file": "README.md"
      },
      {
        "command": "ECONNABORTED",
        "citation": "| ETIMEDOUT | Request timed out after exceeding the configured Axios timeout. Set `transitional.clarifyTimeoutError` to `true`; otherwise Axios throws a generic `ECONNABORTED` error. |",
        "file": "README.md"
      },
      {
        "command": "5xx",
        "citation": "| ERR_BAD_RESPONSE | Response cannot be parsed properly or is in an unexpected format. Usually related to a response with `5xx` status code. |",
        "file": "README.md"
      },
      {
        "command": "4xx",
        "citation": "| ERR_BAD_REQUEST | The request has an unexpected format or is missing required parameters. Usually related to a response with `4xx` status code. |",
        "file": "README.md"
      },
      {
        "command": "error.request",
        "citation": "// `error.request` is an instance of XMLHttpRequest in the browser and an instance of",
        "file": "README.md"
      },
      {
        "command": "validateStatus",
        "citation": "Use `validateStatus` to override the default condition (`status >= 200 && status < 300`) and choose which HTTP status codes should reject.",
        "file": "README.md"
      },
      {
        "command": "status >= 200 && status < 300",
        "citation": "Use `validateStatus` to override the default condition (`status >= 200 && status < 300`) and choose which HTTP status codes should reject.",
        "file": "README.md"
      },
      {
        "command": "validateStatus: undefined",
        "citation": "By default, explicit `validateStatus: undefined` keeps legacy behavior and resolves every response status because `transitional.validateStatusUndefinedResolves` defaults to `true`. Set it to `false` to make explicit `validateStatus: undefined` behave like the option was omitted, so Axios uses the configured/default validator and rejects non-2xx responses by default.",
        "file": "README.md"
      },
      {
        "command": "transitional.validateStatusUndefinedResolves",
        "citation": "By default, explicit `validateStatus: undefined` keeps legacy behavior and resolves every response status because `transitional.validateStatusUndefinedResolves` defaults to `true`. Set it to `false` to make explicit `validateStatus: undefined` behave like the option was omitted, so Axios uses the configured/default validator and rejects non-2xx responses by default.",
        "file": "README.md"
      },
      {
        "command": "true",
        "citation": "By default, explicit `validateStatus: undefined` keeps legacy behavior and resolves every response status because `transitional.validateStatusUndefinedResolves` defaults to `true`. Set it to `false` to make explicit `validateStatus: undefined` behave like the option was omitted, so Axios uses the configured/default validator and rejects non-2xx responses by default.",
        "file": "README.md"
      },
      {
        "command": "false",
        "citation": "By default, explicit `validateStatus: undefined` keeps legacy behavior and resolves every response status because `transitional.validateStatusUndefinedResolves` defaults to `true`. Set it to `false` to make explicit `validateStatus: undefined` behave like the option was omitted, so Axios uses the configured/default validator and rejects non-2xx responses by default.",
        "file": "README.md"
      },
      {
        "command": "validateStatus: undefined",
        "citation": "By default, explicit `validateStatus: undefined` keeps legacy behavior and resolves every response status because `transitional.validateStatusUndefinedResolves` defaults to `true`. Set it to `false` to make explicit `validateStatus: undefined` behave like the option was omitted, so Axios uses the configured/default validator and rejects non-2xx responses by default.",
        "file": "README.md"
      },
      {
        "command": "validateStatus: null",
        "citation": "`validateStatus: null` still accepts every response status. If you disable the transitional behavior and intentionally want all statuses to resolve, use `null` or `() => true`.",
        "file": "README.md"
      },
      {
        "command": "null",
        "citation": "`validateStatus: null` still accepts every response status. If you disable the transitional behavior and intentionally want all statuses to resolve, use `null` or `() => true`.",
        "file": "README.md"
      },
      {
        "command": "() => true",
        "citation": "`validateStatus: null` still accepts every response status. If you disable the transitional behavior and intentionally want all statuses to resolve, use `null` or `() => true`.",
        "file": "README.md"
      },
      {
        "command": "toJSON",
        "citation": "Use `toJSON` to get more information about the HTTP error.",
        "file": "README.md"
      },
      {
        "command": "error.config",
        "citation": "To avoid logging secrets from `error.config`, pass a `redact` array in the request config. Matching config keys are masked case-insensitively at any depth when `AxiosError#toJSON()` is called.",
        "file": "README.md"
      },
      {
        "command": "redact",
        "citation": "To avoid logging secrets from `error.config`, pass a `redact` array in the request config. Matching config keys are masked case-insensitively at any depth when `AxiosError#toJSON()` is called.",
        "file": "README.md"
      },
      {
        "command": "v0.22.0",
        "citation": "Since `v0.22.0`, Axios supports AbortController:",
        "file": "README.md"
      },
      {
        "command": "CancelToken.source",
        "citation": "Create a cancel token with the `CancelToken.source` factory:",
        "file": "README.md"
      },
      {
        "command": "CancelToken",
        "citation": "You can also pass an executor function to the `CancelToken` constructor:",
        "file": "README.md"
      },
      {
        "command": "CancelToken",
        "citation": "`CancelToken` also exposes low-level helpers for legacy integrations:",
        "file": "README.md"
      },
      {
        "command": "signal",
        "citation": "// Pass `signal` to APIs that accept AbortSignal.",
        "file": "README.md"
      },
      {
        "command": "axios.CanceledError",
        "citation": "Canceled requests reject with `axios.CanceledError`. The legacy `axios.Cancel` export is an alias of `axios.CanceledError`, and cancellation errors include `__CANCEL__` for `axios.isCancel` compatibility.",
        "file": "README.md"
      },
      {
        "command": "axios.Cancel",
        "citation": "Canceled requests reject with `axios.CanceledError`. The legacy `axios.Cancel` export is an alias of `axios.CanceledError`, and cancellation errors include `__CANCEL__` for `axios.isCancel` compatibility.",
        "file": "README.md"
      },
      {
        "command": "axios.CanceledError",
        "citation": "Canceled requests reject with `axios.CanceledError`. The legacy `axios.Cancel` export is an alias of `axios.CanceledError`, and cancellation errors include `__CANCEL__` for `axios.isCancel` compatibility.",
        "file": "README.md"
      },
      {
        "command": "__CANCEL__",
        "citation": "Canceled requests reject with `axios.CanceledError`. The legacy `axios.Cancel` export is an alias of `axios.CanceledError`, and cancellation errors include `__CANCEL__` for `axios.isCancel` compatibility.",
        "file": "README.md"
      },
      {
        "command": "axios.isCancel",
        "citation": "Canceled requests reject with `axios.CanceledError`. The legacy `axios.Cancel` export is an alias of `axios.CanceledError`, and cancellation errors include `__CANCEL__` for `axios.isCancel` compatibility.",
        "file": "README.md"
      },
      {
        "command": "JSON",
        "citation": "By default, axios serializes JavaScript objects to `JSON`. To send data as [`application/x-www-form-urlencoded`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST), use the [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) API. It works in most browsers and in [Node](https://nodejs.org/api/url.html#url_class_urlsearchparams) v10 and later.",
        "file": "README.md"
      },
      {
        "command": "URLSearchParams",
        "citation": "By default, axios serializes JavaScript objects to `JSON`. To send data as [`application/x-www-form-urlencoded`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST), use the [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) API. It works in most browsers and in [Node](https://nodejs.org/api/url.html#url_class_urlsearchparams) v10 and later.",
        "file": "README.md"
      },
      {
        "command": "qs",
        "citation": "Alternatively, you can encode data using the [`qs`](https://github.com/ljharb/qs) library:",
        "file": "README.md"
      },
      {
        "command": "querystring",
        "citation": "For older Node.js engines, use the [`querystring`](https://nodejs.org/api/querystring.html) module:",
        "file": "README.md"
      },
      {
        "command": "qs",
        "citation": "You can also use the [`qs`](https://github.com/ljharb/qs) library.",
        "file": "README.md"
      },
      {
        "command": "qs",
        "citation": "> Note: The `qs` library is preferable if you need to stringify nested objects, as the `querystring` method has [known issues](https://github.com/nodejs/node-v0.x-archive/issues/1665) with that use case.",
        "file": "README.md"
      },
      {
        "command": "querystring",
        "citation": "> Note: The `qs` library is preferable if you need to stringify nested objects, as the `querystring` method has [known issues](https://github.com/nodejs/node-v0.x-archive/issues/1665) with that use case.",
        "file": "README.md"
      },
      {
        "command": "body-parser",
        "citation": "If your backend body parser, such as `body-parser` for `express.js`, supports nested object decoding, the server receives the same object structure:",
        "file": "README.md"
      },
      {
        "command": "express.js",
        "citation": "If your backend body parser, such as `body-parser` for `express.js`, supports nested object decoding, the server receives the same object structure:",
        "file": "README.md"
      },
      {
        "command": "Content-Type",
        "citation": "You do not need to set the `Content-Type` header. Axios detects it from the payload type.",
        "file": "README.md"
      },
      {
        "command": "FormData",
        "citation": "For browser, web worker, and React Native `FormData`, leave `Content-Type` unset so the runtime can add the multipart boundary.",
        "file": "README.md"
      },
      {
        "command": "Content-Type",
        "citation": "For browser, web worker, and React Native `FormData`, leave `Content-Type` unset so the runtime can add the multipart boundary.",
        "file": "README.md"
      },
      {
        "command": "form-data",
        "citation": "In node.js, use the [`form-data`](https://github.com/form-data/form-data) library:",
        "file": "README.md"
      },
      {
        "command": "FormData",
        "citation": "In node.js, when a `FormData` object provides `getHeaders()`, axios copies all returned headers by default for v1 compatibility. If the `FormData` object is custom or not fully trusted, set `formDataHeaderPolicy: 'content-only'` to copy only `Content-Type` and `Content-Length`, and set any other request headers explicitly with the request `headers` config.",
        "file": "README.md"
      },
      {
        "command": "FormData",
        "citation": "In node.js, when a `FormData` object provides `getHeaders()`, axios copies all returned headers by default for v1 compatibility. If the `FormData` object is custom or not fully trusted, set `formDataHeaderPolicy: 'content-only'` to copy only `Content-Type` and `Content-Length`, and set any other request headers explicitly with the request `headers` config.",
        "file": "README.md"
      },
      {
        "command": "formDataHeaderPolicy: 'content-only'",
        "citation": "In node.js, when a `FormData` object provides `getHeaders()`, axios copies all returned headers by default for v1 compatibility. If the `FormData` object is custom or not fully trusted, set `formDataHeaderPolicy: 'content-only'` to copy only `Content-Type` and `Content-Length`, and set any other request headers explicitly with the request `headers` config.",
        "file": "README.md"
      },
      {
        "command": "Content-Type",
        "citation": "In node.js, when a `FormData` object provides `getHeaders()`, axios copies all returned headers by default for v1 compatibility. If the `FormData` object is custom or not fully trusted, set `formDataHeaderPolicy: 'content-only'` to copy only `Content-Type` and `Content-Length`, and set any other request headers explicitly with the request `headers` config.",
        "file": "README.md"
      },
      {
        "command": "Content-Length",
        "citation": "In node.js, when a `FormData` object provides `getHeaders()`, axios copies all returned headers by default for v1 compatibility. If the `FormData` object is custom or not fully trusted, set `formDataHeaderPolicy: 'content-only'` to copy only `Content-Type` and `Content-Length`, and set any other request headers explicitly with the request `headers` config.",
        "file": "README.md"
      },
      {
        "command": "headers",
        "citation": "In node.js, when a `FormData` object provides `getHeaders()`, axios copies all returned headers by default for v1 compatibility. If the `FormData` object is custom or not fully trusted, set `formDataHeaderPolicy: 'content-only'` to copy only `Content-Type` and `Content-Length`, and set any other request headers explicitly with the request `headers` config.",
        "file": "README.md"
      },
      {
        "command": "v0.27.0",
        "citation": "Since `v0.27.0`, Axios can serialize an object to FormData if the request `Content-Type`",
        "file": "README.md"
      },
      {
        "command": "Content-Type",
        "citation": "Since `v0.27.0`, Axios can serialize an object to FormData if the request `Content-Type`",
        "file": "README.md"
      },
      {
        "command": "form-data",
        "citation": "The Node.js build uses the [`form-data`](https://github.com/form-data/form-data) polyfill by default.",
        "file": "README.md"
      },
      {
        "command": "env.FormData",
        "citation": "You can override the FormData class with the `env.FormData` config option, but most applications do not need this:",
        "file": "README.md"
      },
      {
        "command": "config.formSerializer: object",
        "citation": "FormData serializer supports additional options via `config.formSerializer: object` property to handle rare cases:",
        "file": "README.md"
      },
      {
        "command": "visitor: Function",
        "citation": "- `visitor: Function` - user-defined visitor function that Axios calls recursively to serialize the data object",
        "file": "README.md"
      },
      {
        "command": "FormData",
        "citation": "to a `FormData` object by following custom rules.",
        "file": "README.md"
      },
      {
        "command": "dots: boolean = false",
        "citation": "- `dots: boolean = false` - use dot notation instead of brackets to serialize arrays and objects;",
        "file": "README.md"
      },
      {
        "command": "metaTokens: boolean = true",
        "citation": "- `metaTokens: boolean = true` - add the special ending (e.g `user{}: '{\"name\": \"John\"}'`) in the FormData key.",
        "file": "README.md"
      },
      {
        "command": "user{}: '{\"name\": \"John\"}'",
        "citation": "- `metaTokens: boolean = true` - add the special ending (e.g `user{}: '{\"name\": \"John\"}'`) in the FormData key.",
        "file": "README.md"
      },
      {
        "command": "indexes: null|false|true = false",
        "citation": "- `indexes: null|false|true = false` - controls how Axios adds indexes to unwrapped keys of `flat` array-like objects.",
        "file": "README.md"
      },
      {
        "command": "flat",
        "citation": "- `indexes: null|false|true = false` - controls how Axios adds indexes to unwrapped keys of `flat` array-like objects.",
        "file": "README.md"
      },
      {
        "command": "null",
        "citation": "- `null` - don't add brackets (`arr: 1`, `arr: 2`, `arr: 3`)",
        "file": "README.md"
      },
      {
        "command": "arr: 1",
        "citation": "- `null` - don't add brackets (`arr: 1`, `arr: 2`, `arr: 3`)",
        "file": "README.md"
      },
      {
        "command": "arr: 2",
        "citation": "- `null` - don't add brackets (`arr: 1`, `arr: 2`, `arr: 3`)",
        "file": "README.md"
      },
      {
        "command": "arr: 3",
        "citation": "- `null` - don't add brackets (`arr: 1`, `arr: 2`, `arr: 3`)",
        "file": "README.md"
      },
      {
        "command": "false",
        "citation": "- `false`(default) - add empty brackets (`arr[]: 1`, `arr[]: 2`, `arr[]: 3`)",
        "file": "README.md"
      },
      {
        "command": "arr[]: 1",
        "citation": "- `false`(default) - add empty brackets (`arr[]: 1`, `arr[]: 2`, `arr[]: 3`)",
        "file": "README.md"
      },
      {
        "command": "arr[]: 2",
        "citation": "- `false`(default) - add empty brackets (`arr[]: 1`, `arr[]: 2`, `arr[]: 3`)",
        "file": "README.md"
      },
      {
        "command": "arr[]: 3",
        "citation": "- `false`(default) - add empty brackets (`arr[]: 1`, `arr[]: 2`, `arr[]: 3`)",
        "file": "README.md"
      },
      {
        "command": "true",
        "citation": "- `true` - add brackets with indexes (`arr[0]: 1`, `arr[1]: 2`, `arr[2]: 3`)",
        "file": "README.md"
      },
      {
        "command": "arr[0]: 1",
        "citation": "- `true` - add brackets with indexes (`arr[0]: 1`, `arr[1]: 2`, `arr[2]: 3`)",
        "file": "README.md"
      },
      {
        "command": "arr[1]: 2",
        "citation": "- `true` - add brackets with indexes (`arr[0]: 1`, `arr[1]: 2`, `arr[2]: 3`)",
        "file": "README.md"
      },
      {
        "command": "arr[2]: 3",
        "citation": "- `true` - add brackets with indexes (`arr[0]: 1`, `arr[1]: 2`, `arr[2]: 3`)",
        "file": "README.md"
      },
      {
        "command": "maxDepth: number = 100",
        "citation": "- `maxDepth: number = 100` - maximum object nesting depth the serializer will recurse into. If the",
        "file": "README.md"
      },
      {
        "command": "AxiosError",
        "citation": "input object exceeds this depth, an `AxiosError` with `code: 'ERR_FORM_DATA_DEPTH_EXCEEDED'` is",
        "file": "README.md"
      },
      {
        "command": "code: 'ERR_FORM_DATA_DEPTH_EXCEEDED'",
        "citation": "input object exceeds this depth, an `AxiosError` with `code: 'ERR_FORM_DATA_DEPTH_EXCEEDED'` is",
        "file": "README.md"
      },
      {
        "command": "Infinity",
        "citation": "attacks via deeply nested payloads. Set to `Infinity` to disable the limit and restore pre-fix behaviour.",
        "file": "README.md"
      },
      {
        "command": "Blob: typeof Blob",
        "citation": "- `Blob: typeof Blob` - Blob constructor used when converting ArrayBuffer-like values for spec-compliant",
        "file": "README.md"
      },
      {
        "command": "FormData",
        "citation": "`FormData`. Override it only for runtimes that provide a compatible `Blob` constructor under a",
        "file": "README.md"
      },
      {
        "command": "Blob",
        "citation": "`FormData`. Override it only for runtimes that provide a compatible `Blob` constructor under a",
        "file": "README.md"
      },
      {
        "command": "postForm",
        "citation": "Axios supports `postForm`, `putForm`, and `patchForm` as shortcuts for the matching HTTP methods with the `Content-Type` header preset to `multipart/form-data`.",
        "file": "README.md"
      },
      {
        "command": "putForm",
        "citation": "Axios supports `postForm`, `putForm`, and `patchForm` as shortcuts for the matching HTTP methods with the `Content-Type` header preset to `multipart/form-data`.",
        "file": "README.md"
      },
      {
        "command": "patchForm",
        "citation": "Axios supports `postForm`, `putForm`, and `patchForm` as shortcuts for the matching HTTP methods with the `Content-Type` header preset to `multipart/form-data`.",
        "file": "README.md"
      },
      {
        "command": "Content-Type",
        "citation": "Axios supports `postForm`, `putForm`, and `patchForm` as shortcuts for the matching HTTP methods with the `Content-Type` header preset to `multipart/form-data`.",
        "file": "README.md"
      },
      {
        "command": "FileList",
        "citation": "`FileList` object can be passed directly:",
        "file": "README.md"
      },
      {
        "command": "FormData",
        "citation": "`FormData` and `HTMLForm` objects can also be posted as `JSON` by explicitly setting the `Content-Type` header to `application/json`:",
        "file": "README.md"
      },
      {
        "command": "HTMLForm",
        "citation": "`FormData` and `HTMLForm` objects can also be posted as `JSON` by explicitly setting the `Content-Type` header to `application/json`:",
        "file": "README.md"
      },
      {
        "command": "JSON",
        "citation": "`FormData` and `HTMLForm` objects can also be posted as `JSON` by explicitly setting the `Content-Type` header to `application/json`:",
        "file": "README.md"
      },
      {
        "command": "Content-Type",
        "citation": "`FormData` and `HTMLForm` objects can also be posted as `JSON` by explicitly setting the `Content-Type` header to `application/json`:",
        "file": "README.md"
      },
      {
        "command": "Blobs",
        "citation": "Sending `Blobs`/`Files` as JSON (`base64`) is not currently supported.",
        "file": "README.md"
      },
      {
        "command": "Files",
        "citation": "Sending `Blobs`/`Files` as JSON (`base64`) is not currently supported.",
        "file": "README.md"
      },
      {
        "command": "base64",
        "citation": "Sending `Blobs`/`Files` as JSON (`base64`) is not currently supported.",
        "file": "README.md"
      },
      {
        "command": "3",
        "citation": "Progress events are limited to `3` times per second.",
        "file": "README.md"
      },
      {
        "command": "maxRedirects: 0",
        "citation": "> Set `maxRedirects: 0` when uploading streams in node.js.",
        "file": "README.md"
      },
      {
        "command": "Upload [${(progress * 100).toFixed(2)}%]: ${(rate / 1024).toFixed(2)}KB/s",
        "citation": "console.log(`Upload [${(progress * 100).toFixed(2)}%]: ${(rate / 1024).toFixed(2)}KB/s`);",
        "file": "README.md"
      },
      {
        "command": "AxiosHeaders",
        "citation": "Axios includes an `AxiosHeaders` class for working with headers through a Map-like API.",
        "file": "README.md"
      },
      {
        "command": "AxiosHeaders",
        "citation": "An `AxiosHeaders` instance can contain several internal value types that control setting and merging.",
        "file": "README.md"
      },
      {
        "command": "toJSON",
        "citation": "Axios gets the final headers object with string values by calling `toJSON`.",
        "file": "README.md"
      },
      {
        "command": "string",
        "citation": "- `string` - normal string value sent to the server",
        "file": "README.md"
      },
      {
        "command": "null",
        "citation": "- `null` - skip header when rendering to JSON",
        "file": "README.md"
      },
      {
        "command": "false",
        "citation": "- `false` - skip header when rendering to JSON. Also indicates that the `set` method must be called with `rewrite` set to `true`",
        "file": "README.md"
      },
      {
        "command": "set",
        "citation": "- `false` - skip header when rendering to JSON. Also indicates that the `set` method must be called with `rewrite` set to `true`",
        "file": "README.md"
      },
      {
        "command": "rewrite",
        "citation": "- `false` - skip header when rendering to JSON. Also indicates that the `set` method must be called with `rewrite` set to `true`",
        "file": "README.md"
      },
      {
        "command": "true",
        "citation": "- `false` - skip header when rendering to JSON. Also indicates that the `set` method must be called with `rewrite` set to `true`",
        "file": "README.md"
      },
      {
        "command": "User-Agent",
        "citation": "to overwrite this value (Axios uses this internally to allow users to opt out of installing certain headers like `User-Agent` or `Content-Type`)",
        "file": "README.md"
      },
      {
        "command": "Content-Type",
        "citation": "to overwrite this value (Axios uses this internally to allow users to opt out of installing certain headers like `User-Agent` or `Content-Type`)",
        "file": "README.md"
      },
      {
        "command": "undefined",
        "citation": "- `undefined` - value is not set",
        "file": "README.md"
      },
      {
        "command": "AxiosHeaders",
        "citation": "You can iterate over an `AxiosHeaders` instance using a `for...of` statement:",
        "file": "README.md"
      },
      {
        "command": "for...of",
        "citation": "You can iterate over an `AxiosHeaders` instance using a `for...of` statement:",
        "file": "README.md"
      },
      {
        "command": "AxiosHeaders",
        "citation": "Header names are case-insensitive, but `AxiosHeaders` keeps the case of the first matching key it sees.",
        "file": "README.md"
      },
      {
        "command": "undefined",
        "citation": "If you need a specific case for non-standard case-sensitive servers, define a case preset with `undefined` and then set the value later:",
        "file": "README.md"
      },
      {
        "command": "AxiosHeaders.concat",
        "citation": "You can also compose the same behavior with `AxiosHeaders.concat`:",
        "file": "README.md"
      },
      {
        "command": "AxiosHeaders",
        "citation": "Constructs a new `AxiosHeaders` instance.",
        "file": "README.md"
      },
      {
        "command": "rewrite",
        "citation": "The `rewrite` argument controls the overwriting behavior:",
        "file": "README.md"
      },
      {
        "command": "false",
        "citation": "- `false` - do not overwrite if the header's value is set (is not `undefined`)",
        "file": "README.md"
      },
      {
        "command": "undefined",
        "citation": "- `false` - do not overwrite if the header's value is set (is not `undefined`)",
        "file": "README.md"
      },
      {
        "command": "undefined",
        "citation": "- `undefined` (default) - overwrite the header unless its value is set to `false`",
        "file": "README.md"
      },
      {
        "command": "false",
        "citation": "- `undefined` (default) - overwrite the header unless its value is set to `false`",
        "file": "README.md"
      },
      {
        "command": "true",
        "citation": "- `true` - rewrite anyway",
        "file": "README.md"
      },
      {
        "command": "Map",
        "citation": "Iterable key/value pairs, such as a `Map`, are accepted:",
        "file": "README.md"
      },
      {
        "command": "this",
        "citation": "Returns `this`.",
        "file": "README.md"
      },
      {
        "command": "RegExp.exec",
        "citation": "Returns the internal value of the header. It can take an extra argument to parse the header's value with `RegExp.exec`,",
        "file": "README.md"
      },
      {
        "command": "true",
        "citation": "Returns `true` if the header is set (has no `undefined` value).",
        "file": "README.md"
      },
      {
        "command": "undefined",
        "citation": "Returns `true` if the header is set (has no `undefined` value).",
        "file": "README.md"
      },
      {
        "command": "true",
        "citation": "Returns `true` if at least one header has been removed.",
        "file": "README.md"
      },
      {
        "command": "delete",
        "citation": "Unlike the `delete` method matcher, this optional matcher matches the header name rather than the value.",
        "file": "README.md"
      },
      {
        "command": "true",
        "citation": "Returns `true` if at least one header has been cleared.",
        "file": "README.md"
      },
      {
        "command": "format",
        "citation": "Set `format` to true for converting header names to lowercase and capitalizing the initial letters (`cOntEnt-type` => `Content-Type`)",
        "file": "README.md"
      },
      {
        "command": "cOntEnt-type",
        "citation": "Set `format` to true for converting header names to lowercase and capitalizing the initial letters (`cOntEnt-type` => `Content-Type`)",
        "file": "README.md"
      },
      {
        "command": "Content-Type",
        "citation": "Set `format` to true for converting header names to lowercase and capitalizing the initial letters (`cOntEnt-type` => `Content-Type`)",
        "file": "README.md"
      },
      {
        "command": "this",
        "citation": "Returns `this`.",
        "file": "README.md"
      },
      {
        "command": "AxiosHeaders",
        "citation": "Merges the instance with targets into a new `AxiosHeaders` instance. If the target is a string, Axios parses it as raw HTTP headers.",
        "file": "README.md"
      },
      {
        "command": "AxiosHeaders",
        "citation": "Returns a new `AxiosHeaders` instance.",
        "file": "README.md"
      },
      {
        "command": "asStrings",
        "citation": "Set `asStrings` to true to resolve arrays as a string containing all elements, separated by commas.",
        "file": "README.md"
      },
      {
        "command": "name: value",
        "citation": "Returns the headers as a CRLF-free HTTP header block, one `name: value` pair per line.",
        "file": "README.md"
      },
      {
        "command": "AxiosHeaders",
        "citation": "Returns a new `AxiosHeaders` instance created from the raw headers passed in,",
        "file": "README.md"
      },
      {
        "command": "AxiosHeaders",
        "citation": "or returns the given headers object if it's already an `AxiosHeaders` instance.",
        "file": "README.md"
      },
      {
        "command": "AxiosHeaders",
        "citation": "Returns a new `AxiosHeaders` instance created by merging the target objects.",
        "file": "README.md"
      },
      {
        "command": "setContentType",
        "citation": "- `setContentType`, `getContentType`, `hasContentType`",
        "file": "README.md"
      },
      {
        "command": "getContentType",
        "citation": "- `setContentType`, `getContentType`, `hasContentType`",
        "file": "README.md"
      },
      {
        "command": "hasContentType",
        "citation": "- `setContentType`, `getContentType`, `hasContentType`",
        "file": "README.md"
      },
      {
        "command": "setContentLength",
        "citation": "- `setContentLength`, `getContentLength`, `hasContentLength`",
        "file": "README.md"
      },
      {
        "command": "getContentLength",
        "citation": "- `setContentLength`, `getContentLength`, `hasContentLength`",
        "file": "README.md"
      },
      {
        "command": "hasContentLength",
        "citation": "- `setContentLength`, `getContentLength`, `hasContentLength`",
        "file": "README.md"
      },
      {
        "command": "setAccept",
        "citation": "- `setAccept`, `getAccept`, `hasAccept`",
        "file": "README.md"
      },
      {
        "command": "getAccept",
        "citation": "- `setAccept`, `getAccept`, `hasAccept`",
        "file": "README.md"
      },
      {
        "command": "hasAccept",
        "citation": "- `setAccept`, `getAccept`, `hasAccept`",
        "file": "README.md"
      },
      {
        "command": "setUserAgent",
        "citation": "- `setUserAgent`, `getUserAgent`, `hasUserAgent`",
        "file": "README.md"
      },
      {
        "command": "getUserAgent",
        "citation": "- `setUserAgent`, `getUserAgent`, `hasUserAgent`",
        "file": "README.md"
      },
      {
        "command": "hasUserAgent",
        "citation": "- `setUserAgent`, `getUserAgent`, `hasUserAgent`",
        "file": "README.md"
      },
      {
        "command": "setContentEncoding",
        "citation": "- `setContentEncoding`, `getContentEncoding`, `hasContentEncoding`",
        "file": "README.md"
      },
      {
        "command": "getContentEncoding",
        "citation": "- `setContentEncoding`, `getContentEncoding`, `hasContentEncoding`",
        "file": "README.md"
      },
      {
        "command": "hasContentEncoding",
        "citation": "- `setContentEncoding`, `getContentEncoding`, `hasContentEncoding`",
        "file": "README.md"
      },
      {
        "command": "v1.7.0",
        "citation": "Axios introduced the fetch adapter in `v1.7.0`. By default, Axios uses it when the `xhr` and `http` adapters are not available in the build or not supported by the environment.",
        "file": "README.md"
      },
      {
        "command": "xhr",
        "citation": "Axios introduced the fetch adapter in `v1.7.0`. By default, Axios uses it when the `xhr` and `http` adapters are not available in the build or not supported by the environment.",
        "file": "README.md"
      },
      {
        "command": "http",
        "citation": "Axios introduced the fetch adapter in `v1.7.0`. By default, Axios uses it when the `xhr` and `http` adapters are not available in the build or not supported by the environment.",
        "file": "README.md"
      },
      {
        "command": "xhr",
        "citation": "The adapter supports the same features as the `xhr` adapter, including upload and download progress capturing.",
        "file": "README.md"
      },
      {
        "command": "stream",
        "citation": "It also supports response types such as `stream` and `formdata` when the environment supports them.",
        "file": "README.md"
      },
      {
        "command": "formdata",
        "citation": "It also supports response types such as `stream` and `formdata` when the environment supports them.",
        "file": "README.md"
      },
      {
        "command": "auth",
        "citation": "When `auth` is omitted, the fetch adapter can read HTTP Basic auth credentials from the request URL, for example `https://user:pass@example.com`. Percent-encoded URL credentials are decoded before the `Authorization` header is generated, and `auth` takes precedence over URL-embedded credentials.",
        "file": "README.md"
      },
      {
        "command": "Authorization",
        "citation": "When `auth` is omitted, the fetch adapter can read HTTP Basic auth credentials from the request URL, for example `https://user:pass@example.com`. Percent-encoded URL credentials are decoded before the `Authorization` header is generated, and `auth` takes precedence over URL-embedded credentials.",
        "file": "README.md"
      },
      {
        "command": "auth",
        "citation": "When `auth` is omitted, the fetch adapter can read HTTP Basic auth credentials from the request URL, for example `https://user:pass@example.com`. Percent-encoded URL credentials are decoded before the `Authorization` header is generated, and `auth` takes precedence over URL-embedded credentials.",
        "file": "README.md"
      },
      {
        "command": "v1.12.0",
        "citation": "Since `v1.12.0`, you can configure the fetch adapter to use a custom fetch API instead of environment globals.",
        "file": "README.md"
      },
      {
        "command": "fetch",
        "citation": "Pass a custom `fetch` function, `Request`, and `Response` constructors through `env` config.",
        "file": "README.md"
      },
      {
        "command": "Request",
        "citation": "Pass a custom `fetch` function, `Request`, and `Response` constructors through `env` config.",
        "file": "README.md"
      },
      {
        "command": "Response",
        "citation": "Pass a custom `fetch` function, `Request`, and `Response` constructors through `env` config.",
        "file": "README.md"
      },
      {
        "command": "env",
        "citation": "Pass a custom `fetch` function, `Request`, and `Response` constructors through `env` config.",
        "file": "README.md"
      },
      {
        "command": "Request",
        "citation": "When using a custom fetch, you may also need to set custom `Request` and `Response` constructors. If you do not set them, Axios uses the global objects.",
        "file": "README.md"
      },
      {
        "command": "Response",
        "citation": "When using a custom fetch, you may also need to set custom `Request` and `Response` constructors. If you do not set them, Axios uses the global objects.",
        "file": "README.md"
      },
      {
        "command": "null",
        "citation": "If your custom fetch API does not provide these objects and the globals are incompatible with it, pass `null` to disable them inside the fetch adapter.",
        "file": "README.md"
      },
      {
        "command": "Request",
        "citation": "> Note: Setting `Request` and `Response` to `null` prevents the fetch adapter from capturing upload and download progress.",
        "file": "README.md"
      },
      {
        "command": "Response",
        "citation": "> Note: Setting `Request` and `Response` to `null` prevents the fetch adapter from capturing upload and download progress.",
        "file": "README.md"
      },
      {
        "command": "null",
        "citation": "> Note: Setting `Request` and `Response` to `null` prevents the fetch adapter from capturing upload and download progress.",
        "file": "README.md"
      },
      {
        "command": "load",
        "citation": "[SvelteKit](https://svelte.dev/docs/kit/web-standards#Fetch-APIs) uses a custom fetch function for server rendering in `load` functions. It also uses relative paths, which are incompatible with the standard URL API. Configure Axios to use SvelteKit's custom fetch API:",
        "file": "README.md"
      },
      {
        "command": "http",
        "citation": "Axios supports HTTP/2 through the Node.js `http` adapter, introduced in v1.13.0.",
        "file": "README.md"
      },
      {
        "command": "httpVersion",
        "citation": "Options like `httpVersion` and `http2Options` are adapter-specific and may not behave the same way in every environment.",
        "file": "README.md"
      },
      {
        "command": "http2Options",
        "citation": "Options like `httpVersion` and `http2Options` are adapter-specific and may not behave the same way in every environment.",
        "file": "README.md"
      },
      {
        "command": "v1.0.0",
        "citation": "Axios follows [semver](https://semver.org/) since `v1.0.0`.",
        "file": "README.md"
      },
      {
        "command": "module.exports",
        "citation": "Because axios publishes an ESM default export and a CJS `module.exports`, TypeScript has a few caveats.",
        "file": "README.md"
      },
      {
        "command": "\"moduleResolution\": \"node16\"",
        "citation": "The recommended setting is `\"moduleResolution\": \"node16\"`, which is implied by `\"module\": \"node16\"`. This requires TypeScript 4.7 or greater.",
        "file": "README.md"
      },
      {
        "command": "\"module\": \"node16\"",
        "citation": "The recommended setting is `\"moduleResolution\": \"node16\"`, which is implied by `\"module\": \"node16\"`. This requires TypeScript 4.7 or greater.",
        "file": "README.md"
      },
      {
        "command": "\"moduleResolution\": \"node 16\"",
        "citation": "If you compile TypeScript to CJS and can't use `\"moduleResolution\": \"node 16\"`, enable `esModuleInterop`.",
        "file": "README.md"
      },
      {
        "command": "esModuleInterop",
        "citation": "If you compile TypeScript to CJS and can't use `\"moduleResolution\": \"node 16\"`, enable `esModuleInterop`.",
        "file": "README.md"
      },
      {
        "command": "\"moduleResolution\": \"node16\"",
        "citation": "If you use TypeScript to type check CJS JavaScript code, your only option is to use `\"moduleResolution\": \"node16\"`.",
        "file": "README.md"
      },
      {
        "command": ".npmrc",
        "citation": "As a supply-chain hardening measure, this repository ships a project-level `.npmrc` that sets `ignore-scripts=true`. This blocks npm lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency when you run `npm install` or `npm ci` inside the repo. See [THREATMODEL.md](./THREATMODEL.md) (threat T-S2) for the rationale.",
        "file": "README.md"
      },
      {
        "command": "preinstall",
        "citation": "As a supply-chain hardening measure, this repository ships a project-level `.npmrc` that sets `ignore-scripts=true`. This blocks npm lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency when you run `npm install` or `npm ci` inside the repo. See [THREATMODEL.md](./THREATMODEL.md) (threat T-S2) for the rationale.",
        "file": "README.md"
      },
      {
        "command": "install",
        "citation": "As a supply-chain hardening measure, this repository ships a project-level `.npmrc` that sets `ignore-scripts=true`. This blocks npm lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency when you run `npm install` or `npm ci` inside the repo. See [THREATMODEL.md](./THREATMODEL.md) (threat T-S2) for the rationale.",
        "file": "README.md"
      },
      {
        "command": "postinstall",
        "citation": "As a supply-chain hardening measure, this repository ships a project-level `.npmrc` that sets `ignore-scripts=true`. This blocks npm lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency when you run `npm install` or `npm ci` inside the repo. See [THREATMODEL.md](./THREATMODEL.md) (threat T-S2) for the rationale.",
        "file": "README.md"
      },
      {
        "command": "prepare",
        "citation": "As a supply-chain hardening measure, this repository ships a project-level `.npmrc` that sets `ignore-scripts=true`. This blocks npm lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency when you run `npm install` or `npm ci` inside the repo. See [THREATMODEL.md](./THREATMODEL.md) (threat T-S2) for the rationale.",
        "file": "README.md"
      },
      {
        "command": "npm install",
        "citation": "As a supply-chain hardening measure, this repository ships a project-level `.npmrc` that sets `ignore-scripts=true`. This blocks npm lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency when you run `npm install` or `npm ci` inside the repo. See [THREATMODEL.md](./THREATMODEL.md) (threat T-S2) for the rationale.",
        "file": "README.md"
      },
      {
        "command": "npm ci",
        "citation": "As a supply-chain hardening measure, this repository ships a project-level `.npmrc` that sets `ignore-scripts=true`. This blocks npm lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency when you run `npm install` or `npm ci` inside the repo. See [THREATMODEL.md](./THREATMODEL.md) (threat T-S2) for the rationale.",
        "file": "README.md"
      },
      {
        "command": "prepare",
        "citation": "One consequence: the repository's own `prepare` hook (which installs Husky's git hooks) will **not** run automatically. After your first install, enable the git hooks manually:",
        "file": "README.md"
      },
      {
        "command": "npm install",
        "citation": "Run those two commands once per fresh checkout. You do **not** need to re-run them after every subsequent `npm install`.",
        "file": "README.md"
      },
      {
        "command": ".npmrc",
        "citation": "Do not remove `ignore-scripts=true` from `.npmrc` to \"fix\" this. That reopens the lifecycle-script attack surface for every other package in the tree. All CI workflows already invoke npm with `--ignore-scripts`, so local behaviour matches CI.",
        "file": "README.md"
      },
      {
        "command": "--ignore-scripts",
        "citation": "Do not remove `ignore-scripts=true` from `.npmrc` to \"fix\" this. That reopens the lifecycle-script attack surface for every other package in the tree. All CI workflows already invoke npm with `--ignore-scripts`, so local behaviour matches CI.",
        "file": "README.md"
      },
      {
        "command": "import axios",
        "citation": "| Runtime | Applications that `import axios` | Malicious servers, network attackers, malicious application input |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "config.auth",
        "citation": "| Credentials in transit | `config.auth`, `Authorization` headers, cookies, XSRF tokens |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "Authorization",
        "citation": "| Credentials in transit | `config.auth`, `Authorization` headers, cookies, XSRF tokens |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "config",
        "citation": "1. Caller to axios. The caller is fully trusted. Anything the caller passes in `config` is assumed intentional. axios does not defend against a malicious caller; that is a non-goal.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "Location",
        "citation": "2. axios to network. Everything past the socket is untrusted: response status, headers, body, redirect `Location`, proxy responses.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "HTTP_PROXY",
        "citation": "3. axios to environment variables. `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` are read by `proxy-from-env`. An attacker who controls the environment can redirect all traffic. This is treated as trusted because it has the same privilege as the process, but it is a relevant pivot in container-escape and CI scenarios.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "HTTPS_PROXY",
        "citation": "3. axios to environment variables. `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` are read by `proxy-from-env`. An attacker who controls the environment can redirect all traffic. This is treated as trusted because it has the same privilege as the process, but it is a relevant pivot in container-escape and CI scenarios.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "NO_PROXY",
        "citation": "3. axios to environment variables. `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` are read by `proxy-from-env`. An attacker who controls the environment can redirect all traffic. This is treated as trusted because it has the same privilege as the process, but it is a relevant pivot in container-escape and CI scenarios.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "proxy-from-env",
        "citation": "3. axios to environment variables. `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` are read by `proxy-from-env`. An attacker who controls the environment can redirect all traffic. This is treated as trusted because it has the same privilege as the process, but it is a relevant pivot in container-escape and CI scenarios.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "transformRequest",
        "citation": "4. Caller-supplied hooks to axios internals. Interceptors, `transformRequest`, `transformResponse`, `paramsSerializer`, `beforeRedirect`, and custom adapters run with full process privilege. axios does not sandbox them.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "transformResponse",
        "citation": "4. Caller-supplied hooks to axios internals. Interceptors, `transformRequest`, `transformResponse`, `paramsSerializer`, `beforeRedirect`, and custom adapters run with full process privilege. axios does not sandbox them.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "paramsSerializer",
        "citation": "4. Caller-supplied hooks to axios internals. Interceptors, `transformRequest`, `transformResponse`, `paramsSerializer`, `beforeRedirect`, and custom adapters run with full process privilege. axios does not sandbox them.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "beforeRedirect",
        "citation": "4. Caller-supplied hooks to axios internals. Interceptors, `transformRequest`, `transformResponse`, `paramsSerializer`, `beforeRedirect`, and custom adapters run with full process privilege. axios does not sandbox them.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "config.url",
        "citation": "| **Description** | Application interpolates user input into `config.url` or `config.baseURL`. Attacker supplies `http://169.254.169.254/`, `http://localhost:6379/`, `file://`, `gopher://`, etc. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "config.baseURL",
        "citation": "| **Description** | Application interpolates user input into `config.url` or `config.baseURL`. Attacker supplies `http://169.254.169.254/`, `http://localhost:6379/`, `file://`, `gopher://`, etc. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "allowAbsoluteUrls: false",
        "citation": "| **Mitigations** | • `allowAbsoluteUrls: false` prevents a relative `url` from overriding `baseURL` (`lib/core/buildFullPath.js`). Defaults to `true` for back-compat. <br>• The HTTP adapter only speaks `http:`/`https:`/`file:`/`data:` (Node) or `http:`/`https:`/`file:`/`blob:`/`url:`/`data:` (browser); exotic schemes like `gopher:` are rejected (`lib/platform/node/index.js`, `lib/platform/browser/index.js`). <br>• No built-in host allowlist. Callers must validate destinations themselves. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "url",
        "citation": "| **Mitigations** | • `allowAbsoluteUrls: false` prevents a relative `url` from overriding `baseURL` (`lib/core/buildFullPath.js`). Defaults to `true` for back-compat. <br>• The HTTP adapter only speaks `http:`/`https:`/`file:`/`data:` (Node) or `http:`/`https:`/`file:`/`blob:`/`url:`/`data:` (browser); exotic schemes like `gopher:` are rejected (`lib/platform/node/index.js`, `lib/platform/browser/index.js`). <br>• No built-in host allowlist. Callers must validate destinations themselves. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "baseURL",
        "citation": "| **Mitigations** | • `allowAbsoluteUrls: false` prevents a relative `url` from overriding `baseURL` (`lib/core/buildFullPath.js`). Defaults to `true` for back-compat. <br>• The HTTP adapter only speaks `http:`/`https:`/`file:`/`data:` (Node) or `http:`/`https:`/`file:`/`blob:`/`url:`/`data:` (browser); exotic schemes like `gopher:` are rejected (`lib/platform/node/index.js`, `lib/platform/browser/index.js`). <br>• No built-in host allowlist. Callers must validate destinations themselves. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "true",
        "citation": "| **Mitigations** | • `allowAbsoluteUrls: false` prevents a relative `url` from overriding `baseURL` (`lib/core/buildFullPath.js`). Defaults to `true` for back-compat. <br>• The HTTP adapter only speaks `http:`/`https:`/`file:`/`data:` (Node) or `http:`/`https:`/`file:`/`blob:`/`url:`/`data:` (browser); exotic schemes like `gopher:` are rejected (`lib/platform/node/index.js`, `lib/platform/browser/index.js`). <br>• No built-in host allowlist. Callers must validate destinations themselves. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "Authorization: Bearer …",
        "citation": "| **Description** | Caller sets `Authorization: Bearer …` and requests `https://api.trusted.com/x`. Server responds `302 Location: https://evil.com/`. Does the bearer token go to evil.com? |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "302 Location: https://evil.com/",
        "citation": "| **Description** | Caller sets `Authorization: Bearer …` and requests `https://api.trusted.com/x`. Server responds `302 Location: https://evil.com/`. Does the bearer token go to evil.com? |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "Authorization",
        "citation": "| **Mitigations** | • Node adapter delegates to `follow-redirects@^1.16.0`, which strips `Authorization`, `Cookie`, and `Proxy-Authorization` on cross-host redirects and on HTTPS→HTTP downgrades. <br>• `sensitiveHeaders` lets callers list custom secret-bearing headers (for example `X-API-Key`) that axios strips on cross-origin redirects. <br>• `maxRedirects` defaults to 5; set to `0` to handle redirects manually. <br>• `beforeRedirect` callback allows custom inspection. <br>• Browser adapters (XHR/fetch) delegate to the browser, which applies its own cross-origin credential rules. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "Cookie",
        "citation": "| **Mitigations** | • Node adapter delegates to `follow-redirects@^1.16.0`, which strips `Authorization`, `Cookie`, and `Proxy-Authorization` on cross-host redirects and on HTTPS→HTTP downgrades. <br>• `sensitiveHeaders` lets callers list custom secret-bearing headers (for example `X-API-Key`) that axios strips on cross-origin redirects. <br>• `maxRedirects` defaults to 5; set to `0` to handle redirects manually. <br>• `beforeRedirect` callback allows custom inspection. <br>• Browser adapters (XHR/fetch) delegate to the browser, which applies its own cross-origin credential rules. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "Proxy-Authorization",
        "citation": "| **Mitigations** | • Node adapter delegates to `follow-redirects@^1.16.0`, which strips `Authorization`, `Cookie`, and `Proxy-Authorization` on cross-host redirects and on HTTPS→HTTP downgrades. <br>• `sensitiveHeaders` lets callers list custom secret-bearing headers (for example `X-API-Key`) that axios strips on cross-origin redirects. <br>• `maxRedirects` defaults to 5; set to `0` to handle redirects manually. <br>• `beforeRedirect` callback allows custom inspection. <br>• Browser adapters (XHR/fetch) delegate to the browser, which applies its own cross-origin credential rules. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "sensitiveHeaders",
        "citation": "| **Mitigations** | • Node adapter delegates to `follow-redirects@^1.16.0`, which strips `Authorization`, `Cookie`, and `Proxy-Authorization` on cross-host redirects and on HTTPS→HTTP downgrades. <br>• `sensitiveHeaders` lets callers list custom secret-bearing headers (for example `X-API-Key`) that axios strips on cross-origin redirects. <br>• `maxRedirects` defaults to 5; set to `0` to handle redirects manually. <br>• `beforeRedirect` callback allows custom inspection. <br>• Browser adapters (XHR/fetch) delegate to the browser, which applies its own cross-origin credential rules. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "X-API-Key",
        "citation": "| **Mitigations** | • Node adapter delegates to `follow-redirects@^1.16.0`, which strips `Authorization`, `Cookie`, and `Proxy-Authorization` on cross-host redirects and on HTTPS→HTTP downgrades. <br>• `sensitiveHeaders` lets callers list custom secret-bearing headers (for example `X-API-Key`) that axios strips on cross-origin redirects. <br>• `maxRedirects` defaults to 5; set to `0` to handle redirects manually. <br>• `beforeRedirect` callback allows custom inspection. <br>• Browser adapters (XHR/fetch) delegate to the browser, which applies its own cross-origin credential rules. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "maxRedirects",
        "citation": "| **Mitigations** | • Node adapter delegates to `follow-redirects@^1.16.0`, which strips `Authorization`, `Cookie`, and `Proxy-Authorization` on cross-host redirects and on HTTPS→HTTP downgrades. <br>• `sensitiveHeaders` lets callers list custom secret-bearing headers (for example `X-API-Key`) that axios strips on cross-origin redirects. <br>• `maxRedirects` defaults to 5; set to `0` to handle redirects manually. <br>• `beforeRedirect` callback allows custom inspection. <br>• Browser adapters (XHR/fetch) delegate to the browser, which applies its own cross-origin credential rules. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "0",
        "citation": "| **Mitigations** | • Node adapter delegates to `follow-redirects@^1.16.0`, which strips `Authorization`, `Cookie`, and `Proxy-Authorization` on cross-host redirects and on HTTPS→HTTP downgrades. <br>• `sensitiveHeaders` lets callers list custom secret-bearing headers (for example `X-API-Key`) that axios strips on cross-origin redirects. <br>• `maxRedirects` defaults to 5; set to `0` to handle redirects manually. <br>• `beforeRedirect` callback allows custom inspection. <br>• Browser adapters (XHR/fetch) delegate to the browser, which applies its own cross-origin credential rules. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "beforeRedirect",
        "citation": "| **Mitigations** | • Node adapter delegates to `follow-redirects@^1.16.0`, which strips `Authorization`, `Cookie`, and `Proxy-Authorization` on cross-host redirects and on HTTPS→HTTP downgrades. <br>• `sensitiveHeaders` lets callers list custom secret-bearing headers (for example `X-API-Key`) that axios strips on cross-origin redirects. <br>• `maxRedirects` defaults to 5; set to `0` to handle redirects manually. <br>• `beforeRedirect` callback allows custom inspection. <br>• Browser adapters (XHR/fetch) delegate to the browser, which applies its own cross-origin credential rules. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "follow-redirects",
        "citation": "| **Residual risk** | Low for standard credential headers and configured custom secret headers. We inherit `follow-redirects`' security posture - it is a critical transitive dependency and its CVEs are our CVEs. Callers must list any custom secret headers they want stripped. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "headers: { 'X-User': req.query.name }",
        "citation": "| **Description** | Application puts user input into a header value: `headers: { 'X-User': req.query.name }`. Attacker supplies `foo\\r\\nX-Injected: bar\\r\\n\\r\\n<body>`. A related surface is multipart per-part headers: attacker-controlled `blob.type` or `blob.name` flowing into the multipart body. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "foo\\r\\nX-Injected: bar\\r\\n\\r\\n<body>",
        "citation": "| **Description** | Application puts user input into a header value: `headers: { 'X-User': req.query.name }`. Attacker supplies `foo\\r\\nX-Injected: bar\\r\\n\\r\\n<body>`. A related surface is multipart per-part headers: attacker-controlled `blob.type` or `blob.name` flowing into the multipart body. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "blob.type",
        "citation": "| **Description** | Application puts user input into a header value: `headers: { 'X-User': req.query.name }`. Attacker supplies `foo\\r\\nX-Injected: bar\\r\\n\\r\\n<body>`. A related surface is multipart per-part headers: attacker-controlled `blob.type` or `blob.name` flowing into the multipart body. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "blob.name",
        "citation": "| **Description** | Application puts user input into a header value: `headers: { 'X-User': req.query.name }`. Attacker supplies `foo\\r\\nX-Injected: bar\\r\\n\\r\\n<body>`. A related surface is multipart per-part headers: attacker-controlled `blob.type` or `blob.name` flowing into the multipart body. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "http",
        "citation": "| **Mitigations** | • `lib/core/AxiosHeaders.js` rejects header values containing `\\r` or `\\n`, and validates header names against an RFC-7230-shaped charset. Node's own `http` module also rejects these. <br>• `lib/helpers/formDataToStream.js` strips CRLF from `value.type` and percent-encodes CRLF/`\"` in `value.name` via `escapeName()` before interpolating them into per-part headers (GHSA-445q-vr5w-6q77). Node's `http` module does not defend here; multipart injection is in body bytes, not request headers. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "value.type",
        "citation": "| **Mitigations** | • `lib/core/AxiosHeaders.js` rejects header values containing `\\r` or `\\n`, and validates header names against an RFC-7230-shaped charset. Node's own `http` module also rejects these. <br>• `lib/helpers/formDataToStream.js` strips CRLF from `value.type` and percent-encodes CRLF/`\"` in `value.name` via `escapeName()` before interpolating them into per-part headers (GHSA-445q-vr5w-6q77). Node's `http` module does not defend here; multipart injection is in body bytes, not request headers. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "value.name",
        "citation": "| **Mitigations** | • `lib/core/AxiosHeaders.js` rejects header values containing `\\r` or `\\n`, and validates header names against an RFC-7230-shaped charset. Node's own `http` module also rejects these. <br>• `lib/helpers/formDataToStream.js` strips CRLF from `value.type` and percent-encodes CRLF/`\"` in `value.name` via `escapeName()` before interpolating them into per-part headers (GHSA-445q-vr5w-6q77). Node's `http` module does not defend here; multipart injection is in body bytes, not request headers. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "http",
        "citation": "| **Mitigations** | • `lib/core/AxiosHeaders.js` rejects header values containing `\\r` or `\\n`, and validates header names against an RFC-7230-shaped charset. Node's own `http` module also rejects these. <br>• `lib/helpers/formDataToStream.js` strips CRLF from `value.type` and percent-encodes CRLF/`\"` in `value.name` via `escapeName()` before interpolating them into per-part headers (GHSA-445q-vr5w-6q77). Node's `http` module does not defend here; multipart injection is in body bytes, not request headers. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "{\"__proto__\": {\"isAdmin\": true}}",
        "citation": "| **Description** | Server returns `{\"__proto__\": {\"isAdmin\": true}}`. If axios merged this into an object naively, every `{}` in the process would gain `.isAdmin`. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": ".isAdmin",
        "citation": "| **Description** | Server returns `{\"__proto__\": {\"isAdmin\": true}}`. If axios merged this into an object naively, every `{}` in the process would gain `.isAdmin`. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "JSON.parse",
        "citation": "| **Mitigations** | • `JSON.parse` itself does not pollute (it creates own-properties named `__proto__`, not prototype links). <br>• Internal merge paths filter dangerous keys: `lib/utils.js` and `lib/core/mergeConfig.js` filter `__proto__` / `constructor` / `prototype`; `lib/helpers/formDataToJSON.js` filters `__proto__`. <br>• These were added in response to past advisories. A regression here is a P0. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "__proto__",
        "citation": "| **Mitigations** | • `JSON.parse` itself does not pollute (it creates own-properties named `__proto__`, not prototype links). <br>• Internal merge paths filter dangerous keys: `lib/utils.js` and `lib/core/mergeConfig.js` filter `__proto__` / `constructor` / `prototype`; `lib/helpers/formDataToJSON.js` filters `__proto__`. <br>• These were added in response to past advisories. A regression here is a P0. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "__proto__",
        "citation": "| **Mitigations** | • `JSON.parse` itself does not pollute (it creates own-properties named `__proto__`, not prototype links). <br>• Internal merge paths filter dangerous keys: `lib/utils.js` and `lib/core/mergeConfig.js` filter `__proto__` / `constructor` / `prototype`; `lib/helpers/formDataToJSON.js` filters `__proto__`. <br>• These were added in response to past advisories. A regression here is a P0. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "constructor",
        "citation": "| **Mitigations** | • `JSON.parse` itself does not pollute (it creates own-properties named `__proto__`, not prototype links). <br>• Internal merge paths filter dangerous keys: `lib/utils.js` and `lib/core/mergeConfig.js` filter `__proto__` / `constructor` / `prototype`; `lib/helpers/formDataToJSON.js` filters `__proto__`. <br>• These were added in response to past advisories. A regression here is a P0. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "prototype",
        "citation": "| **Mitigations** | • `JSON.parse` itself does not pollute (it creates own-properties named `__proto__`, not prototype links). <br>• Internal merge paths filter dangerous keys: `lib/utils.js` and `lib/core/mergeConfig.js` filter `__proto__` / `constructor` / `prototype`; `lib/helpers/formDataToJSON.js` filters `__proto__`. <br>• These were added in response to past advisories. A regression here is a P0. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "__proto__",
        "citation": "| **Mitigations** | • `JSON.parse` itself does not pollute (it creates own-properties named `__proto__`, not prototype links). <br>• Internal merge paths filter dangerous keys: `lib/utils.js` and `lib/core/mergeConfig.js` filter `__proto__` / `constructor` / `prototype`; `lib/helpers/formDataToJSON.js` filters `__proto__`. <br>• These were added in response to past advisories. A regression here is a P0. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "Object.prototype",
        "citation": "#### T-R4b: Prototype pollution, read-side gadgets (polluted `Object.prototype` drives axios behavior)",
        "file": "THREATMODEL.md"
      },
      {
        "command": "Object.prototype",
        "citation": "| **Description** | A _different_ library in the caller's dependency tree pollutes `Object.prototype` (e.g. `Object.prototype.validateStatus = () => true`). axios code that reads a config property through the prototype chain then picks up the attacker's value and executes the associated behavior. Each reachable property is a distinct **gadget**: `validateStatus` (bypass HTTP error handling), `parseReviver` (silently tamper JSON response bodies), `transport` / `httpAgent` / `lookup` (MITM / intercept), `withXSRFToken` (leak XSRF token cross-origin), `transformResponse` (response replacement), and so on. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "Object.prototype.validateStatus = () => true",
        "citation": "| **Description** | A _different_ library in the caller's dependency tree pollutes `Object.prototype` (e.g. `Object.prototype.validateStatus = () => true`). axios code that reads a config property through the prototype chain then picks up the attacker's value and executes the associated behavior. Each reachable property is a distinct **gadget**: `validateStatus` (bypass HTTP error handling), `parseReviver` (silently tamper JSON response bodies), `transport` / `httpAgent` / `lookup` (MITM / intercept), `withXSRFToken` (leak XSRF token cross-origin), `transformResponse` (response replacement), and so on. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "validateStatus",
        "citation": "| **Description** | A _different_ library in the caller's dependency tree pollutes `Object.prototype` (e.g. `Object.prototype.validateStatus = () => true`). axios code that reads a config property through the prototype chain then picks up the attacker's value and executes the associated behavior. Each reachable property is a distinct **gadget**: `validateStatus` (bypass HTTP error handling), `parseReviver` (silently tamper JSON response bodies), `transport` / `httpAgent` / `lookup` (MITM / intercept), `withXSRFToken` (leak XSRF token cross-origin), `transformResponse` (response replacement), and so on. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "parseReviver",
        "citation": "| **Description** | A _different_ library in the caller's dependency tree pollutes `Object.prototype` (e.g. `Object.prototype.validateStatus = () => true`). axios code that reads a config property through the prototype chain then picks up the attacker's value and executes the associated behavior. Each reachable property is a distinct **gadget**: `validateStatus` (bypass HTTP error handling), `parseReviver` (silently tamper JSON response bodies), `transport` / `httpAgent` / `lookup` (MITM / intercept), `withXSRFToken` (leak XSRF token cross-origin), `transformResponse` (response replacement), and so on. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "transport",
        "citation": "| **Description** | A _different_ library in the caller's dependency tree pollutes `Object.prototype` (e.g. `Object.prototype.validateStatus = () => true`). axios code that reads a config property through the prototype chain then picks up the attacker's value and executes the associated behavior. Each reachable property is a distinct **gadget**: `validateStatus` (bypass HTTP error handling), `parseReviver` (silently tamper JSON response bodies), `transport` / `httpAgent` / `lookup` (MITM / intercept), `withXSRFToken` (leak XSRF token cross-origin), `transformResponse` (response replacement), and so on. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "httpAgent",
        "citation": "| **Description** | A _different_ library in the caller's dependency tree pollutes `Object.prototype` (e.g. `Object.prototype.validateStatus = () => true`). axios code that reads a config property through the prototype chain then picks up the attacker's value and executes the associated behavior. Each reachable property is a distinct **gadget**: `validateStatus` (bypass HTTP error handling), `parseReviver` (silently tamper JSON response bodies), `transport` / `httpAgent` / `lookup` (MITM / intercept), `withXSRFToken` (leak XSRF token cross-origin), `transformResponse` (response replacement), and so on. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "lookup",
        "citation": "| **Description** | A _different_ library in the caller's dependency tree pollutes `Object.prototype` (e.g. `Object.prototype.validateStatus = () => true`). axios code that reads a config property through the prototype chain then picks up the attacker's value and executes the associated behavior. Each reachable property is a distinct **gadget**: `validateStatus` (bypass HTTP error handling), `parseReviver` (silently tamper JSON response bodies), `transport` / `httpAgent` / `lookup` (MITM / intercept), `withXSRFToken` (leak XSRF token cross-origin), `transformResponse` (response replacement), and so on. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "withXSRFToken",
        "citation": "| **Description** | A _different_ library in the caller's dependency tree pollutes `Object.prototype` (e.g. `Object.prototype.validateStatus = () => true`). axios code that reads a config property through the prototype chain then picks up the attacker's value and executes the associated behavior. Each reachable property is a distinct **gadget**: `validateStatus` (bypass HTTP error handling), `parseReviver` (silently tamper JSON response bodies), `transport` / `httpAgent` / `lookup` (MITM / intercept), `withXSRFToken` (leak XSRF token cross-origin), `transformResponse` (response replacement), and so on. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "transformResponse",
        "citation": "| **Description** | A _different_ library in the caller's dependency tree pollutes `Object.prototype` (e.g. `Object.prototype.validateStatus = () => true`). axios code that reads a config property through the prototype chain then picks up the attacker's value and executes the associated behavior. Each reachable property is a distinct **gadget**: `validateStatus` (bypass HTTP error handling), `parseReviver` (silently tamper JSON response bodies), `transport` / `httpAgent` / `lookup` (MITM / intercept), `withXSRFToken` (leak XSRF token cross-origin), `transformResponse` (response replacement), and so on. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "hasOwnProp",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "config1",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "config2",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "hasOwnProp",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "mergeDirectKeys",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "validateStatus",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "hasOwnProp",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "in",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "transformResponse",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "transformRequest",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "transitional",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "responseType",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "parseReviver",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "response",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "transport",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "httpAgent",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "httpsAgent",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "lookup",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "family",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "http2Options",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "hasOwnProp",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "withXSRFToken",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "=== true",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "1",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "axios.get",
        "citation": "| **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "config.foo",
        "citation": "| **Residual risk** | Low, but the surface is every config property read. Any new code path that reads `config.foo` / `this.foo` / destructures from a merged config must use a `hasOwnProp` guard. The non-goal that axios does not defend a caller with a polluted prototype is narrower than it sounds. The pollution typically comes from a transitive dependency, not from the caller's own intent, and the above mitigations neutralize the reachable gadgets even when the prototype is polluted. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "this.foo",
        "citation": "| **Residual risk** | Low, but the surface is every config property read. Any new code path that reads `config.foo` / `this.foo` / destructures from a merged config must use a `hasOwnProp` guard. The non-goal that axios does not defend a caller with a polluted prototype is narrower than it sounds. The pollution typically comes from a transitive dependency, not from the caller's own intent, and the above mitigations neutralize the reachable gadgets even when the prototype is polluted. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "hasOwnProp",
        "citation": "| **Residual risk** | Low, but the surface is every config property read. Any new code path that reads `config.foo` / `this.foo` / destructures from a merged config must use a `hasOwnProp` guard. The non-goal that axios does not defend a caller with a polluted prototype is narrower than it sounds. The pollution typically comes from a transitive dependency, not from the caller's own intent, and the above mitigations neutralize the reachable gadgets even when the prototype is polluted. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "Content-Encoding: gzip",
        "citation": "| **Description** | Server sends `Content-Encoding: gzip` with a 10 KB body that decompresses to 10 GB. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "maxContentLength",
        "citation": "| **Mitigations** | • `maxContentLength` bounds the decompressed response size in the Node adapter (`lib/adapters/http.js`), enforced chunk-by-chunk on the decompressed stream for both buffered and `responseType: 'stream'` responses (stream path fixed in GHSA-vf2m-468p-8v99). <br>• `maxBodyLength` bounds the request side, including when `maxRedirects === 0` (previously bypassed). <br>• Both default to `-1` (unlimited). Callers handling untrusted servers should set these. The README carries a top-level \"security notice\" call-out and `docs/pages/misc/security.md` documents the exact mitigation snippet in all four locales. <br>• Decompression uses Node's `zlib`, which streams. Memory is bounded by the limit, not the full expansion. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "responseType: 'stream'",
        "citation": "| **Mitigations** | • `maxContentLength` bounds the decompressed response size in the Node adapter (`lib/adapters/http.js`), enforced chunk-by-chunk on the decompressed stream for both buffered and `responseType: 'stream'` responses (stream path fixed in GHSA-vf2m-468p-8v99). <br>• `maxBodyLength` bounds the request side, including when `maxRedirects === 0` (previously bypassed). <br>• Both default to `-1` (unlimited). Callers handling untrusted servers should set these. The README carries a top-level \"security notice\" call-out and `docs/pages/misc/security.md` documents the exact mitigation snippet in all four locales. <br>• Decompression uses Node's `zlib`, which streams. Memory is bounded by the limit, not the full expansion. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "maxBodyLength",
        "citation": "| **Mitigations** | • `maxContentLength` bounds the decompressed response size in the Node adapter (`lib/adapters/http.js`), enforced chunk-by-chunk on the decompressed stream for both buffered and `responseType: 'stream'` responses (stream path fixed in GHSA-vf2m-468p-8v99). <br>• `maxBodyLength` bounds the request side, including when `maxRedirects === 0` (previously bypassed). <br>• Both default to `-1` (unlimited). Callers handling untrusted servers should set these. The README carries a top-level \"security notice\" call-out and `docs/pages/misc/security.md` documents the exact mitigation snippet in all four locales. <br>• Decompression uses Node's `zlib`, which streams. Memory is bounded by the limit, not the full expansion. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "maxRedirects === 0",
        "citation": "| **Mitigations** | • `maxContentLength` bounds the decompressed response size in the Node adapter (`lib/adapters/http.js`), enforced chunk-by-chunk on the decompressed stream for both buffered and `responseType: 'stream'` responses (stream path fixed in GHSA-vf2m-468p-8v99). <br>• `maxBodyLength` bounds the request side, including when `maxRedirects === 0` (previously bypassed). <br>• Both default to `-1` (unlimited). Callers handling untrusted servers should set these. The README carries a top-level \"security notice\" call-out and `docs/pages/misc/security.md` documents the exact mitigation snippet in all four locales. <br>• Decompression uses Node's `zlib`, which streams. Memory is bounded by the limit, not the full expansion. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "-1",
        "citation": "| **Mitigations** | • `maxContentLength` bounds the decompressed response size in the Node adapter (`lib/adapters/http.js`), enforced chunk-by-chunk on the decompressed stream for both buffered and `responseType: 'stream'` responses (stream path fixed in GHSA-vf2m-468p-8v99). <br>• `maxBodyLength` bounds the request side, including when `maxRedirects === 0` (previously bypassed). <br>• Both default to `-1` (unlimited). Callers handling untrusted servers should set these. The README carries a top-level \"security notice\" call-out and `docs/pages/misc/security.md` documents the exact mitigation snippet in all four locales. <br>• Decompression uses Node's `zlib`, which streams. Memory is bounded by the limit, not the full expansion. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "zlib",
        "citation": "| **Mitigations** | • `maxContentLength` bounds the decompressed response size in the Node adapter (`lib/adapters/http.js`), enforced chunk-by-chunk on the decompressed stream for both buffered and `responseType: 'stream'` responses (stream path fixed in GHSA-vf2m-468p-8v99). <br>• `maxBodyLength` bounds the request side, including when `maxRedirects === 0` (previously bypassed). <br>• Both default to `-1` (unlimited). Callers handling untrusted servers should set these. The README carries a top-level \"security notice\" call-out and `docs/pages/misc/security.md` documents the exact mitigation snippet in all four locales. <br>• Decompression uses Node's `zlib`, which streams. Memory is bounded by the limit, not the full expansion. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "httpsAgent: new https.Agent({ rejectUnauthorized: false })",
        "citation": "| **Description** | Caller passes `httpsAgent: new https.Agent({ rejectUnauthorized: false })` to \"fix\" a certificate error in dev, ships it to prod. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "https",
        "citation": "| **In scope?** | **No.** axios delegates TLS entirely to Node's `https` module / the browser. We do not inspect or warn on agent configuration. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "xsrfCookieName",
        "citation": "| **Description** | Browser deployment. `xsrfCookieName` is set; attacker tricks the app into requesting `https://evil.com` and the XSRF token cookie value is attached as a header. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "withXSRFToken",
        "citation": "| **Mitigations** | `lib/helpers/resolveConfig.js` only attaches the XSRF header when `isURLSameOrigin()` passes (or when `withXSRFToken` is explicitly forced). This was the fix for **CVE-2023-45857**. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "URL",
        "citation": "| **Residual risk** | Low. The same-origin check uses the WHATWG `URL` parser (`lib/helpers/isURLSameOrigin.js`), which is robust against parser-differential attacks. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "AxiosError",
        "citation": "| **Description** | Request fails. `AxiosError` includes `config`, which includes `config.auth`, `config.headers.Authorization`, `config.httpsAgent` (with embedded client cert/key). Caller logs the error, exposing secrets in logs. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "config",
        "citation": "| **Description** | Request fails. `AxiosError` includes `config`, which includes `config.auth`, `config.headers.Authorization`, `config.httpsAgent` (with embedded client cert/key). Caller logs the error, exposing secrets in logs. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "config.auth",
        "citation": "| **Description** | Request fails. `AxiosError` includes `config`, which includes `config.auth`, `config.headers.Authorization`, `config.httpsAgent` (with embedded client cert/key). Caller logs the error, exposing secrets in logs. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "config.headers.Authorization",
        "citation": "| **Description** | Request fails. `AxiosError` includes `config`, which includes `config.auth`, `config.headers.Authorization`, `config.httpsAgent` (with embedded client cert/key). Caller logs the error, exposing secrets in logs. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "config.httpsAgent",
        "citation": "| **Description** | Request fails. `AxiosError` includes `config`, which includes `config.auth`, `config.headers.Authorization`, `config.httpsAgent` (with embedded client cert/key). Caller logs the error, exposing secrets in logs. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": ".env",
        "citation": "| **Description** | Attacker controls the process environment (compromised CI step, container escape, `.env` injection) and sets `HTTPS_PROXY=http://evil.com:8080`. All axios traffic is now MITM'd. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "config.proxy: false",
        "citation": "| **Mitigations** | • `config.proxy: false` disables environment-based proxy detection entirely. <br>• `NO_PROXY` is honored (`lib/helpers/shouldBypassProxy.js`), with recent hardening for CIDR ranges, IPv6 literals, and wildcard patterns to close parser-differential edge cases. <br>• HTTPS through any proxy uses CONNECT tunneling via `https-proxy-agent` so the origin's cert is validated end-to-end and the proxy sees only SNI, never the URL, headers, or body. `Proxy-Authorization` is sent on the CONNECT request only, never on the wrapped TLS-protected request. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "NO_PROXY",
        "citation": "| **Mitigations** | • `config.proxy: false` disables environment-based proxy detection entirely. <br>• `NO_PROXY` is honored (`lib/helpers/shouldBypassProxy.js`), with recent hardening for CIDR ranges, IPv6 literals, and wildcard patterns to close parser-differential edge cases. <br>• HTTPS through any proxy uses CONNECT tunneling via `https-proxy-agent` so the origin's cert is validated end-to-end and the proxy sees only SNI, never the URL, headers, or body. `Proxy-Authorization` is sent on the CONNECT request only, never on the wrapped TLS-protected request. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "https-proxy-agent",
        "citation": "| **Mitigations** | • `config.proxy: false` disables environment-based proxy detection entirely. <br>• `NO_PROXY` is honored (`lib/helpers/shouldBypassProxy.js`), with recent hardening for CIDR ranges, IPv6 literals, and wildcard patterns to close parser-differential edge cases. <br>• HTTPS through any proxy uses CONNECT tunneling via `https-proxy-agent` so the origin's cert is validated end-to-end and the proxy sees only SNI, never the URL, headers, or body. `Proxy-Authorization` is sent on the CONNECT request only, never on the wrapped TLS-protected request. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "Proxy-Authorization",
        "citation": "| **Mitigations** | • `config.proxy: false` disables environment-based proxy detection entirely. <br>• `NO_PROXY` is honored (`lib/helpers/shouldBypassProxy.js`), with recent hardening for CIDR ranges, IPv6 literals, and wildcard patterns to close parser-differential edge cases. <br>• HTTPS through any proxy uses CONNECT tunneling via `https-proxy-agent` so the origin's cert is validated end-to-end and the proxy sees only SNI, never the URL, headers, or body. `Proxy-Authorization` is sent on the CONNECT request only, never on the wrapped TLS-protected request. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "Authorization",
        "citation": "| **Description** | Caller installs a third-party \"axios plugin\" from npm that registers an interceptor exfiltrating every `Authorization` header. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "data",
        "citation": "| **Description** | Caller passes untrusted object input as request `data` in a context that serializes to `multipart/form-data` or `application/x-www-form-urlencoded`. A pathological input with thousands of nesting levels causes `lib/helpers/toFormData.js` to recurse until stack overflow or the process is killed. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "formSerializer.maxDepth",
        "citation": "| **Mitigations** | • `formSerializer.maxDepth` caps recursion depth; default is 100, can be set to `Infinity` to disable. <br>• Exceeding the cap throws `AxiosError` with code `ERR_FORM_DATA_DEPTH_EXCEEDED` rather than crashing the process. <br>• Documented per locale in `docs/pages/advanced/multipart-form-data-format.md` and `docs/pages/advanced/x-www-form-urlencoded-format.md`. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "Infinity",
        "citation": "| **Mitigations** | • `formSerializer.maxDepth` caps recursion depth; default is 100, can be set to `Infinity` to disable. <br>• Exceeding the cap throws `AxiosError` with code `ERR_FORM_DATA_DEPTH_EXCEEDED` rather than crashing the process. <br>• Documented per locale in `docs/pages/advanced/multipart-form-data-format.md` and `docs/pages/advanced/x-www-form-urlencoded-format.md`. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "AxiosError",
        "citation": "| **Mitigations** | • `formSerializer.maxDepth` caps recursion depth; default is 100, can be set to `Infinity` to disable. <br>• Exceeding the cap throws `AxiosError` with code `ERR_FORM_DATA_DEPTH_EXCEEDED` rather than crashing the process. <br>• Documented per locale in `docs/pages/advanced/multipart-form-data-format.md` and `docs/pages/advanced/x-www-form-urlencoded-format.md`. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "ERR_FORM_DATA_DEPTH_EXCEEDED",
        "citation": "| **Mitigations** | • `formSerializer.maxDepth` caps recursion depth; default is 100, can be set to `Infinity` to disable. <br>• Exceeding the cap throws `AxiosError` with code `ERR_FORM_DATA_DEPTH_EXCEEDED` rather than crashing the process. <br>• Documented per locale in `docs/pages/advanced/multipart-form-data-format.md` and `docs/pages/advanced/x-www-form-urlencoded-format.md`. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "maxDepth: Infinity",
        "citation": "| **Residual risk** | Low when callers leave the default in place. Setting `maxDepth: Infinity` reintroduces the risk. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "config.url",
        "citation": "- Validate that `config.url` points somewhere \"safe.\" We don't know what safe means for your application.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "config",
        "citation": "- Redact `config` from thrown errors. The caller may legitimately need it for retry logic.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "Object.prototype",
        "citation": "- Defend against a fully compromised caller process (e.g. attacker-controlled code running inside the caller). For the narrower case of a polluted `Object.prototype` arriving via a transitive dependency, axios does defend the reachable config-read gadgets (see T-R4b), but any new config-read path must continue to use `hasOwnProp` guards to stay on this side of the line.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "hasOwnProp",
        "citation": "- Defend against a fully compromised caller process (e.g. attacker-controlled code running inside the caller). For the narrower case of a polluted `Object.prototype` arriving via a transitive dependency, axios does defend the reachable config-read gadgets (see T-R4b), but any new config-read path must continue to use `hasOwnProp` guards to stay on this side of the line.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "Object.keys",
        "citation": "- Defend against monkey-patched JavaScript or Node.js runtime APIs (`Object.keys`, `http.request`, `ClientRequest.prototype.setHeader`, `fetch`, etc.). If attacker-controlled code is already running in the same process, it can observe or alter requests below axios and this is outside axios' security boundary.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "http.request",
        "citation": "- Defend against monkey-patched JavaScript or Node.js runtime APIs (`Object.keys`, `http.request`, `ClientRequest.prototype.setHeader`, `fetch`, etc.). If attacker-controlled code is already running in the same process, it can observe or alter requests below axios and this is outside axios' security boundary.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "ClientRequest.prototype.setHeader",
        "citation": "- Defend against monkey-patched JavaScript or Node.js runtime APIs (`Object.keys`, `http.request`, `ClientRequest.prototype.setHeader`, `fetch`, etc.). If attacker-controlled code is already running in the same process, it can observe or alter requests below axios and this is outside axios' security boundary.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "fetch",
        "citation": "- Defend against monkey-patched JavaScript or Node.js runtime APIs (`Object.keys`, `http.request`, `ClientRequest.prototype.setHeader`, `fetch`, etc.). If attacker-controlled code is already running in the same process, it can observe or alter requests below axios and this is outside axios' security boundary.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "axios",
        "citation": "This model protects what gets published as `axios` on npm. A successful attack here compromises every downstream consumer at once. Given axios' install base, this is the higher-risk half of the document.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "axios",
        "citation": "| **The npm `axios` package name** | Attacker can publish malware as `axios@1.x.y+1`. Game over for the ecosystem. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "publish.yml",
        "citation": "| **GitHub `axios/axios` write access** | Attacker can push a tag, which triggers publish. Or modify `publish.yml` itself. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "follow-redirects",
        "citation": "| **Runtime dependency integrity** | `follow-redirects`, `form-data`, `proxy-from-env`, `https-proxy-agent` ship inside every axios install. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "form-data",
        "citation": "| **Runtime dependency integrity** | `follow-redirects`, `form-data`, `proxy-from-env`, `https-proxy-agent` ship inside every axios install. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "proxy-from-env",
        "citation": "| **Runtime dependency integrity** | `follow-redirects`, `form-data`, `proxy-from-env`, `https-proxy-agent` ship inside every axios install. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "https-proxy-agent",
        "citation": "| **Runtime dependency integrity** | `follow-redirects`, `form-data`, `proxy-from-env`, `https-proxy-agent` ship inside every axios install. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "pull_request",
        "citation": "1. Contributor PRs to main branch. PRs from forks are untrusted. CI runs them, but `pull_request` workflows have no access to secrets and use a read-only `GITHUB_TOKEN`.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "GITHUB_TOKEN",
        "citation": "1. Contributor PRs to main branch. PRs from forks are untrusted. CI runs them, but `pull_request` workflows have no access to secrets and use a read-only `GITHUB_TOKEN`.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "v1.x",
        "citation": "2. Main branch to release tag. Pushing to `v1.x` does not publish. Only pushing a `v1.*.*` tag does. Tag push requires write access.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "id-token: write",
        "citation": "3. GitHub Actions to npm. This boundary is crossed via OIDC (`id-token: write` to npm trusted publisher). The repo has no long-lived `NPM_TOKEN` secret.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "NPM_TOKEN",
        "citation": "3. GitHub Actions to npm. This boundary is crossed via OIDC (`id-token: write` to npm trusted publisher). The repo has no long-lived `NPM_TOKEN` secret.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm install",
        "citation": "| Compromised dependency | Attempt to run code on `npm install` via lifecycle scripts. Blocked on maintainer workstations (project `.npmrc`) and in CI (`--ignore-scripts` on every job). Residual execution path: plugin code under `npm run build` / `test` / `lint`. | Steal tokens, inject into build. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": ".npmrc",
        "citation": "| Compromised dependency | Attempt to run code on `npm install` via lifecycle scripts. Blocked on maintainer workstations (project `.npmrc`) and in CI (`--ignore-scripts` on every job). Residual execution path: plugin code under `npm run build` / `test` / `lint`. | Steal tokens, inject into build. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "--ignore-scripts",
        "citation": "| Compromised dependency | Attempt to run code on `npm install` via lifecycle scripts. Blocked on maintainer workstations (project `.npmrc`) and in CI (`--ignore-scripts` on every job). Residual execution path: plugin code under `npm run build` / `test` / `lint`. | Steal tokens, inject into build. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm run build",
        "citation": "| Compromised dependency | Attempt to run code on `npm install` via lifecycle scripts. Blocked on maintainer workstations (project `.npmrc`) and in CI (`--ignore-scripts` on every job). Residual execution path: plugin code under `npm run build` / `test` / `lint`. | Steal tokens, inject into build. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "test",
        "citation": "| Compromised dependency | Attempt to run code on `npm install` via lifecycle scripts. Blocked on maintainer workstations (project `.npmrc`) and in CI (`--ignore-scripts` on every job). Residual execution path: plugin code under `npm run build` / `test` / `lint`. | Steal tokens, inject into build. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "lint",
        "citation": "| Compromised dependency | Attempt to run code on `npm install` via lifecycle scripts. Blocked on maintainer workstations (project `.npmrc`) and in CI (`--ignore-scripts` on every job). Residual execution path: plugin code under `npm run build` / `test` / `lint`. | Steal tokens, inject into build. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "rollup",
        "citation": "| **Description** | Attacker opens a PR with a subtle backdoor: an obfuscated payload in a test fixture, a Unicode homoglyph in a comparison, or a malicious `rollup` plugin in the config. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "pull_request",
        "citation": "| **Mitigations** | • Mandatory review before merge. <br>• `pull_request` workflows run with no secrets and a read-only token, so a malicious test cannot exfiltrate anything from CI. <br>• `pull_request_target` is not used because it would grant secrets to fork code. <br>• `zizmor` lints workflow files for known-dangerous patterns. <br>• Branch protection on `v1.x`. <br>• Package, lockfile, and GitHub Actions update PRs are maintainer/bot-only; outside-collaborator PRs for those updates are closed. <br>• Path-scoped `.github/CODEOWNERS` flags sensitive paths explicitly: runtime source (`/lib/`, `/index.*`), build/release infrastructure (`rollup.config.js`, `package.json`, `package-lock.json`, `.npmrc`), CI automation (`.github/workflows/`, `.github/dependabot.yml`, `CODEOWNERS` itself), and security-critical docs (`THREATMODEL.md`, `SECURITY.md`). Changes to these paths surface the scoped ownership rule in the PR review UI distinct from the catch-all. The audit trail shows that the PR touched a sensitive path. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "pull_request_target",
        "citation": "| **Mitigations** | • Mandatory review before merge. <br>• `pull_request` workflows run with no secrets and a read-only token, so a malicious test cannot exfiltrate anything from CI. <br>• `pull_request_target` is not used because it would grant secrets to fork code. <br>• `zizmor` lints workflow files for known-dangerous patterns. <br>• Branch protection on `v1.x`. <br>• Package, lockfile, and GitHub Actions update PRs are maintainer/bot-only; outside-collaborator PRs for those updates are closed. <br>• Path-scoped `.github/CODEOWNERS` flags sensitive paths explicitly: runtime source (`/lib/`, `/index.*`), build/release infrastructure (`rollup.config.js`, `package.json`, `package-lock.json`, `.npmrc`), CI automation (`.github/workflows/`, `.github/dependabot.yml`, `CODEOWNERS` itself), and security-critical docs (`THREATMODEL.md`, `SECURITY.md`). Changes to these paths surface the scoped ownership rule in the PR review UI distinct from the catch-all. The audit trail shows that the PR touched a sensitive path. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "zizmor",
        "citation": "| **Mitigations** | • Mandatory review before merge. <br>• `pull_request` workflows run with no secrets and a read-only token, so a malicious test cannot exfiltrate anything from CI. <br>• `pull_request_target` is not used because it would grant secrets to fork code. <br>• `zizmor` lints workflow files for known-dangerous patterns. <br>• Branch protection on `v1.x`. <br>• Package, lockfile, and GitHub Actions update PRs are maintainer/bot-only; outside-collaborator PRs for those updates are closed. <br>• Path-scoped `.github/CODEOWNERS` flags sensitive paths explicitly: runtime source (`/lib/`, `/index.*`), build/release infrastructure (`rollup.config.js`, `package.json`, `package-lock.json`, `.npmrc`), CI automation (`.github/workflows/`, `.github/dependabot.yml`, `CODEOWNERS` itself), and security-critical docs (`THREATMODEL.md`, `SECURITY.md`). Changes to these paths surface the scoped ownership rule in the PR review UI distinct from the catch-all. The audit trail shows that the PR touched a sensitive path. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "v1.x",
        "citation": "| **Mitigations** | • Mandatory review before merge. <br>• `pull_request` workflows run with no secrets and a read-only token, so a malicious test cannot exfiltrate anything from CI. <br>• `pull_request_target` is not used because it would grant secrets to fork code. <br>• `zizmor` lints workflow files for known-dangerous patterns. <br>• Branch protection on `v1.x`. <br>• Package, lockfile, and GitHub Actions update PRs are maintainer/bot-only; outside-collaborator PRs for those updates are closed. <br>• Path-scoped `.github/CODEOWNERS` flags sensitive paths explicitly: runtime source (`/lib/`, `/index.*`), build/release infrastructure (`rollup.config.js`, `package.json`, `package-lock.json`, `.npmrc`), CI automation (`.github/workflows/`, `.github/dependabot.yml`, `CODEOWNERS` itself), and security-critical docs (`THREATMODEL.md`, `SECURITY.md`). Changes to these paths surface the scoped ownership rule in the PR review UI distinct from the catch-all. The audit trail shows that the PR touched a sensitive path. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "rollup.config.js",
        "citation": "| **Mitigations** | • Mandatory review before merge. <br>• `pull_request` workflows run with no secrets and a read-only token, so a malicious test cannot exfiltrate anything from CI. <br>• `pull_request_target` is not used because it would grant secrets to fork code. <br>• `zizmor` lints workflow files for known-dangerous patterns. <br>• Branch protection on `v1.x`. <br>• Package, lockfile, and GitHub Actions update PRs are maintainer/bot-only; outside-collaborator PRs for those updates are closed. <br>• Path-scoped `.github/CODEOWNERS` flags sensitive paths explicitly: runtime source (`/lib/`, `/index.*`), build/release infrastructure (`rollup.config.js`, `package.json`, `package-lock.json`, `.npmrc`), CI automation (`.github/workflows/`, `.github/dependabot.yml`, `CODEOWNERS` itself), and security-critical docs (`THREATMODEL.md`, `SECURITY.md`). Changes to these paths surface the scoped ownership rule in the PR review UI distinct from the catch-all. The audit trail shows that the PR touched a sensitive path. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "package.json",
        "citation": "| **Mitigations** | • Mandatory review before merge. <br>• `pull_request` workflows run with no secrets and a read-only token, so a malicious test cannot exfiltrate anything from CI. <br>• `pull_request_target` is not used because it would grant secrets to fork code. <br>• `zizmor` lints workflow files for known-dangerous patterns. <br>• Branch protection on `v1.x`. <br>• Package, lockfile, and GitHub Actions update PRs are maintainer/bot-only; outside-collaborator PRs for those updates are closed. <br>• Path-scoped `.github/CODEOWNERS` flags sensitive paths explicitly: runtime source (`/lib/`, `/index.*`), build/release infrastructure (`rollup.config.js`, `package.json`, `package-lock.json`, `.npmrc`), CI automation (`.github/workflows/`, `.github/dependabot.yml`, `CODEOWNERS` itself), and security-critical docs (`THREATMODEL.md`, `SECURITY.md`). Changes to these paths surface the scoped ownership rule in the PR review UI distinct from the catch-all. The audit trail shows that the PR touched a sensitive path. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "package-lock.json",
        "citation": "| **Mitigations** | • Mandatory review before merge. <br>• `pull_request` workflows run with no secrets and a read-only token, so a malicious test cannot exfiltrate anything from CI. <br>• `pull_request_target` is not used because it would grant secrets to fork code. <br>• `zizmor` lints workflow files for known-dangerous patterns. <br>• Branch protection on `v1.x`. <br>• Package, lockfile, and GitHub Actions update PRs are maintainer/bot-only; outside-collaborator PRs for those updates are closed. <br>• Path-scoped `.github/CODEOWNERS` flags sensitive paths explicitly: runtime source (`/lib/`, `/index.*`), build/release infrastructure (`rollup.config.js`, `package.json`, `package-lock.json`, `.npmrc`), CI automation (`.github/workflows/`, `.github/dependabot.yml`, `CODEOWNERS` itself), and security-critical docs (`THREATMODEL.md`, `SECURITY.md`). Changes to these paths surface the scoped ownership rule in the PR review UI distinct from the catch-all. The audit trail shows that the PR touched a sensitive path. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": ".npmrc",
        "citation": "| **Mitigations** | • Mandatory review before merge. <br>• `pull_request` workflows run with no secrets and a read-only token, so a malicious test cannot exfiltrate anything from CI. <br>• `pull_request_target` is not used because it would grant secrets to fork code. <br>• `zizmor` lints workflow files for known-dangerous patterns. <br>• Branch protection on `v1.x`. <br>• Package, lockfile, and GitHub Actions update PRs are maintainer/bot-only; outside-collaborator PRs for those updates are closed. <br>• Path-scoped `.github/CODEOWNERS` flags sensitive paths explicitly: runtime source (`/lib/`, `/index.*`), build/release infrastructure (`rollup.config.js`, `package.json`, `package-lock.json`, `.npmrc`), CI automation (`.github/workflows/`, `.github/dependabot.yml`, `CODEOWNERS` itself), and security-critical docs (`THREATMODEL.md`, `SECURITY.md`). Changes to these paths surface the scoped ownership rule in the PR review UI distinct from the catch-all. The audit trail shows that the PR touched a sensitive path. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "CODEOWNERS",
        "citation": "| **Mitigations** | • Mandatory review before merge. <br>• `pull_request` workflows run with no secrets and a read-only token, so a malicious test cannot exfiltrate anything from CI. <br>• `pull_request_target` is not used because it would grant secrets to fork code. <br>• `zizmor` lints workflow files for known-dangerous patterns. <br>• Branch protection on `v1.x`. <br>• Package, lockfile, and GitHub Actions update PRs are maintainer/bot-only; outside-collaborator PRs for those updates are closed. <br>• Path-scoped `.github/CODEOWNERS` flags sensitive paths explicitly: runtime source (`/lib/`, `/index.*`), build/release infrastructure (`rollup.config.js`, `package.json`, `package-lock.json`, `.npmrc`), CI automation (`.github/workflows/`, `.github/dependabot.yml`, `CODEOWNERS` itself), and security-critical docs (`THREATMODEL.md`, `SECURITY.md`). Changes to these paths surface the scoped ownership rule in the PR review UI distinct from the catch-all. The audit trail shows that the PR touched a sensitive path. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "THREATMODEL.md",
        "citation": "| **Mitigations** | • Mandatory review before merge. <br>• `pull_request` workflows run with no secrets and a read-only token, so a malicious test cannot exfiltrate anything from CI. <br>• `pull_request_target` is not used because it would grant secrets to fork code. <br>• `zizmor` lints workflow files for known-dangerous patterns. <br>• Branch protection on `v1.x`. <br>• Package, lockfile, and GitHub Actions update PRs are maintainer/bot-only; outside-collaborator PRs for those updates are closed. <br>• Path-scoped `.github/CODEOWNERS` flags sensitive paths explicitly: runtime source (`/lib/`, `/index.*`), build/release infrastructure (`rollup.config.js`, `package.json`, `package-lock.json`, `.npmrc`), CI automation (`.github/workflows/`, `.github/dependabot.yml`, `CODEOWNERS` itself), and security-critical docs (`THREATMODEL.md`, `SECURITY.md`). Changes to these paths surface the scoped ownership rule in the PR review UI distinct from the catch-all. The audit trail shows that the PR touched a sensitive path. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "SECURITY.md",
        "citation": "| **Mitigations** | • Mandatory review before merge. <br>• `pull_request` workflows run with no secrets and a read-only token, so a malicious test cannot exfiltrate anything from CI. <br>• `pull_request_target` is not used because it would grant secrets to fork code. <br>• `zizmor` lints workflow files for known-dangerous patterns. <br>• Branch protection on `v1.x`. <br>• Package, lockfile, and GitHub Actions update PRs are maintainer/bot-only; outside-collaborator PRs for those updates are closed. <br>• Path-scoped `.github/CODEOWNERS` flags sensitive paths explicitly: runtime source (`/lib/`, `/index.*`), build/release infrastructure (`rollup.config.js`, `package.json`, `package-lock.json`, `.npmrc`), CI automation (`.github/workflows/`, `.github/dependabot.yml`, `CODEOWNERS` itself), and security-critical docs (`THREATMODEL.md`, `SECURITY.md`). Changes to these paths surface the scoped ownership rule in the PR review UI distinct from the catch-all. The audit trail shows that the PR touched a sensitive path. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "@jasonsaayman",
        "citation": "| **Gaps** | • Review is human and fallible. Obfuscated changes to `dist/` (if checked in) or to large test fixtures are hard to spot. <br>• No automated diffing of `lib/` to `dist/` to catch build-output tampering. <br>Single-maintainer constraint: with `@jasonsaayman` as sole owner on every scoped path, CODEOWNERS cannot enforce a second reviewer. Two-person review on sensitive paths remains unavailable until a co-maintainer is added. Path-scoping is pre-staged for that event. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": ".npmrc",
        "citation": "> Historically the weakest link. The project-level `.npmrc` and hardware-backed maintainer keys materially improve it, but build-tool plugin execution (Rollup/Babel/Vitest/ESLint) is still the top residual investment area. `ignore-scripts` does not affect those tools, and they run whenever a maintainer builds or tests.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "ignore-scripts",
        "citation": "> Historically the weakest link. The project-level `.npmrc` and hardware-backed maintainer keys materially improve it, but build-tool plugin execution (Rollup/Babel/Vitest/ESLint) is still the top residual investment area. `ignore-scripts` does not affect those tools, and they run whenever a maintainer builds or tests.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "postinstall",
        "citation": "| **Description** | One of the ~45 direct dev dependencies, or one of their thousands of transitive dependencies, is compromised (maintainer account takeover, expired domain re-registration, the usual). It ships a `postinstall` script that reads `~/.npmrc`, `~/.ssh/id_*`, `~/.config/gh/hosts.yml`, `~/.aws/credentials`, `~/.gnupg/` and POSTs them to an attacker. <br><br>The next time a maintainer runs `npm install` on their workstation, the script runs as the maintainer's user, with full filesystem access. No exploit needed. This is npm working as designed. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm install",
        "citation": "| **Description** | One of the ~45 direct dev dependencies, or one of their thousands of transitive dependencies, is compromised (maintainer account takeover, expired domain re-registration, the usual). It ships a `postinstall` script that reads `~/.npmrc`, `~/.ssh/id_*`, `~/.config/gh/hosts.yml`, `~/.aws/credentials`, `~/.gnupg/` and POSTs them to an attacker. <br><br>The next time a maintainer runs `npm install` on their workstation, the script runs as the maintainer's user, with full filesystem access. No exploit needed. This is npm working as designed. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "event-stream",
        "citation": "| **Likelihood** | Medium and rising. This exact pattern has hit `event-stream`, `ua-parser-js`, `coa`, `rc`, `node-ipc`, `@solana/web3.js`, the Ledger connect-kit, the 2024 polyfill.io incident, and dozens more. axios' dev tree includes Babel, Rollup, Gulp, ESLint, Vitest, and Playwright, each pulling hundreds of transitives. The attack surface is enormous and refreshes on every `npm install`. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "ua-parser-js",
        "citation": "| **Likelihood** | Medium and rising. This exact pattern has hit `event-stream`, `ua-parser-js`, `coa`, `rc`, `node-ipc`, `@solana/web3.js`, the Ledger connect-kit, the 2024 polyfill.io incident, and dozens more. axios' dev tree includes Babel, Rollup, Gulp, ESLint, Vitest, and Playwright, each pulling hundreds of transitives. The attack surface is enormous and refreshes on every `npm install`. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "coa",
        "citation": "| **Likelihood** | Medium and rising. This exact pattern has hit `event-stream`, `ua-parser-js`, `coa`, `rc`, `node-ipc`, `@solana/web3.js`, the Ledger connect-kit, the 2024 polyfill.io incident, and dozens more. axios' dev tree includes Babel, Rollup, Gulp, ESLint, Vitest, and Playwright, each pulling hundreds of transitives. The attack surface is enormous and refreshes on every `npm install`. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "rc",
        "citation": "| **Likelihood** | Medium and rising. This exact pattern has hit `event-stream`, `ua-parser-js`, `coa`, `rc`, `node-ipc`, `@solana/web3.js`, the Ledger connect-kit, the 2024 polyfill.io incident, and dozens more. axios' dev tree includes Babel, Rollup, Gulp, ESLint, Vitest, and Playwright, each pulling hundreds of transitives. The attack surface is enormous and refreshes on every `npm install`. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "node-ipc",
        "citation": "| **Likelihood** | Medium and rising. This exact pattern has hit `event-stream`, `ua-parser-js`, `coa`, `rc`, `node-ipc`, `@solana/web3.js`, the Ledger connect-kit, the 2024 polyfill.io incident, and dozens more. axios' dev tree includes Babel, Rollup, Gulp, ESLint, Vitest, and Playwright, each pulling hundreds of transitives. The attack surface is enormous and refreshes on every `npm install`. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm install",
        "citation": "| **Likelihood** | Medium and rising. This exact pattern has hit `event-stream`, `ua-parser-js`, `coa`, `rc`, `node-ipc`, `@solana/web3.js`, the Ledger connect-kit, the 2024 polyfill.io incident, and dozens more. axios' dev tree includes Babel, Rollup, Gulp, ESLint, Vitest, and Playwright, each pulling hundreds of transitives. The attack surface is enormous and refreshes on every `npm install`. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "publish.yml",
        "citation": "| **Current mitigations** | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build. <br>• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal. <br>• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update. <br>• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency. <br>• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README \"Contributing / Local setup\" section. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm ci --ignore-scripts",
        "citation": "| **Current mitigations** | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build. <br>• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal. <br>• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update. <br>• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency. <br>• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README \"Contributing / Local setup\" section. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "NPM_TOKEN",
        "citation": "| **Current mitigations** | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build. <br>• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal. <br>• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update. <br>• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency. <br>• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README \"Contributing / Local setup\" section. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "package-lock.json",
        "citation": "| **Current mitigations** | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build. <br>• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal. <br>• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update. <br>• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency. <br>• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README \"Contributing / Local setup\" section. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": ".npmrc",
        "citation": "| **Current mitigations** | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build. <br>• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal. <br>• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update. <br>• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency. <br>• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README \"Contributing / Local setup\" section. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm install",
        "citation": "| **Current mitigations** | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build. <br>• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal. <br>• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update. <br>• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency. <br>• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README \"Contributing / Local setup\" section. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm ci",
        "citation": "| **Current mitigations** | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build. <br>• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal. <br>• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update. <br>• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency. <br>• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README \"Contributing / Local setup\" section. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "preinstall",
        "citation": "| **Current mitigations** | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build. <br>• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal. <br>• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update. <br>• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency. <br>• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README \"Contributing / Local setup\" section. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "install",
        "citation": "| **Current mitigations** | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build. <br>• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal. <br>• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update. <br>• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency. <br>• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README \"Contributing / Local setup\" section. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "postinstall",
        "citation": "| **Current mitigations** | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build. <br>• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal. <br>• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update. <br>• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency. <br>• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README \"Contributing / Local setup\" section. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "prepare",
        "citation": "| **Current mitigations** | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build. <br>• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal. <br>• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update. <br>• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency. <br>• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README \"Contributing / Local setup\" section. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "husky",
        "citation": "| **Current mitigations** | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build. <br>• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal. <br>• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update. <br>• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency. <br>• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README \"Contributing / Local setup\" section. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "prepare",
        "citation": "| **Current mitigations** | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build. <br>• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal. <br>• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update. <br>• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency. <br>• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README \"Contributing / Local setup\" section. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm rebuild husky && npx husky",
        "citation": "| **Current mitigations** | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build. <br>• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal. <br>• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update. <br>• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency. <br>• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README \"Contributing / Local setup\" section. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm run build",
        "citation": "| **Gaps: workstation** | `ignore-scripts=true` neutralizes the lifecycle-script path, but it does not neutralize build-time code execution. A malicious Rollup / Babel / Terser / ESLint / Vitest plugin still runs when a maintainer executes `npm run build` / `npm test` / `npm run lint`. Those are not lifecycle scripts; they are tools the maintainer explicitly invoked. <br><br>The lockfile pins which packages install, but if one of those pinned packages was already malicious when the lock was generated, or the maintainer runs `npm update` / `npm install <new-pkg>` without re-setting `ignore-scripts`, fresh lifecycle scripts can land. <br><br>The development environment still has full read access to every credential the maintainer's user can read once a build tool runs. Isolation (devcontainer / VM) remains the strongest control. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm test",
        "citation": "| **Gaps: workstation** | `ignore-scripts=true` neutralizes the lifecycle-script path, but it does not neutralize build-time code execution. A malicious Rollup / Babel / Terser / ESLint / Vitest plugin still runs when a maintainer executes `npm run build` / `npm test` / `npm run lint`. Those are not lifecycle scripts; they are tools the maintainer explicitly invoked. <br><br>The lockfile pins which packages install, but if one of those pinned packages was already malicious when the lock was generated, or the maintainer runs `npm update` / `npm install <new-pkg>` without re-setting `ignore-scripts`, fresh lifecycle scripts can land. <br><br>The development environment still has full read access to every credential the maintainer's user can read once a build tool runs. Isolation (devcontainer / VM) remains the strongest control. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm run lint",
        "citation": "| **Gaps: workstation** | `ignore-scripts=true` neutralizes the lifecycle-script path, but it does not neutralize build-time code execution. A malicious Rollup / Babel / Terser / ESLint / Vitest plugin still runs when a maintainer executes `npm run build` / `npm test` / `npm run lint`. Those are not lifecycle scripts; they are tools the maintainer explicitly invoked. <br><br>The lockfile pins which packages install, but if one of those pinned packages was already malicious when the lock was generated, or the maintainer runs `npm update` / `npm install <new-pkg>` without re-setting `ignore-scripts`, fresh lifecycle scripts can land. <br><br>The development environment still has full read access to every credential the maintainer's user can read once a build tool runs. Isolation (devcontainer / VM) remains the strongest control. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm update",
        "citation": "| **Gaps: workstation** | `ignore-scripts=true` neutralizes the lifecycle-script path, but it does not neutralize build-time code execution. A malicious Rollup / Babel / Terser / ESLint / Vitest plugin still runs when a maintainer executes `npm run build` / `npm test` / `npm run lint`. Those are not lifecycle scripts; they are tools the maintainer explicitly invoked. <br><br>The lockfile pins which packages install, but if one of those pinned packages was already malicious when the lock was generated, or the maintainer runs `npm update` / `npm install <new-pkg>` without re-setting `ignore-scripts`, fresh lifecycle scripts can land. <br><br>The development environment still has full read access to every credential the maintainer's user can read once a build tool runs. Isolation (devcontainer / VM) remains the strongest control. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm install <new-pkg>",
        "citation": "| **Gaps: workstation** | `ignore-scripts=true` neutralizes the lifecycle-script path, but it does not neutralize build-time code execution. A malicious Rollup / Babel / Terser / ESLint / Vitest plugin still runs when a maintainer executes `npm run build` / `npm test` / `npm run lint`. Those are not lifecycle scripts; they are tools the maintainer explicitly invoked. <br><br>The lockfile pins which packages install, but if one of those pinned packages was already malicious when the lock was generated, or the maintainer runs `npm update` / `npm install <new-pkg>` without re-setting `ignore-scripts`, fresh lifecycle scripts can land. <br><br>The development environment still has full read access to every credential the maintainer's user can read once a build tool runs. Isolation (devcontainer / VM) remains the strongest control. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "ignore-scripts",
        "citation": "| **Gaps: workstation** | `ignore-scripts=true` neutralizes the lifecycle-script path, but it does not neutralize build-time code execution. A malicious Rollup / Babel / Terser / ESLint / Vitest plugin still runs when a maintainer executes `npm run build` / `npm test` / `npm run lint`. Those are not lifecycle scripts; they are tools the maintainer explicitly invoked. <br><br>The lockfile pins which packages install, but if one of those pinned packages was already malicious when the lock was generated, or the maintainer runs `npm update` / `npm install <new-pkg>` without re-setting `ignore-scripts`, fresh lifecycle scripts can land. <br><br>The development environment still has full read access to every credential the maintainer's user can read once a build tool runs. Isolation (devcontainer / VM) remains the strongest control. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm publish",
        "citation": "Publishing happens via GitHub Actions OIDC. There is no workflow that requires `npm publish` from a laptop. If `~/.npmrc` has a token, it should be read-only or scoped to unrelated packages. If there is nothing to steal, this attack path is defanged.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm install",
        "citation": "2. Run `npm install` / `npm ci` with `--ignore-scripts` locally. Adopted: project ships a `.npmrc` with `ignore-scripts=true`.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm ci",
        "citation": "2. Run `npm install` / `npm ci` with `--ignore-scripts` locally. Adopted: project ships a `.npmrc` with `ignore-scripts=true`.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "--ignore-scripts",
        "citation": "2. Run `npm install` / `npm ci` with `--ignore-scripts` locally. Adopted: project ships a `.npmrc` with `ignore-scripts=true`.",
        "file": "THREATMODEL.md"
      },
      {
        "command": ".npmrc",
        "citation": "2. Run `npm install` / `npm ci` with `--ignore-scripts` locally. Adopted: project ships a `.npmrc` with `ignore-scripts=true`.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm install",
        "citation": "All `npm install` / `npm ci` runs in a contributor or maintainer checkout skip lifecycle scripts by default. To set up git hooks after install, run the one trusted script manually:",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm ci",
        "citation": "All `npm install` / `npm ci` runs in a contributor or maintainer checkout skip lifecycle scripts by default. To set up git hooks after install, run the one trusted script manually:",
        "file": "THREATMODEL.md"
      },
      {
        "command": "repo",
        "citation": "- `~/.config/gh/` with a `repo`-scoped GitHub token",
        "file": "THREATMODEL.md"
      },
      {
        "command": "sk-ssh-ed25519@openssh.com",
        "citation": "All maintainers use FIDO2/WebAuthn for GitHub auth and `sk-ssh-ed25519@openssh.com` for git push. A stolen `~/.ssh/id_ed25519_sk` is useless without the physical key. This converts \"steal a file\" into \"steal a file and a physical object.\" Each maintainer should keep a backup key registered and stored separately.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "package-lock.json",
        "citation": "A 4000-line `package-lock.json` diff hides a lot. Tooling: `npm diff`, `lockfile-lint`, Socket.dev's PR integration. Pay particular attention to new packages with install scripts (`hasInstallScript: true` in the lockfile).",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm diff",
        "citation": "A 4000-line `package-lock.json` diff hides a lot. Tooling: `npm diff`, `lockfile-lint`, Socket.dev's PR integration. Pay particular attention to new packages with install scripts (`hasInstallScript: true` in the lockfile).",
        "file": "THREATMODEL.md"
      },
      {
        "command": "lockfile-lint",
        "citation": "A 4000-line `package-lock.json` diff hides a lot. Tooling: `npm diff`, `lockfile-lint`, Socket.dev's PR integration. Pay particular attention to new packages with install scripts (`hasInstallScript: true` in the lockfile).",
        "file": "THREATMODEL.md"
      },
      {
        "command": "hasInstallScript: true",
        "citation": "A 4000-line `package-lock.json` diff hides a lot. Tooling: `npm diff`, `lockfile-lint`, Socket.dev's PR integration. Pay particular attention to new packages with install scripts (`hasInstallScript: true` in the lockfile).",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npx",
        "citation": "Each one is a recurring trust decision delegated to a stranger. Prefer tools that can run via `npx` on demand (not in `node_modules`) or that are already in the tree.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "node_modules",
        "citation": "Each one is a recurring trust decision delegated to a stranger. Prefer tools that can run via `npx` on demand (not in `node_modules`) or that are already in the tree.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "repo",
        "citation": "| **Description** | Maintainer receives a convincing email: <br>• \"npm security alert: your axios package has been flagged, log in to verify ownership\" links to a fake npm login; password + TOTP are captured and replayed in real time. <br>• \"GitHub: @axios has been added to a new organization, review access\" links to a fake GitHub OAuth consent screen; the attacker app gets `repo` scope. <br>• Social: a \"recruiter\" asks the maintainer to clone and `npm install` a \"take-home assignment\" repo. <br><br>npm and GitHub credentials for axios maintainers have been specifically targeted by these campaigns in the past. This is not theoretical. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm install",
        "citation": "| **Description** | Maintainer receives a convincing email: <br>• \"npm security alert: your axios package has been flagged, log in to verify ownership\" links to a fake npm login; password + TOTP are captured and replayed in real time. <br>• \"GitHub: @axios has been added to a new organization, review access\" links to a fake GitHub OAuth consent screen; the attacker app gets `repo` scope. <br>• Social: a \"recruiter\" asks the maintainer to clone and `npm install` a \"take-home assignment\" repo. <br><br>npm and GitHub credentials for axios maintainers have been specifically targeted by these campaigns in the past. This is not theoretical. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "axios",
        "citation": "| **Mitigations** | • npm 2FA is required for publish on the `axios` package. <br>• OIDC publishing means there is no maintainer npm session involved in a normal release. This narrows the attack to GitHub. <br>• All maintainers authenticate to GitHub with hardware-backed WebAuthn/passkeys (FIDO2 security keys / platform authenticators). Origin-bound credentials cannot be relayed by a phishing proxy (Evilginx, Modlishka). TOTP alone is not permitted for maintainer accounts. <br>• Git push uses `sk-ssh-ed25519@openssh.com` hardware-resident SSH keys where supported. A stolen key file is useless without the physical device. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "sk-ssh-ed25519@openssh.com",
        "citation": "| **Mitigations** | • npm 2FA is required for publish on the `axios` package. <br>• OIDC publishing means there is no maintainer npm session involved in a normal release. This narrows the attack to GitHub. <br>• All maintainers authenticate to GitHub with hardware-backed WebAuthn/passkeys (FIDO2 security keys / platform authenticators). Origin-bound credentials cannot be relayed by a phishing proxy (Evilginx, Modlishka). TOTP alone is not permitted for maintainer accounts. <br>• Git push uses `sk-ssh-ed25519@openssh.com` hardware-resident SSH keys where supported. A stolen key file is useless without the physical device. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "follow-redirects",
        "citation": "| **Description** | `follow-redirects`, `form-data`, `proxy-from-env`, or `https-proxy-agent` ships a malicious version. Unlike T-S2, this code ends up in the published axios bundle / runtime rather than being limited to maintainer machines. Every axios consumer runs it. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "form-data",
        "citation": "| **Description** | `follow-redirects`, `form-data`, `proxy-from-env`, or `https-proxy-agent` ships a malicious version. Unlike T-S2, this code ends up in the published axios bundle / runtime rather than being limited to maintainer machines. Every axios consumer runs it. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "proxy-from-env",
        "citation": "| **Description** | `follow-redirects`, `form-data`, `proxy-from-env`, or `https-proxy-agent` ships a malicious version. Unlike T-S2, this code ends up in the published axios bundle / runtime rather than being limited to maintainer machines. Every axios consumer runs it. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "https-proxy-agent",
        "citation": "| **Description** | `follow-redirects`, `form-data`, `proxy-from-env`, or `https-proxy-agent` ships a malicious version. Unlike T-S2, this code ends up in the published axios bundle / runtime rather than being limited to maintainer machines. Every axios consumer runs it. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "package.json",
        "citation": "| **Mitigations** | • Three runtime deps total, minimal by design. <br>• `^` ranges in `package.json` mean consumers may get newer patch versions than the lockfile pins. This is intentional, because consumers get security fixes, but it also means a malicious patch release of `follow-redirects` propagates without an axios release. <br>• `follow-redirects` is security-conscious and well-maintained; we track its advisories closely (multiple past axios releases were just `follow-redirects` bumps). <br>• Dependabot is configured (`.github/dependabot.yml`) for both npm and GitHub Actions, running weekly with grouped updates for production and development dependencies. The 7-day cooldown stays in place unless a critical vulnerability requires a maintainer-led manual update. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "follow-redirects",
        "citation": "| **Mitigations** | • Three runtime deps total, minimal by design. <br>• `^` ranges in `package.json` mean consumers may get newer patch versions than the lockfile pins. This is intentional, because consumers get security fixes, but it also means a malicious patch release of `follow-redirects` propagates without an axios release. <br>• `follow-redirects` is security-conscious and well-maintained; we track its advisories closely (multiple past axios releases were just `follow-redirects` bumps). <br>• Dependabot is configured (`.github/dependabot.yml`) for both npm and GitHub Actions, running weekly with grouped updates for production and development dependencies. The 7-day cooldown stays in place unless a critical vulnerability requires a maintainer-led manual update. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "follow-redirects",
        "citation": "| **Mitigations** | • Three runtime deps total, minimal by design. <br>• `^` ranges in `package.json` mean consumers may get newer patch versions than the lockfile pins. This is intentional, because consumers get security fixes, but it also means a malicious patch release of `follow-redirects` propagates without an axios release. <br>• `follow-redirects` is security-conscious and well-maintained; we track its advisories closely (multiple past axios releases were just `follow-redirects` bumps). <br>• Dependabot is configured (`.github/dependabot.yml`) for both npm and GitHub Actions, running weekly with grouped updates for production and development dependencies. The 7-day cooldown stays in place unless a critical vulnerability requires a maintainer-led manual update. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "follow-redirects",
        "citation": "| **Mitigations** | • Three runtime deps total, minimal by design. <br>• `^` ranges in `package.json` mean consumers may get newer patch versions than the lockfile pins. This is intentional, because consumers get security fixes, but it also means a malicious patch release of `follow-redirects` propagates without an axios release. <br>• `follow-redirects` is security-conscious and well-maintained; we track its advisories closely (multiple past axios releases were just `follow-redirects` bumps). <br>• Dependabot is configured (`.github/dependabot.yml`) for both npm and GitHub Actions, running weekly with grouped updates for production and development dependencies. The 7-day cooldown stays in place unless a critical vulnerability requires a maintainer-led manual update. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "rollup",
        "citation": "| **Description** | The published tarball contains a `dist/axios.min.js` that does not match what `rollup` would produce from `lib/`. Nobody reads minified bundles. A backdoor here is invisible to source review. <br><br>Vectors: a malicious dev-dep Rollup/Babel/Terser plugin injects code at build time (T-S2 applied to CI), or a maintainer with a compromised workstation accidentally publishes a tampered local build. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "publish.yml",
        "citation": "| **Mitigations** | • Builds run only in CI as part of `publish.yml`, from a clean `npm ci --ignore-scripts` checkout. There is no \"publish from laptop\" path. <br>• `--ignore-scripts` means a malicious dev dependency cannot tamper with `node_modules` before the build, but it can still tamper during the build if it is a Rollup/Babel plugin. Those run as part of `npm run build`, not as lifecycle scripts. <br>• npm provenance (`--provenance`) cryptographically attests which workflow on which commit produced the tarball. Consumers can verify with `npm audit signatures`. This proves the build ran in GitHub Actions on a known SHA. It does not prove the build is correct, only that it is traceable. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm ci --ignore-scripts",
        "citation": "| **Mitigations** | • Builds run only in CI as part of `publish.yml`, from a clean `npm ci --ignore-scripts` checkout. There is no \"publish from laptop\" path. <br>• `--ignore-scripts` means a malicious dev dependency cannot tamper with `node_modules` before the build, but it can still tamper during the build if it is a Rollup/Babel plugin. Those run as part of `npm run build`, not as lifecycle scripts. <br>• npm provenance (`--provenance`) cryptographically attests which workflow on which commit produced the tarball. Consumers can verify with `npm audit signatures`. This proves the build ran in GitHub Actions on a known SHA. It does not prove the build is correct, only that it is traceable. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "--ignore-scripts",
        "citation": "| **Mitigations** | • Builds run only in CI as part of `publish.yml`, from a clean `npm ci --ignore-scripts` checkout. There is no \"publish from laptop\" path. <br>• `--ignore-scripts` means a malicious dev dependency cannot tamper with `node_modules` before the build, but it can still tamper during the build if it is a Rollup/Babel plugin. Those run as part of `npm run build`, not as lifecycle scripts. <br>• npm provenance (`--provenance`) cryptographically attests which workflow on which commit produced the tarball. Consumers can verify with `npm audit signatures`. This proves the build ran in GitHub Actions on a known SHA. It does not prove the build is correct, only that it is traceable. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "node_modules",
        "citation": "| **Mitigations** | • Builds run only in CI as part of `publish.yml`, from a clean `npm ci --ignore-scripts` checkout. There is no \"publish from laptop\" path. <br>• `--ignore-scripts` means a malicious dev dependency cannot tamper with `node_modules` before the build, but it can still tamper during the build if it is a Rollup/Babel plugin. Those run as part of `npm run build`, not as lifecycle scripts. <br>• npm provenance (`--provenance`) cryptographically attests which workflow on which commit produced the tarball. Consumers can verify with `npm audit signatures`. This proves the build ran in GitHub Actions on a known SHA. It does not prove the build is correct, only that it is traceable. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm run build",
        "citation": "| **Mitigations** | • Builds run only in CI as part of `publish.yml`, from a clean `npm ci --ignore-scripts` checkout. There is no \"publish from laptop\" path. <br>• `--ignore-scripts` means a malicious dev dependency cannot tamper with `node_modules` before the build, but it can still tamper during the build if it is a Rollup/Babel plugin. Those run as part of `npm run build`, not as lifecycle scripts. <br>• npm provenance (`--provenance`) cryptographically attests which workflow on which commit produced the tarball. Consumers can verify with `npm audit signatures`. This proves the build ran in GitHub Actions on a known SHA. It does not prove the build is correct, only that it is traceable. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "--provenance",
        "citation": "| **Mitigations** | • Builds run only in CI as part of `publish.yml`, from a clean `npm ci --ignore-scripts` checkout. There is no \"publish from laptop\" path. <br>• `--ignore-scripts` means a malicious dev dependency cannot tamper with `node_modules` before the build, but it can still tamper during the build if it is a Rollup/Babel plugin. Those run as part of `npm run build`, not as lifecycle scripts. <br>• npm provenance (`--provenance`) cryptographically attests which workflow on which commit produced the tarball. Consumers can verify with `npm audit signatures`. This proves the build ran in GitHub Actions on a known SHA. It does not prove the build is correct, only that it is traceable. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm audit signatures",
        "citation": "| **Mitigations** | • Builds run only in CI as part of `publish.yml`, from a clean `npm ci --ignore-scripts` checkout. There is no \"publish from laptop\" path. <br>• `--ignore-scripts` means a malicious dev dependency cannot tamper with `node_modules` before the build, but it can still tamper during the build if it is a Rollup/Babel plugin. Those run as part of `npm run build`, not as lifecycle scripts. <br>• npm provenance (`--provenance`) cryptographically attests which workflow on which commit produced the tarball. Consumers can verify with `npm audit signatures`. This proves the build ran in GitHub Actions on a known SHA. It does not prove the build is correct, only that it is traceable. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "rollup.config.js",
        "citation": "| **Gaps** | • The build is not currently reproducible in the strict sense. A third party cannot independently rebuild and get a byte-identical `dist/`. Timestamps, plugin ordering, and minifier nondeterminism would need to be locked down. <br>• `.github/workflows/verify-build-reproducibility.yml` performs a two-pass build-and-diff on PRs that touch build-related paths (`lib/**`, `rollup.config.js`, `package.json`, `package-lock.json`, and the workflow itself). It is currently non-blocking (`continue-on-error: true`). It surfaces divergence in the CI summary so reproducibility regressions are visible, without gating merges until the build is deterministic. Once divergence is eliminated, remove `continue-on-error` to promote this to a hard gate. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "package.json",
        "citation": "| **Gaps** | • The build is not currently reproducible in the strict sense. A third party cannot independently rebuild and get a byte-identical `dist/`. Timestamps, plugin ordering, and minifier nondeterminism would need to be locked down. <br>• `.github/workflows/verify-build-reproducibility.yml` performs a two-pass build-and-diff on PRs that touch build-related paths (`lib/**`, `rollup.config.js`, `package.json`, `package-lock.json`, and the workflow itself). It is currently non-blocking (`continue-on-error: true`). It surfaces divergence in the CI summary so reproducibility regressions are visible, without gating merges until the build is deterministic. Once divergence is eliminated, remove `continue-on-error` to promote this to a hard gate. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "package-lock.json",
        "citation": "| **Gaps** | • The build is not currently reproducible in the strict sense. A third party cannot independently rebuild and get a byte-identical `dist/`. Timestamps, plugin ordering, and minifier nondeterminism would need to be locked down. <br>• `.github/workflows/verify-build-reproducibility.yml` performs a two-pass build-and-diff on PRs that touch build-related paths (`lib/**`, `rollup.config.js`, `package.json`, `package-lock.json`, and the workflow itself). It is currently non-blocking (`continue-on-error: true`). It surfaces divergence in the CI summary so reproducibility regressions are visible, without gating merges until the build is deterministic. Once divergence is eliminated, remove `continue-on-error` to promote this to a hard gate. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "continue-on-error: true",
        "citation": "| **Gaps** | • The build is not currently reproducible in the strict sense. A third party cannot independently rebuild and get a byte-identical `dist/`. Timestamps, plugin ordering, and minifier nondeterminism would need to be locked down. <br>• `.github/workflows/verify-build-reproducibility.yml` performs a two-pass build-and-diff on PRs that touch build-related paths (`lib/**`, `rollup.config.js`, `package.json`, `package-lock.json`, and the workflow itself). It is currently non-blocking (`continue-on-error: true`). It surfaces divergence in the CI summary so reproducibility regressions are visible, without gating merges until the build is deterministic. Once divergence is eliminated, remove `continue-on-error` to promote this to a hard gate. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "continue-on-error",
        "citation": "| **Gaps** | • The build is not currently reproducible in the strict sense. A third party cannot independently rebuild and get a byte-identical `dist/`. Timestamps, plugin ordering, and minifier nondeterminism would need to be locked down. <br>• `.github/workflows/verify-build-reproducibility.yml` performs a two-pass build-and-diff on PRs that touch build-related paths (`lib/**`, `rollup.config.js`, `package.json`, `package-lock.json`, and the workflow itself). It is currently non-blocking (`continue-on-error: true`). It surfaces divergence in the CI summary so reproducibility regressions are visible, without gating merges until the build is deterministic. Once divergence is eliminated, remove `continue-on-error` to promote this to a hard gate. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "curl",
        "citation": "| **Description** | Attacker with write access (or a merged PR that was not reviewed carefully) modifies `.github/workflows/publish.yml` to `curl` the OIDC token somewhere, or to add a step that patches `dist/` after the build. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "@v6",
        "citation": "| **Mitigations** | • All actions are pinned to full commit SHAs, not tags: `actions/checkout@de0fac...`, not `@v6`. A compromised action tag can't silently change behavior. <br>• `permissions:` are minimal (`contents: read`, `id-token: write`). <br>• `persist-credentials: false` on checkout, so the build steps cannot push back to the repo. <br>• `zizmor` lints workflows on every PR and push to `v1.x` (`.github/workflows/zizmor.yml`); results surface as GitHub code-scanning alerts via the `security-events: write` permission on that job. This job must remain in the required-checks set on `v1.x` branch protection for the mitigation to be binding. <br>• The `npm-publish` GitHub Environment can require designated reviewers before the job runs; a tampered workflow still pauses for human approval. <br>• CODEOWNERS carries a path-scoped rule for `/.github/workflows/` and `/.github/CODEOWNERS` itself, so workflow and ownership changes surface in the review UI as touching a scoped path rather than being folded into the default approval. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "contents: read",
        "citation": "| **Mitigations** | • All actions are pinned to full commit SHAs, not tags: `actions/checkout@de0fac...`, not `@v6`. A compromised action tag can't silently change behavior. <br>• `permissions:` are minimal (`contents: read`, `id-token: write`). <br>• `persist-credentials: false` on checkout, so the build steps cannot push back to the repo. <br>• `zizmor` lints workflows on every PR and push to `v1.x` (`.github/workflows/zizmor.yml`); results surface as GitHub code-scanning alerts via the `security-events: write` permission on that job. This job must remain in the required-checks set on `v1.x` branch protection for the mitigation to be binding. <br>• The `npm-publish` GitHub Environment can require designated reviewers before the job runs; a tampered workflow still pauses for human approval. <br>• CODEOWNERS carries a path-scoped rule for `/.github/workflows/` and `/.github/CODEOWNERS` itself, so workflow and ownership changes surface in the review UI as touching a scoped path rather than being folded into the default approval. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "id-token: write",
        "citation": "| **Mitigations** | • All actions are pinned to full commit SHAs, not tags: `actions/checkout@de0fac...`, not `@v6`. A compromised action tag can't silently change behavior. <br>• `permissions:` are minimal (`contents: read`, `id-token: write`). <br>• `persist-credentials: false` on checkout, so the build steps cannot push back to the repo. <br>• `zizmor` lints workflows on every PR and push to `v1.x` (`.github/workflows/zizmor.yml`); results surface as GitHub code-scanning alerts via the `security-events: write` permission on that job. This job must remain in the required-checks set on `v1.x` branch protection for the mitigation to be binding. <br>• The `npm-publish` GitHub Environment can require designated reviewers before the job runs; a tampered workflow still pauses for human approval. <br>• CODEOWNERS carries a path-scoped rule for `/.github/workflows/` and `/.github/CODEOWNERS` itself, so workflow and ownership changes surface in the review UI as touching a scoped path rather than being folded into the default approval. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "persist-credentials: false",
        "citation": "| **Mitigations** | • All actions are pinned to full commit SHAs, not tags: `actions/checkout@de0fac...`, not `@v6`. A compromised action tag can't silently change behavior. <br>• `permissions:` are minimal (`contents: read`, `id-token: write`). <br>• `persist-credentials: false` on checkout, so the build steps cannot push back to the repo. <br>• `zizmor` lints workflows on every PR and push to `v1.x` (`.github/workflows/zizmor.yml`); results surface as GitHub code-scanning alerts via the `security-events: write` permission on that job. This job must remain in the required-checks set on `v1.x` branch protection for the mitigation to be binding. <br>• The `npm-publish` GitHub Environment can require designated reviewers before the job runs; a tampered workflow still pauses for human approval. <br>• CODEOWNERS carries a path-scoped rule for `/.github/workflows/` and `/.github/CODEOWNERS` itself, so workflow and ownership changes surface in the review UI as touching a scoped path rather than being folded into the default approval. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "zizmor",
        "citation": "| **Mitigations** | • All actions are pinned to full commit SHAs, not tags: `actions/checkout@de0fac...`, not `@v6`. A compromised action tag can't silently change behavior. <br>• `permissions:` are minimal (`contents: read`, `id-token: write`). <br>• `persist-credentials: false` on checkout, so the build steps cannot push back to the repo. <br>• `zizmor` lints workflows on every PR and push to `v1.x` (`.github/workflows/zizmor.yml`); results surface as GitHub code-scanning alerts via the `security-events: write` permission on that job. This job must remain in the required-checks set on `v1.x` branch protection for the mitigation to be binding. <br>• The `npm-publish` GitHub Environment can require designated reviewers before the job runs; a tampered workflow still pauses for human approval. <br>• CODEOWNERS carries a path-scoped rule for `/.github/workflows/` and `/.github/CODEOWNERS` itself, so workflow and ownership changes surface in the review UI as touching a scoped path rather than being folded into the default approval. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "v1.x",
        "citation": "| **Mitigations** | • All actions are pinned to full commit SHAs, not tags: `actions/checkout@de0fac...`, not `@v6`. A compromised action tag can't silently change behavior. <br>• `permissions:` are minimal (`contents: read`, `id-token: write`). <br>• `persist-credentials: false` on checkout, so the build steps cannot push back to the repo. <br>• `zizmor` lints workflows on every PR and push to `v1.x` (`.github/workflows/zizmor.yml`); results surface as GitHub code-scanning alerts via the `security-events: write` permission on that job. This job must remain in the required-checks set on `v1.x` branch protection for the mitigation to be binding. <br>• The `npm-publish` GitHub Environment can require designated reviewers before the job runs; a tampered workflow still pauses for human approval. <br>• CODEOWNERS carries a path-scoped rule for `/.github/workflows/` and `/.github/CODEOWNERS` itself, so workflow and ownership changes surface in the review UI as touching a scoped path rather than being folded into the default approval. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "security-events: write",
        "citation": "| **Mitigations** | • All actions are pinned to full commit SHAs, not tags: `actions/checkout@de0fac...`, not `@v6`. A compromised action tag can't silently change behavior. <br>• `permissions:` are minimal (`contents: read`, `id-token: write`). <br>• `persist-credentials: false` on checkout, so the build steps cannot push back to the repo. <br>• `zizmor` lints workflows on every PR and push to `v1.x` (`.github/workflows/zizmor.yml`); results surface as GitHub code-scanning alerts via the `security-events: write` permission on that job. This job must remain in the required-checks set on `v1.x` branch protection for the mitigation to be binding. <br>• The `npm-publish` GitHub Environment can require designated reviewers before the job runs; a tampered workflow still pauses for human approval. <br>• CODEOWNERS carries a path-scoped rule for `/.github/workflows/` and `/.github/CODEOWNERS` itself, so workflow and ownership changes surface in the review UI as touching a scoped path rather than being folded into the default approval. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "v1.x",
        "citation": "| **Mitigations** | • All actions are pinned to full commit SHAs, not tags: `actions/checkout@de0fac...`, not `@v6`. A compromised action tag can't silently change behavior. <br>• `permissions:` are minimal (`contents: read`, `id-token: write`). <br>• `persist-credentials: false` on checkout, so the build steps cannot push back to the repo. <br>• `zizmor` lints workflows on every PR and push to `v1.x` (`.github/workflows/zizmor.yml`); results surface as GitHub code-scanning alerts via the `security-events: write` permission on that job. This job must remain in the required-checks set on `v1.x` branch protection for the mitigation to be binding. <br>• The `npm-publish` GitHub Environment can require designated reviewers before the job runs; a tampered workflow still pauses for human approval. <br>• CODEOWNERS carries a path-scoped rule for `/.github/workflows/` and `/.github/CODEOWNERS` itself, so workflow and ownership changes surface in the review UI as touching a scoped path rather than being folded into the default approval. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm-publish",
        "citation": "| **Mitigations** | • All actions are pinned to full commit SHAs, not tags: `actions/checkout@de0fac...`, not `@v6`. A compromised action tag can't silently change behavior. <br>• `permissions:` are minimal (`contents: read`, `id-token: write`). <br>• `persist-credentials: false` on checkout, so the build steps cannot push back to the repo. <br>• `zizmor` lints workflows on every PR and push to `v1.x` (`.github/workflows/zizmor.yml`); results surface as GitHub code-scanning alerts via the `security-events: write` permission on that job. This job must remain in the required-checks set on `v1.x` branch protection for the mitigation to be binding. <br>• The `npm-publish` GitHub Environment can require designated reviewers before the job runs; a tampered workflow still pauses for human approval. <br>• CODEOWNERS carries a path-scoped rule for `/.github/workflows/` and `/.github/CODEOWNERS` itself, so workflow and ownership changes surface in the review UI as touching a scoped path rather than being folded into the default approval. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "v1.99.99",
        "citation": "| **Description** | Attacker with write access force-pushes an existing tag to point at a malicious commit, or pushes `v1.99.99` so that a release is published out of band. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "1.15.0",
        "citation": "| **Mitigations** | • npm rejects re-publishing an existing version. Re-tagging cannot overwrite the published `1.15.0`. <br>• Provenance attestation records the commit SHA the tag pointed to at publish time, which is forensically verifiable. Consumers can confirm with `npm audit signatures axios` (documented in SECURITY.md). <br>• Tag protection rules: repository setting must forbid tag deletion and force-push for the `v1.*.*` pattern. This is a GitHub UI setting (Settings > Tags > rulesets), not file-based; enforcement is auditable via the Rulesets REST API. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm audit signatures axios",
        "citation": "| **Mitigations** | • npm rejects re-publishing an existing version. Re-tagging cannot overwrite the published `1.15.0`. <br>• Provenance attestation records the commit SHA the tag pointed to at publish time, which is forensically verifiable. Consumers can confirm with `npm audit signatures axios` (documented in SECURITY.md). <br>• Tag protection rules: repository setting must forbid tag deletion and force-push for the `v1.*.*` pattern. This is a GitHub UI setting (Settings > Tags > rulesets), not file-based; enforcement is auditable via the Rulesets REST API. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "v1.x.x",
        "citation": "| **Gaps** | A new malicious version (`v1.x.x`) is still publishable by anyone with tag-push rights. This collapses back into T-S3 (account security). |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "axois",
        "citation": "| **Description** | Attacker publishes `axois`, `axios-http`, `@axios/core`, etc., and waits for typos. Or publishes a package shadowing an internal name used in a consumer's monorepo. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": "axios-http",
        "citation": "| **Description** | Attacker publishes `axois`, `axios-http`, `@axios/core`, etc., and waits for typos. Or publishes a package shadowing an internal name used in a consumer's monorepo. |",
        "file": "THREATMODEL.md"
      },
      {
        "command": ".npmrc",
        "citation": "| T-S2 Dev-dep steals keys | Medium | Critical | Partial | Isolated dev environment (devcontainer/VM); no publish tokens on workstations. Lifecycle scripts now blocked via project `.npmrc`, but build-tool plugins still execute |",
        "file": "THREATMODEL.md"
      },
      {
        "command": ".npmrc",
        "citation": "The top remaining investment is T-S2 (dev-dependency compromise of maintainer workstations). Lifecycle-script execution is now blocked by the project-level `.npmrc`, and T-S3 phishing risk dropped materially once all maintainers moved to hardware-backed WebAuthn. Real-time credential relay no longer works. The residual T-S2 gap is build-tool plugin execution (Rollup/Babel/Vitest/ESLint), which `ignore-scripts` does not cover. Closing it requires running builds in an isolated environment without access to long-lived credentials.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "ignore-scripts",
        "citation": "The top remaining investment is T-S2 (dev-dependency compromise of maintainer workstations). Lifecycle-script execution is now blocked by the project-level `.npmrc`, and T-S3 phishing risk dropped materially once all maintainers moved to hardware-backed WebAuthn. Real-time credential relay no longer works. The residual T-S2 gap is build-tool plugin execution (Rollup/Babel/Vitest/ESLint), which `ignore-scripts` does not cover. Closing it requires running builds in an isolated environment without access to long-lived credentials.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "repo",
        "citation": "- GitHub: revoke all active sessions (`https://github.com/settings/sessions`), revoke all OAuth/PAT tokens (`/settings/tokens`, `/settings/applications`), review authorized SSH keys and remove any unrecognised. If a PAT with `repo` or `admin:org` scope existed, assume leak.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm token list",
        "citation": "- npm: run `npm token list` and `npm token revoke <token>` for any publish-capable token. If no CLI access, revoke via `https://www.npmjs.com/settings/<user>/tokens`. Rotate npm password and force sign-out of all sessions.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm token revoke <token>",
        "citation": "- npm: run `npm token list` and `npm token revoke <token>` for any publish-capable token. If no CLI access, revoke via `https://www.npmjs.com/settings/<user>/tokens`. Rotate npm password and force sign-out of all sessions.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "git log --tags --oneline -n 20",
        "citation": "- Verify recent tags match intent: `git log --tags --oneline -n 20`. Compare with `https://www.npmjs.com/package/axios?activeTab=versions`.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm audit signatures axios@<version>",
        "citation": "- For each recent publish, verify provenance: `npm audit signatures axios@<version>` and cross-check the `sourceCommit` in the provenance attestation against the tag's SHA. Divergence = investigate.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "sourceCommit",
        "citation": "- For each recent publish, verify provenance: `npm audit signatures axios@<version>` and cross-check the `sourceCommit` in the provenance attestation against the tag's SHA. Divergence = investigate.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "sk-ssh-ed25519@openssh.com",
        "citation": "- Generate new SSH keys on clean hardware. Remove old keys from GitHub. If using `sk-ssh-ed25519@openssh.com`, register new hardware key first, then deregister the old one. Do not leave the account with zero registered keys.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "security@npmjs.com",
        "citation": "- npm security: `security@npmjs.com`. Include package name, suspected versions, timeline.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm unpublish <pkg>@<version>",
        "citation": "- npm allows `npm unpublish <pkg>@<version>` within 72 hours of publish. After that, use `npm deprecate <pkg>@<version> \"<reason>\"` with a message pointing to the advisory.",
        "file": "THREATMODEL.md"
      },
      {
        "command": "npm deprecate <pkg>@<version> \"<reason>\"",
        "citation": "- npm allows `npm unpublish <pkg>@<version>` within 72 hours of publish. After that, use `npm deprecate <pkg>@<version> \"<reason>\"` with a message pointing to the advisory.",
        "file": "THREATMODEL.md"
      }
    ],
    "fullText": "# README.md\n<h3 align=\"center\">💎 Platinum sponsors <br /></h3>\n<table align=\"center\">\n    <tr>\n        <td align=\"center\" width=\"50%\">\n            <a\n                href=\"https://thanks.dev/?utm_source&#x3D;axios&amp;utm_medium&#x3D;sponsorlist&amp;utm_campaign&#x3D;sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"90px\"\n                    height=\"90px\"\n                    src=\"https://images.opencollective.com/thanks-dev/360b917/logo/256.png?height=256\"\n                    alt=\"Thanks.dev\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                We're passionate about making open source sustainable. Scan your dependency tree to better understand which open source projects need funding.\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://thanks.dev/?utm_source&#x3D;axios&amp;utm_medium&#x3D;readme_sponsorlist&amp;utm_campaign&#x3D;sponsorship\"\n                    target=\"_blank\"\n                    ><b>thanks.dev</b></a\n                >\n            </p>\n        </td>\n        <td align=\"center\" width=\"50%\">\n            <a\n                href=\"https://opencollective.com/axios/contribute\"\n                target=\"_blank\"\n                >💜 Become a sponsor</a\n            >\n        </td>\n    </tr>\n</table>\n<table align=\"center\">\n    <tr>\n        <td align=\"center\" width=\"50%\">\n            <a\n                href=\"https://opencollective.com/axios/contribute\"\n                target=\"_blank\"\n                >💜 Become a sponsor</a\n            >\n        </td>\n        <td align=\"center\" width=\"50%\">\n            <a\n                href=\"https://opencollective.com/axios/contribute\"\n                target=\"_blank\"\n                >💜 Become a sponsor</a\n            >\n        </td>\n    </tr>\n</table>\n<h3 align=\"center\">🥇 Gold sponsors <br /></h3>\n<table align=\"center\" width=\"100%\">\n    <tr width=\"33.333333333333336%\">\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://www.principal.com/about-us?utm_source&#x3D;axios&amp;utm_medium&#x3D;sponsorlist&amp;utm_campaign&#x3D;sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"90px\"\n                    height=\"90px\"\n                    src=\"https://images.opencollective.com/principal/431e690/logo.png\"\n                    alt=\"Principal Financial Group\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                Free tools to help with your financial planning needs!\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://www.principal.com/about-us?utm_source&#x3D;axios&amp;utm_medium&#x3D;readme_sponsorlist&amp;utm_campaign&#x3D;sponsorship\"\n                    target=\"_blank\"\n                    ><b>principal.com</b></a\n                >\n            </p>\n        </td>\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://opensource.sap.com?utm_source&#x3D;axios&amp;utm_medium&#x3D;sponsorlist&amp;utm_campaign&#x3D;sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"90px\"\n                    height=\"90px\"\n                    src=\"https://avatars.githubusercontent.com/u/2531208?s=200&v=4\"\n                    alt=\"SAP\"\n                />\n            </a>\n            <p\n                align=\"center\"\n                title=\"SAP SE, a global software company, is one of the largest vendors of ERP and other enterprise applications.\"\n            >\n                BSAP SE, a global software company, is one of the largest vendors of ERP and other enterprise applications.\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://opensource.sap.com?utm_source&#x3D;axios&amp;utm_medium&#x3D;readme_sponsorlist&amp;utm_campaign&#x3D;sponsorship\"\n                    target=\"_blank\"\n                    ><b>opensource.sap.com</b></a\n                >\n            </p>\n        </td>\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://www.descope.com/?utm_source&#x3D;axios&amp;utm_medium&#x3D;referral&amp;utm_campaign&#x3D;axios-oss-sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n               <img\n                    width=\"90px\"\n                    height=\"90px\"\n                    src=\"https://images.opencollective.com/descope/b53243e/logo.png\"\n                    alt=\"Descope\"\n                />\n            </a>\n            <p\n                align=\"center\"\n                title=\"Hi, we&#x27;re Descope! We are building something in the authentication space for app developers and can't wait to place it in your hands.\"\n            >\n                Reduce user friction, prevent account takeover, and get a 360° view of your customer and agentic identities with the Descope External IAM platform.\n            </p>\n              <p align=\"center\">\n                   <a\n                       href=\"https://www.descope.com/?utm_source&#x3D;axios&amp;utm_medium&#x3D;referral&amp;utm_campaign&#x3D;axios-oss-sponsorship\"\n                       target=\"_blank\"\n                       ><b>descope.com</b></a\n                   >\n              </p>\n        </td>\n    </tr>\n    <tr width=\"33.333333333333336%\">\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://stytch.com/\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n               <img\n                    width=\"90px\"\n                    height=\"90px\"\n                    src=\"https://images.opencollective.com/stytch/f84ce43/logo/256.png?height=256\"\n                    alt=\"Stytch\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                The identity platform for humans & AI agents\n            </p>\n            <p align=\"center\">\n                   <a\n                       href=\"https://stytch.com\"\n                       target=\"_blank\"\n                       ><b>stytch.com</b></a\n                   >\n              </p>\n        </td>\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://rxdb.info/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship&utm_content=logo\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"90px\"\n                    height=\"90px\"\n                    src=\"https://rxdb.info/files/logo/logo_text_white.svg\"\n                    alt=\"RxDB\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                RxDB is a NoSQL database for JavaScript that runs directly in your app.\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://rxdb.info/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship&utm_content=logo\"\n                    target=\"_blank\"\n                    ><b>rxdb.info</b></a\n                >\n            </p>\n        </td>\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://poprey.com/?utm_source&#x3D;axios&amp;utm_medium&#x3D;sponsorlist&amp;utm_campaign&#x3D;sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"70px\"\n                    height=\"70px\"\n                    src=\"https://images.opencollective.com/instagram-likes/2a72a03/avatar.png\"\n                    alt=\"Poprey\"\n                />\n            </a>\n            <p align=\"center\">\n                Buy Instagram Likes\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://poprey.com/?utm_source&#x3D;axios&amp;utm_medium&#x3D;readme_sponsorlist&amp;utm_campaign&#x3D;sponsorship\"\n                    target=\"_blank\"\n                    ><b>poprey.com</b></a\n                >\n            </p>\n        </td>\n    </tr>\n    <tr width=\"33.333333333333336%\">\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://buzzoid.com/buy-instagram-followers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"71px\"\n                    height=\"70px\"\n                    src=\"https://images.opencollective.com/buzzoid-buy-instagram-followers/56a09fe/logo.png\"\n                    alt=\"Buzzoid - Buy Instagram Followers\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                At Buzzoid, you can buy Instagram followers through a short checkout flow with safety controls. Rated world&#39;s #1 IG service since 2012.\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://buzzoid.com/buy-instagram-followers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                    target=\"_blank\"\n                    ><b>buzzoid.com</b></a\n                >\n            </p>\n        </td>\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://twicsy.com/buy-instagram-followers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"71px\"\n                    height=\"70px\"\n                    src=\"https://images.opencollective.com/buy-instagram-followers-twicsy/b4c5d7f/logo/256.png?height=256\"\n                    alt=\"Buy Instagram Followers Twicsy\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                Buy real Instagram followers from Twicsy. Twicsy has been voted the best site to buy followers from the likes of US Magazine.\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://twicsy.com/buy-instagram-followers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                    target=\"_blank\"\n                    ><b>twicsy.com</b></a\n                >\n            </p>\n        </td>\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://global.fun88.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"71px\"\n                    height=\"70px\"\n                    src=\"https://images.opencollective.com/fun88-official/bf2843c/logo.png\"\n                    alt=\"Fun 88\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                Fun88 is a global online gambling and betting brand founded in 2009, offering a wide range of services including sports betting, live casino games, slots, and virtual gaming.\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://global.fun88.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                    target=\"_blank\"\n                    ><b>global.fun88.com</b></a\n                >\n            </p>\n        </td>\n    </tr>\n    <tr width=\"33.333333333333336%\">\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://www.jbo88b.com/vn/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"71px\"\n                    height=\"70px\"\n                    src=\"https://images.opencollective.com/jbo-vietnam/3fc6159/avatar.png\"\n                    alt=\"JBO Vietnam\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                JBO Vietnam is a prominent online entertainment brand in Vietnam, offering sports betting, esports, online casino games, and a wide range of other exciting games.\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://www.jbo88b.com/vn/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                    target=\"_blank\"\n                    ><b>jbo88b.com</b></a\n                >\n            </p>\n        </td>\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://www.jbo579.com/th/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                style=\"padding: 10px; display: inline-block\"\n                target=\"_blank\"\n            >\n                <img\n                    width=\"71px\"\n                    height=\"70px\"\n                    src=\"https://images.opencollective.com/jbo-thailand/d17e84f/avatar.png\"\n                    alt=\"JBO Thailand\"\n                />\n            </a>\n            <p\n                align=\"center\"\n            >\n                JBO Thailand is a prominent online entertainment brand in Thailand, offering sports betting, esports, online casino games, and a wide range of other exciting games.\n            </p>\n            <p align=\"center\">\n                <a\n                    href=\"https://www.jbo579.com/th/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship\"\n                    target=\"_blank\"\n                    ><b>jbo88b.com</b></a\n                >\n            </p>\n        </td>\n        <td align=\"center\" width=\"33.333333333333336%\">\n            <a\n                href=\"https://opencollective.com/axios/contribute\"\n                target=\"_blank\"\n                >💜 Become a sponsor</a\n            >\n        </td>\n    </tr>\n</table>\n\n<!--<div>marker</div>-->\n\n<br><br>\n\n<div align=\"center\">\n   <a href=\"https://axios.rest\"><img src=\"https://axios.rest/logo.svg\" alt=\"Axios\" /></a><br>\n</div>\n\n<p align=\"center\">Promise based HTTP client for the browser and node.js</p>\n\n<p align=\"center\">\n    <a href=\"https://axios.rest/\"><b>Website</b></a> •\n    <a href=\"https://axios.rest/pages/getting-started/first-steps.html\"><b>Documentation</b></a>\n</p>\n\n<div align=\"center\">\n\n[![npm version](https://img.shields.io/npm/v/axios.svg?style=flat-square)](https://www.npmjs.org/package/axios)\n[![Build status](https://img.shields.io/github/actions/workflow/status/axios/axios/ci.yml?branch=v1.x&label=CI&logo=github&style=flat-square)](https://github.com/axios/axios/actions/workflows/ci.yml)\n[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod&style=flat-square)](https://gitpod.io/#https://github.com/axios/axios)\n[![install size](https://img.shields.io/badge/dynamic/json?url=https://packagephobia.com/v2/api.json?p=axios&query=$.install.pretty&label=install%20size&style=flat-square)](https://packagephobia.now.sh/result?p=axios)\n[![npm bundle size](https://img.shields.io/bundlephobia/minzip/axios?style=flat-square)](https://bundlephobia.com/package/axios@latest)\n[![npm downloads](https://img.shields.io/npm/dm/axios.svg?style=flat-square)](https://npm-stat.com/charts.html?package=axios)\n[![gitter chat](https://img.shields.io/gitter/room/mzabriskie/axios.svg?style=flat-square)](https://gitter.im/mzabriskie/axios)\n[![code helpers](https://www.codetriage.com/axios/axios/badges/users.svg)](https://www.codetriage.com/axios/axios)\n[![Contributors](https://img.shields.io/github/contributors/axios/axios.svg?style=flat-square)](CONTRIBUTORS.md)\n[![Agent Friendly](https://agentfriendlycode.com/api/badge/github/axios/axios.svg)](https://agentfriendlycode.com/repo/32)\n\n</div>\n\n## Table of contents\n\n- [Features](#features)\n- [Browser support](#browser-support)\n- [Installing](#installing)\n  - [Package manager](#package-manager)\n  - [CDN](#cdn)\n- [Example](#example)\n- [Axios API](#axios-api)\n- [Request method aliases](#request-method-aliases)\n- [Concurrency](#concurrency-deprecated)\n- [Creating an instance](#creating-an-instance)\n- [Instance methods](#instance-methods)\n- [Request config](#request-config)\n- [Response schema](#response-schema)\n- [Config defaults](#config-defaults)\n  - [Global axios defaults](#global-axios-defaults)\n  - [Custom instance defaults](#custom-instance-defaults)\n  - [Config order of precedence](#config-order-of-precedence)\n- [Interceptors](#interceptors)\n  - [Multiple interceptors](#multiple-interceptors)\n- [Handling errors](#handling-errors)\n- [Handling timeouts](#handling-timeouts)\n- [Cancellation](#cancellation)\n  - [AbortController](#abortcontroller)\n  - [CancelToken](#canceltoken-deprecated)\n- [Using application/x-www-form-urlencoded format](#using-applicationx-www-form-urlencoded-format)\n  - [URLSearchParams](#urlsearchparams)\n  - [Query string](#query-string-older-browsers)\n  - [Automatic serialization](#automatic-serialization-to-urlsearchparams)\n- [Using multipart/form-data format](#using-multipartform-data-format)\n  - [FormData](#formdata)\n  - [Automatic serialization](#automatic-serialization-to-formdata)\n- [Posting files](#posting-files)\n- [HTML form posting](#html-form-posting-browser)\n- [Progress capturing](#progress-capturing)\n- [Rate limiting](#rate-limiting)\n- [AxiosHeaders](#axiosheaders)\n- [Fetch adapter](#fetch-adapter)\n  - [Custom fetch](#custom-fetch)\n    - [Using with Tauri](#using-with-tauri)\n    - [Using with SvelteKit](#using-with-sveltekit)\n- [HTTP/2 support](#http2-support)\n- [Semver](#semver)\n- [Promises](#promises)\n- [TypeScript](#typescript)\n- [Contributing](#contributing)\n  - [Local setup](#local-setup)\n- [Resources](#resources)\n- [Credits](#credits)\n- [License](#license)\n\n## Features\n\n- Make [XMLHttpRequests](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) from the browser.\n- Make [http](https://nodejs.org/api/http.html) requests from Node.js.\n- Use the [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) API for asynchronous request handling.\n- Intercept requests and responses to add custom logic or transform data.\n- Transform request and response data.\n- Cancel requests with built-in cancellation APIs.\n- Serialize and parse [JSON](https://www.json.org/json-en.html) data.\n- Serialize data objects to `multipart/form-data` or `application/x-www-form-urlencoded`.\n- Add client-side protection against [Cross-Site Request Forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery).\n\n## Browser support\n\n|                                                     Chrome                                                     |                                                      Firefox                                                      |                                                     Safari                                                     |                                                    Opera                                                    |                                                   Edge                                                   |\n| :------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------: |\n| ![Chrome browser logo](https://raw.githubusercontent.com/alrra/browser-logos/main/src/chrome/chrome_48x48.png) | ![Firefox browser logo](https://raw.githubusercontent.com/alrra/browser-logos/main/src/firefox/firefox_48x48.png) | ![Safari browser logo](https://raw.githubusercontent.com/alrra/browser-logos/main/src/safari/safari_48x48.png) | ![Opera browser logo](https://raw.githubusercontent.com/alrra/browser-logos/main/src/opera/opera_48x48.png) | ![Edge browser logo](https://raw.githubusercontent.com/alrra/browser-logos/main/src/edge/edge_48x48.png) |\n|                                                    Latest ✔                                                    |                                                     Latest ✔                                                      |                                                    Latest ✔                                                    |                                                  Latest ✔                                                   |                                                 Latest ✔                                                 |\n\n[![Browser Matrix](https://saucelabs.com/open_sauce/build_matrix/axios.svg)](https://saucelabs.com/u/axios)\n\n## Installing\n\n### Package manager\n\nUsing npm:\n\n```bash\n$ npm install axios\n```\n\nUsing yarn:\n\n```bash\n$ yarn add axios\n```\n\nUsing pnpm:\n\n```bash\n$ pnpm add axios\n```\n\nUsing bun:\n\n```bash\n$ bun add axios\n```\n\nUsing Deno:\n\n```bash\n$ deno add axios\n```\n\nOnce the package is installed, import it with `import` or `require`:\n\n```js\nimport axios, { isCancel, AxiosError } from 'axios';\n```\n\nYou can also use the default export, since the named export is just a re-export from the Axios factory:\n\n```js\nimport axios from 'axios';\n\nconsole.log(axios.isCancel('something'));\n```\n\nIf you use `require` for importing, **only the default export is available**:\n\n```js\nconst axios = require('axios');\n\nconsole.log(axios.isCancel('something'));\n```\n\nSome bundlers and ES6 linters need this form:\n\n```js\nimport { default as axios } from 'axios';\n```\n\nIn custom or legacy environments, you can import the bundle directly:\n\n```js\nconst axios = require('axios/dist/browser/axios.cjs'); // browser commonJS bundle (ES2017)\n// const axios = require('axios/dist/node/axios.cjs'); // node commonJS bundle (ES2017)\n```\n\n### CDN\n\nUsing jsDelivr CDN (ES5 UMD browser module):\n\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/axios@1.13.2/dist/axios.min.js\"></script>\n```\n\nUsing unpkg CDN:\n\n```html\n<script src=\"https://unpkg.com/axios@1.13.2/dist/axios.min.js\"></script>\n```\n\n## Example\n\n```js\nimport axios from 'axios';\n//const axios = require('axios'); // legacy way\n\ntry {\n  const response = await axios.get('/user?ID=12345');\n  console.log(response);\n} catch (error) {\n  console.error(error);\n}\n\n// Optionally the request above could also be done as\naxios\n  .get('/user', {\n    params: {\n      ID: 12345,\n    },\n    timeout: 5000, // 5 seconds. See \"Handling Timeouts\" below for matching error handling\n  })\n  .then(function (response) {\n    console.log(response);\n  })\n  .catch(function (error) {\n    console.log(error);\n  })\n  .finally(function () {\n    // always executed\n  });\n\n// Want to use async/await? Add the `async` keyword to your outer function/method.\nasync function getUser() {\n  try {\n    // Example: GET request with query parameters\n    const response = await axios.get('/user', {\n      params: {\n        ID: 12345,\n      },\n    });\n\n    // Using the `params` option improves readability and automatically formats query strings\n\n    console.log(response);\n  } catch (error) {\n    console.error(error);\n  }\n}\n```\n\n> Note: Set a `timeout` in production. Without one, a stalled request can hang\n> indefinitely. See [Handling Timeouts](#handling-timeouts) for the matching error handling.\n\n> Note: `async/await` is part of ECMAScript 2017 and is not supported in Internet\n> Explorer and older browsers, so use with caution.\n\nPerforming a `POST` request\n\n```js\nconst response = await axios.post('/user', {\n  firstName: 'Fred',\n  lastName: 'Flintstone',\n});\nconsole.log(response);\n```\n\nPerforming multiple concurrent requests\n\n```js\nfunction getUserAccount() {\n  return axios.get('/user/12345');\n}\n\nfunction getUserPermissions() {\n  return axios.get('/user/12345/permissions');\n}\n\nPromise.all([getUserAccount(), getUserPermissions()]).then(function (results) {\n  const acct = results[0];\n  const perm = results[1];\n});\n```\n\n## axios API\n\nRequests can be made by passing the relevant config to `axios`.\n\n##### axios(config)\n\n```js\n// Send a POST request\naxios({\n  method: 'post',\n  url: '/user/12345',\n  data: {\n    firstName: 'Fred',\n    lastName: 'Flintstone',\n  },\n});\n```\n\n```js\n// GET request for remote image in node.js\nconst response = await axios({\n  method: 'get',\n  url: 'https://bit.ly/2mTM3nY',\n  responseType: 'stream',\n});\nresponse.data.pipe(fs.createWriteStream('ada_lovelace.jpg'));\n```\n\n##### axios(url[, config])\n\n```js\n// Send a GET request (default method)\naxios('/user/12345');\n```\n\n### Request method aliases\n\nFor convenience, aliases have been provided for all common request methods.\n\n##### axios.request(config)\n\n##### axios.get(url[, config])\n\n##### axios.delete(url[, config])\n\n##### axios.head(url[, config])\n\n##### axios.options(url[, config])\n\n##### axios.post(url[, data[, config]])\n\n##### axios.put(url[, data[, config]])\n\n##### axios.patch(url[, data[, config]])\n\n###### Note\n\nWhen using the alias methods `url`, `method`, and `data` properties don't need to be specified in config.\n\n### Concurrency (deprecated)\n\nUse `Promise.all` instead of these helpers.\n\nHelper functions for dealing with concurrent requests.\n\naxios.all(iterable)\naxios.spread(callback)\n\n### Creating an instance\n\nYou can create a new instance of axios with a custom config.\n\n##### axios.create([config])\n\n```js\nconst instance = axios.create({\n  baseURL: 'https://some-domain.com/api/',\n  timeout: 1000,\n  headers: { 'X-Custom-Header': 'foobar' },\n});\n```\n\n### Instance methods\n\nThe following instance methods are available. Axios merges the specified config with the instance config.\n\n##### axios#request(config)\n\n##### axios#get(url[, config])\n\n##### axios#delete(url[, config])\n\n##### axios#head(url[, config])\n\n##### axios#options(url[, config])\n\n##### axios#post(url[, data[, config]])\n\n##### axios#put(url[, data[, config]])\n\n##### axios#patch(url[, data[, config]])\n\n##### axios#getUri([config])\n\n## Request config\n\n### Security notice: decompression-bomb protection is opt-in\n\nBy default `maxContentLength` and `maxBodyLength` are `-1` (unlimited). A malicious or compromised server can return a tiny gzip/deflate/brotli/zstd body that expands to gigabytes and exhaust the Node.js process.\n\nIf you call servers you do not fully trust, **set a cap**:\n\n```js\naxios.defaults.maxContentLength = 10 * 1024 * 1024; // 10 MB\naxios.defaults.maxBodyLength = 10 * 1024 * 1024;\n```\n\nSee the [security guide](https://axios.rest/pages/misc/security.html) for details.\n\nThese config options are available for requests. Only `url` is required. Requests default to `GET` when `method` is not set.\n\n```js\n{\n  // `url` is the server URL for the request\n  url: '/user',\n\n  // `method` is the request method to be used when making the request\n  method: 'get', // default\n\n  // Axios prepends `baseURL` to `url` unless `url` is absolute and `allowAbsoluteUrls` is set to true.\n  // It can be convenient to set `baseURL` for an instance of axios to pass relative URLs\n  // to the methods of that instance.\n  // `baseURL` is not a security boundary. If `url` is attacker-controlled, validate it\n  // before passing it to axios. Relative URLs can contain `..` segments that resolve\n  // outside an intended path prefix after the final URL is parsed.\n  baseURL: 'https://some-domain.com/api/',\n\n  // `allowAbsoluteUrls` determines whether or not absolute URLs will override a configured `baseUrl`.\n  // When set to true (default), absolute values for `url` will override `baseUrl`.\n  // When set to false, absolute values for `url` will always be prepended by `baseUrl`.\n  allowAbsoluteUrls: true,\n\n  // `transformRequest` allows changes to the request data before it is sent to the server\n  // This is only applicable for request methods 'PUT', 'POST', 'PATCH' and 'DELETE'\n  // The last function in the array must return a string or an instance of Buffer, ArrayBuffer,\n  // FormData or Stream\n  // You may modify the headers object.\n  transformRequest: [function (data, headers) {\n    // Do whatever you want to transform the data\n\n    return data;\n  }],\n\n  // `transformResponse` allows changes to the response data to be made before\n  // it is passed to then/catch\n  transformResponse: [function (data) {\n    // Do whatever you want to transform the data\n\n    return data;\n  }],\n\n  // `parseReviver` is an optional function passed as the\n  // second argument (reviver) to JSON.parse()\n  parseReviver: function (key, value, context) {\n    // In modern environments, context.source provides the raw JSON string\n    // allowing for precision-safe parsing of BigInt\n    if (typeof value === 'number' && context?.source) {\n      const isInteger = Number.isInteger(value);\n      const isUnsafe = !Number.isSafeInteger(value);\n      const isValidIntegerString = /^-?\\d+$/.test(context.source);\n\n      if (isInteger && isUnsafe && isValidIntegerString) {\n        try {\n          return BigInt(context.source);\n        } catch {\n          // Fallback: return original value if parsing fails\n        }\n      }\n    }\n    return value;\n  },\n\n  // `headers` are custom headers to be sent\n  headers: {'X-Requested-With': 'XMLHttpRequest'},\n\n  // `params` are the URL parameters to be sent with the request\n  // Must be a plain object or a URLSearchParams object\n  params: {\n    ID: 12345\n  },\n\n  // `paramsSerializer` is an optional config that allows you to customize serializing `params`.\n  paramsSerializer: {\n\n    // Custom encoder function which sends key/value pairs in an iterative fashion.\n    encode?: (param: string): string => { /* Do custom operations here and return transformed string */ },\n\n    // Custom serializer function for the entire parameter. Allows the user to mimic pre 1.x behaviour.\n    serialize?: (params: Record<string, any>, options?: ParamsSerializerOptions ),\n\n    // Configuration for formatting array indexes in the params.\n    indexes: false, // Three available options: (1) indexes: null (leads to no brackets), (2) (default) indexes: false (leads to empty brackets), (3) indexes: true (leads to brackets with indexes).\n\n    // Maximum object nesting depth when serializing params. Payloads deeper than this throw an\n    // AxiosError with code ERR_FORM_DATA_DEPTH_EXCEEDED. Default: 100. Set to Infinity to disable.\n    maxDepth: 100\n\n  },\n\n  // `data` is the data to be sent as the request body\n  // Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH'\n  // `data` is request-specific: axios does not inherit or deep-merge it from defaults.\n  // To add shared body fields, use a request interceptor or transformRequest.\n  // When no `transformRequest` is set, it must be of one of the following types:\n  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams\n  // - Browser only: FormData, File, Blob\n  // - React Native: FormData\n  // - Node only: Stream, Buffer, FormData (form-data package)\n  data: {\n    firstName: 'Fred'\n  },\n\n  // `formDataHeaderPolicy` controls how node.js FormData#getHeaders() is copied.\n  // 'legacy' (default) copies all returned headers for v1 compatibility.\n  // 'content-only' copies only Content-Type and Content-Length.\n  formDataHeaderPolicy: 'legacy',\n\n  // syntax alternative to send data into the body\n  // method post\n  // only the value is sent, not the key\n  data: 'Country=Brasil&City=Belo Horizonte',\n\n  // `timeout` specifies the number of milliseconds before the request times out.\n  // If the request takes longer than `timeout`, Axios aborts it.\n  timeout: 1000, // default is `0` (no timeout)\n\n  // `withCredentials` indicates whether or not cross-site Access-Control requests\n  // should be made using credentials\n  // This only controls whether the browser sends credentials.\n  // It does not control whether the XSRF header is added.\n  withCredentials: false, // default\n\n  // `adapter` allows custom handling of requests which makes testing easier.\n  // Return a promise and supply a valid response (see lib/adapters/README.md)\n  adapter: function (config) {\n    /* ... */\n  },\n  // Also, you can set the name of the built-in adapter, or provide an array with their names\n  // to choose the first available in the environment\n  adapter: 'xhr', // 'fetch' | 'http' | ['xhr', 'http', 'fetch']\n\n  // `auth` indicates that HTTP Basic auth should be used, and supplies credentials.\n  // This will set an `Authorization` header, overwriting any existing\n  // `Authorization` custom headers you have set using `headers`.\n  // If `auth` is omitted, the Node.js HTTP and fetch adapters can read\n  // HTTP Basic auth credentials from the request URL, for example\n  // `https://user:pass@example.com`. Axios decodes percent-encoded URL\n  // credentials, and `auth` takes precedence over URL-embedded credentials.\n  // The Node.js HTTP adapter preserves Basic auth on same-origin redirects\n  // and strips it on cross-origin redirects.\n  // Please note that only HTTP Basic auth is configurable through this parameter.\n  // For Bearer tokens and such, use `Authorization` custom headers instead.\n  auth: {\n    username: 'janedoe',\n    password: 's00pers3cret'\n  },\n\n  // `responseType` indicates the type of data that the server will respond with\n  // options are: 'arraybuffer', 'document', 'json', 'text', 'stream'\n  //   browser only: 'blob'\n  responseType: 'json', // default\n\n  // `responseEncoding` indicates encoding to use for decoding responses (Node.js only)\n  // Note: Ignored for `responseType` of 'stream' or client-side requests\n  // options are: 'ascii', 'ASCII', 'ansi', 'ANSI', 'binary', 'BINARY', 'base64', 'BASE64', 'base64url',\n  // 'BASE64URL', 'hex', 'HEX', 'latin1', 'LATIN1', 'ucs-2', 'UCS-2', 'ucs2', 'UCS2', 'utf-8', 'UTF-8',\n  // 'utf8', 'UTF8', 'utf16le', 'UTF16LE'\n  responseEncoding: 'utf8', // default\n\n  // `xsrfCookieName` is the name of the cookie to use as a value for the xsrf token\n  xsrfCookieName: 'XSRF-TOKEN', // default\n\n  // `xsrfHeaderName` is the name of the http header that carries the xsrf token value\n  xsrfHeaderName: 'X-XSRF-TOKEN', // default\n\n  // `withXSRFToken` defines whether to send the XSRF header in browser requests.\n  // `undefined` (default) - set XSRF header only for the same origin requests\n  // `true` - always set XSRF header, including for cross-origin requests\n  // `false` - never set XSRF header\n  // function - resolve with custom logic; receives the internal config object\n  withXSRFToken: boolean | undefined | ((config: InternalAxiosRequestConfig) => boolean | undefined),\n\n  // `withXSRFToken` controls whether Axios reads the XSRF cookie and sets the XSRF header.\n  // - `undefined` (default): the XSRF header is set only for same-origin requests.\n  // - `true`: attempt to set the XSRF header for all requests (including cross-origin).\n  // - `false`: never set the XSRF header.\n  // - function: a callback that receives the request `config` and returns `true`,\n  //   `false`, or `undefined` to decide per-request behavior.\n  //\n  // Note about `withCredentials`: `withCredentials` controls whether cross-site\n  // requests include credentials (cookies and HTTP auth). In older Axios versions,\n  // setting `withCredentials: true` implicitly caused Axios to set the XSRF header\n  // for cross-origin requests. Newer Axios separates these concerns: to allow the\n  // XSRF header to be sent for cross-origin requests you should set both\n  // `withCredentials: true` and `withXSRFToken: true`.\n  //\n  // Example:\n  // axios.get('/user', { withCredentials: true, withXSRFToken: true });\n\n  // `onUploadProgress` allows handling of progress events for uploads\n  // browser & node.js\n  onUploadProgress: function ({loaded, total, progress, bytes, estimated, rate, upload = true}) {\n    // Do whatever you want with the Axios progress event\n  },\n\n  // `onDownloadProgress` allows handling of progress events for downloads\n  // browser & node.js\n  onDownloadProgress: function ({loaded, total, progress, bytes, estimated, rate, download = true}) {\n    // Do whatever you want with the Axios progress event\n  },\n\n  // `maxContentLength` defines the max size of the response content in bytes.\n  // It is enforced by the Node.js HTTP adapter and the fetch adapter.\n  maxContentLength: 2000,\n\n  // `maxBodyLength` defines the max size of the request content in bytes.\n  // It is enforced by the Node.js HTTP adapter and the fetch adapter when the body length can be determined.\n  maxBodyLength: 2000,\n\n  // `redact` masks matching config keys when AxiosError#toJSON() is called.\n  // Matching is case-insensitive and recursive. It does not change the request.\n  redact: ['authorization', 'password'],\n\n  // `validateStatus` defines whether to resolve or reject the promise for a given\n  // HTTP response status code. If `validateStatus` returns `true` or is set to\n  // `null`, Axios resolves the promise; otherwise, Axios rejects it.\n  // Explicit `validateStatus: undefined` resolves every status by default for\n  // backward compatibility. Set `transitional.validateStatusUndefinedResolves`\n  // to `false` to make explicit `undefined` behave as if this option was omitted.\n  validateStatus: function (status) {\n    return status >= 200 && status < 300; // default\n  },\n\n  // `maxRedirects` defines the maximum number of redirects to follow in node.js.\n  // If set to 0, Axios follows no redirects.\n  maxRedirects: 21, // default\n\n  // `sensitiveHeaders` (Node only option) lists custom secret-bearing headers\n  // (such as `X-API-Key`) to remove from cross-origin redirects. Matching is\n  // case-insensitive. Same-origin redirects keep these headers. If\n  // `maxRedirects` is 0, this option is not used.\n  sensitiveHeaders: ['X-API-Key'],\n\n  // `beforeRedirect` defines a function that Axios calls before redirect.\n  // Use this to adjust the request options upon redirecting,\n  // to inspect the latest response headers,\n  // or to cancel the request by throwing an error\n  // If maxRedirects is set to 0, `beforeRedirect` is not used.\n\n  beforeRedirect: (options, { headers }) => {\n    if (\n      options.hostname === \"example.com\" &&\n      options.protocol === \"https:\"\n    ) {\n      options.auth = \"user:password\";\n    }\n  },\n  // Security note:\n  // The `beforeRedirect` hook runs after sensitive headers are stripped during redirects.\n  // `follow-redirects` removes credentials on protocol downgrades\n  // (HTTPS to HTTP). Because `beforeRedirect` runs after that step,\n  // re-injecting credentials without checking the destination can expose\n  // sensitive data. Only add credentials for trusted HTTPS destinations.\n\n  // `socketPath` defines a UNIX Socket to be used in node.js.\n  // e.g. '/var/run/docker.sock' to send requests to the docker daemon.\n  // Only either `socketPath` or `proxy` can be specified.\n  // If both are specified, `socketPath` is used.\n  //\n  // Security: when `socketPath` is set, hostname/port of the URL are ignored,\n  // which bypasses hostname-based SSRF protections. Never derive `socketPath`\n  // from untrusted input. Use `allowedSocketPaths` (below) to restrict accepted\n  // socket paths for defense-in-depth.\n  socketPath: null, // default\n\n  // `allowedSocketPaths` restricts which `socketPath` values are accepted.\n  // Accepts a string or array of strings. Entries and the incoming socketPath\n  // are compared after path.resolve(). A mismatch throws AxiosError with code\n  // `ERR_BAD_OPTION_VALUE`. When null/undefined, no restriction is applied.\n  allowedSocketPaths: null, // default\n\n  // `transport` determines the transport method for the request.\n  // If defined, Axios uses it. Otherwise, if `maxRedirects` is 0,\n  // Axios uses the default `http` or `https` library, depending on the protocol specified in `protocol`.\n  // Otherwise, Axios uses the `httpFollow` or `httpsFollow` library, again depending on the protocol,\n  // which can handle redirects.\n  transport: undefined, // default\n\n  // `httpAgent` and `httpsAgent` define a custom agent to be used when performing http\n  // and https requests, respectively, in node.js. This allows options to be added like\n  // `keepAlive` that are not enabled by default before Node.js v19.0.0. After Node.js\n  // v19.0.0, you no longer need to customize the agent to enable `keepAlive` because\n  // `http.globalAgent` has `keepAlive` enabled by default.\n  httpAgent: new http.Agent({ keepAlive: true }),\n  httpsAgent: new https.Agent({ keepAlive: true }),\n\n  // `proxy` defines the hostname, port, and protocol of the proxy server.\n  // You can also define your proxy using the conventional `http_proxy` and\n  // `https_proxy` environment variables. If you are using environment variables\n  // for your proxy configuration, you can also define a `no_proxy` environment\n  // variable as a comma-separated list of domains that should not be proxied.\n  // Use `false` to disable proxies, ignoring environment variables.\n  // On Node.js versions with native environment proxy support, axios defers\n  // environment proxy handling to Node when the selected agent has `proxyEnv`\n  // enabled, including processes started with `NODE_USE_ENV_PROXY=1`,\n  // `--use-env-proxy`, or `NODE_OPTIONS=--use-env-proxy`. Custom agents without\n  // `proxyEnv` continue to use axios environment proxy resolution. Explicit\n  // `proxy` config is still handled by axios.\n  // `auth` indicates that HTTP Basic auth should be used to connect to the proxy, and\n  // supplies credentials.\n  // For `http://` targets, axios sends the request to the proxy in\n  // forward-proxy mode and stamps `Proxy-Authorization` onto the request\n  // headers (overwriting any user-supplied `Proxy-Authorization` header).\n  // For `https://` targets, axios establishes a CONNECT tunnel through the\n  // proxy and performs TLS end-to-end with the origin; `Proxy-Authorization`\n  // is sent on the CONNECT request only, never on the wrapped TLS request,\n  // so the proxy never sees the URL, headers, or body. Axios forwards\n  // `httpsAgent` TLS options such as `ca`, `cert`, `key`, and\n  // `rejectUnauthorized` to the generated tunneling agent, so they still apply\n  // to the origin TLS connection.\n  // If you supply an `HttpsProxyAgent`, axios leaves tunneling to that agent.\n  // If the proxy server uses HTTPS, then you must set the protocol to `https`.\n  // A user-supplied `Host` header in `headers` is preserved when forwarding\n  // through a proxy (case-insensitive match on `host`/`Host`/`HOST`); this\n  // lets you target a virtual host that differs from the request URL, for\n  // example, hitting `127.0.0.1:4000` while having the proxy treat the\n  // request as `example.com`. If no `Host` header is supplied, axios\n  // defaults it to the request URL's `hostname:port` as before. The Host\n  // header is only set in forward-proxy mode (HTTP targets); for HTTPS\n  // tunneling the Host header is sent inside the TLS connection, not seen\n  // by the proxy.\n  proxy: {\n    protocol: 'https',\n    host: '127.0.0.1',\n    // hostname: '127.0.0.1' // Takes precedence over 'host' if both are defined\n    port: 9000,\n    auth: {\n      username: 'mikeymike',\n      password: 'rapunz3l'\n    }\n  },\n\n  // `cancelToken` specifies a cancel token that can be used to cancel the request\n  // (see Cancellation section below for details)\n  cancelToken: new CancelToken(function (cancel) {\n  }),\n\n  // an alternative way to cancel Axios requests using AbortController\n  signal: new AbortController().signal,\n\n  // `decompress` indicates whether or not the response body should be decompressed\n  // automatically. If set to `true` will also remove the 'content-encoding' header\n  // from the responses objects of all decompressed responses\n  // Axios supports gzip, deflate, brotli, and zstd when the current Node.js\n  // runtime provides the corresponding zlib decompressor.\n  // - Node only (XHR cannot turn off decompression)\n  decompress: true, // default\n\n  // `insecureHTTPParser` boolean.\n  // Indicates where to use an insecure HTTP parser that accepts invalid HTTP headers.\n  // This may allow interoperability with non-conformant HTTP implementations.\n  // Using the insecure parser should be avoided.\n  // see options https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_http_request_url_options_callback\n  // see also https://nodejs.org/en/blog/vulnerability/february-2020-security-releases/#strict-http-header-parsing-none\n  insecureHTTPParser: undefined, // default\n\n  // transitional options for backward compatibility that may be removed in the newer versions\n  transitional: {\n    // silent JSON parsing mode\n    // `true`  - ignore JSON parsing errors and set response.data to null if parsing failed (old behaviour)\n    // `false` - throw SyntaxError if JSON parsing failed\n    // Important: this option only takes effect when `responseType` is explicitly set to 'json'.\n    // When `responseType` is omitted (defaults to no value), axios uses `forcedJSONParsing`\n    // to attempt JSON parsing, but will silently return the raw string on failure regardless\n    // of this setting. To have invalid JSON throw errors, use:\n    //   { responseType: 'json', transitional: { silentJSONParsing: false } }\n    silentJSONParsing: true, // default value for the current Axios version\n\n    // try to parse the response string as JSON even if `responseType` is not 'json'\n    forcedJSONParsing: true,\n\n    // throw ETIMEDOUT error instead of generic ECONNABORTED on request timeouts\n    clarifyTimeoutError: false,\n\n    // keep explicit `validateStatus: undefined` resolving every response status\n    // for backward compatibility. Set to false to make explicit undefined behave\n    // as if validateStatus was omitted.\n    validateStatusUndefinedResolves: true,\n\n    // advertise `zstd` in the default Accept-Encoding header when the current\n    // Node.js runtime supports zstd decompression. Axios still decompresses\n    // zstd responses when support exists and `decompress` is true.\n    advertiseZstdAcceptEncoding: false,\n\n    // use the legacy interceptor request/response ordering\n    legacyInterceptorReqResOrdering: true, // default\n  },\n\n  env: {\n    // The FormData class to be used to automatically serialize the payload into a FormData object\n    FormData: window?.FormData || global?.FormData\n  },\n\n  formSerializer: {\n      visitor: (value, key, path, helpers) => {}; // custom visitor function to serialize form values\n      dots: boolean; // use dots instead of brackets format\n      metaTokens: boolean; // keep special endings like {} in parameter key\n      indexes: boolean; // array indexes format null - no brackets, false - empty brackets, true - brackets with indexes\n      maxDepth: 100; // maximum object nesting depth; throws AxiosError (ERR_FORM_DATA_DEPTH_EXCEEDED) if exceeded. Set to Infinity to disable.\n  },\n\n  // http adapter only (node.js)\n  maxRate: [\n    100 * 1024, // 100KB/s upload limit,\n    100 * 1024  // 100KB/s download limit\n  ]\n}\n```\n\nFor custom secret-bearing headers in Node.js, list them in `sensitiveHeaders` so Axios removes them when following a redirect to another origin:\n\n```js\naxios.get('https://api.example.com/users', {\n  headers: { 'X-API-Key': 'secret' },\n  sensitiveHeaders: ['X-API-Key'],\n});\n```\n\n### Strict RFC 3986 percent-encoding for query params\n\nBy default, axios decodes `%3A`, `%24`, `%2C` and `%20` back to `:`, `$`, `,` and `+` for readability (the `+` follows the `application/x-www-form-urlencoded` convention for spaces in query strings). These characters are valid in a query component under [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.4), so the default output is correct, but some backends require strict percent-encoding and reject the readable form.\n\nOverride the default encoder via `paramsSerializer.encode`:\n\n```js\n// Per-request: emit strict RFC 3986 percent-encoding for query values\naxios.get('/foo', {\n  params: { filter: JSON.stringify({ startedAt: '2026-01-23' }) },\n  paramsSerializer: { encode: encodeURIComponent },\n});\n\n// Or set it on the instance defaults\nconst client = axios.create({\n  paramsSerializer: { encode: encodeURIComponent },\n});\n```\n\n## HTTP/2 support\n\nAxios has experimental HTTP/2 support in the Node.js HTTP adapter.\n\nSupport depends on the runtime environment and Node.js version. Redirects and some adapter behavior may differ from HTTP/1.1.\n\nOptions like `httpVersion` and `http2Options` are adapter-specific and may not work the same way in every environment.\n\nIf you need HTTP/2, check runtime support or use a custom adapter.\n\n## Response schema\n\nThe response to a request contains the following information.\n\n```js\n{\n  // `data` is the response that was provided by the server\n  data: {},\n\n  // `status` is the HTTP status code from the server response\n  status: 200,\n\n  // `statusText` is the HTTP status message from the server response\n  statusText: 'OK',\n\n  // `headers` the HTTP headers that the server responded with\n  // All header names are lowercase and can be accessed using the bracket notation.\n  // Example: `response.headers['content-type']`\n  headers: {},\n\n  // `config` is the config that was provided to `axios` for the request\n  config: {},\n\n  // `request` is the request that generated this response\n  // It is the last ClientRequest instance in node.js (in redirects)\n  // and an XMLHttpRequest instance in the browser\n  request: {}\n}\n```\n\nWhen using `then`, you receive the response like this:\n\n```js\nconst response = await axios.get('/user/12345');\nconsole.log(response.data);\nconsole.log(response.status);\nconsole.log(response.statusText);\nconsole.log(response.headers);\nconsole.log(response.config);\n```\n\nWhen using `catch`, or passing a [rejection callback](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) as the second parameter of `then`, read the response from the `error` object. See [Handling errors](#handling-errors).\n\n## Config defaults\n\nConfig defaults apply to every request.\n\n### Global axios defaults\n\n```js\naxios.defaults.baseURL = 'https://api.example.com';\n\n// Important: If you use axios with multiple domains, Axios sends AUTH_TOKEN to all of them.\n// See below for an example using Custom instance defaults instead.\naxios.defaults.headers.common['Authorization'] = AUTH_TOKEN;\n\naxios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';\n```\n\n### Custom instance defaults\n\n```js\n// Set config defaults when creating the instance\nconst instance = axios.create({\n  baseURL: 'https://api.example.com',\n});\n\n// Alter defaults after instance has been created\ninstance.defaults.headers.common['Authorization'] = AUTH_TOKEN;\n```\n\n### Config order of precedence\n\nAxios merges config in this order: library defaults from [lib/defaults/index.js](https://github.com/axios/axios/blob/main/lib/defaults/index.js#L49), the instance `defaults` property, and the request `config` argument. Later values take precedence over earlier ones.\n\nSome options are request-specific and are only taken from the request `config`. `data` is one of those options: axios does not inherit or deep-merge request bodies from global or instance defaults. If every request needs shared body fields, add them with a request interceptor or `transformRequest`, and scope that logic carefully so sensitive values are not sent to the wrong endpoint.\n\n```js\n// Create an instance using the config defaults provided by the library\n// At this point the timeout config value is `0` as is the default for the library\nconst instance = axios.create();\n\n// Override timeout default for the library\n// Now all requests using this instance will wait 2.5 seconds before timing out\ninstance.defaults.timeout = 2500;\n\n// Override timeout for this request as it's known to take a long time\ninstance.get('/longRequest', {\n  timeout: 5000,\n});\n```\n\n## Interceptors\n\nYou can intercept requests or responses before methods like `.get()` or `.post()`\nresolve their promises (before code inside `then` or `catch`, or after `await`)\n\n```js\nconst instance = axios.create();\n\n// Add a request interceptor\ninstance.interceptors.request.use(\n  function (config) {\n    // Do something before the request is sent\n    return config;\n  },\n  function (error) {\n    // Do something with the request error\n    return Promise.reject(error);\n  }\n);\n\n// Add a response interceptor\ninstance.interceptors.response.use(\n  function (response) {\n    // Any status code that lies within the range of 2xx causes this function to trigger\n    // Do something with response data\n    return response;\n  },\n  function (error) {\n    // Any status codes that fall outside the range of 2xx cause this function to trigger\n    // Do something with response error\n    return Promise.reject(error);\n  }\n);\n```\n\nIf you need to remove an interceptor later you can.\n\n```js\nconst instance = axios.create();\nconst myInterceptor = instance.interceptors.request.use(function () {\n  /*...*/\n});\ninstance.interceptors.request.eject(myInterceptor);\n```\n\nYou can also clear all interceptors for requests or responses.\n\n```js\nconst instance = axios.create();\ninstance.interceptors.request.use(function () {\n  /*...*/\n});\ninstance.interceptors.request.clear(); // Removes interceptors from requests\ninstance.interceptors.response.use(function () {\n  /*...*/\n});\ninstance.interceptors.response.clear(); // Removes interceptors from responses\n```\n\nYou can add interceptors to a custom instance of axios.\n\n```js\nconst instance = axios.create();\ninstance.interceptors.request.use(function () {\n  /*...*/\n});\n```\n\nWhen you add request interceptors, they are presumed to be asynchronous by default. This can cause a delay\nin the execution of your axios request when the main thread is blocked (a promise is created under the hood for\nthe interceptor and your request gets put at the bottom of the call stack). If your request interceptors are synchronous you can add a flag\nto the options object that will tell axios to run the code synchronously and avoid any delays in request execution.\n\n```js\naxios.interceptors.request.use(\n  function (config) {\n    config.headers.test = 'I am only a header!';\n    return config;\n  },\n  null,\n  { synchronous: true }\n);\n```\n\nIf you want to execute a particular interceptor based on a runtime check,\nyou can add a `runWhen` function to the options object. The request interceptor will not run **if and only if** the return\nof `runWhen` is `false`. Axios calls the function with the config\nobject (don't forget that you can bind your own arguments to it as well.) This can be handy when you have an\nasynchronous request interceptor that only needs to run at certain times.\n\n```js\nfunction onGetCall(config) {\n  return config.method === 'get';\n}\naxios.interceptors.request.use(\n  function (config) {\n    config.headers.test = 'special get headers';\n    return config;\n  },\n  null,\n  { runWhen: onGetCall }\n);\n```\n\n> Note: The options parameter (with `synchronous` and `runWhen` properties) is only supported for request interceptors at the moment.\n\n### Interceptor execution order\n\nRequest and response interceptors use different execution orders.\n\nRequest interceptors run in reverse order (LIFO: last in, first out). The last interceptor added runs first.\n\nResponse interceptors run in the order they were added (FIFO: first in, first out). The first interceptor added runs first.\n\nExample:\n\n```js\nconst instance = axios.create();\n\nconst interceptor = (id) => (base) => {\n  console.log(id);\n  return base;\n};\n\ninstance.interceptors.request.use(interceptor('Request Interceptor 1'));\ninstance.interceptors.request.use(interceptor('Request Interceptor 2'));\ninstance.interceptors.request.use(interceptor('Request Interceptor 3'));\ninstance.interceptors.response.use(interceptor('Response Interceptor 1'));\ninstance.interceptors.response.use(interceptor('Response Interceptor 2'));\ninstance.interceptors.response.use(interceptor('Response Interceptor 3'));\n\n// Console output:\n// Request Interceptor 3\n// Request Interceptor 2\n// Request Interceptor 1\n// [HTTP request is made]\n// Response Interceptor 1\n// Response Interceptor 2\n// Response Interceptor 3\n```\n\n### Multiple interceptors\n\nWhen a response is fulfilled and multiple response interceptors are registered:\n\n- Each interceptor runs in registration order.\n- Each interceptor receives the result from the previous interceptor.\n- The chain returns the result from the last interceptor.\n- If a fulfillment interceptor throws, Axios skips the next fulfillment interceptor and calls the next rejection interceptor.\n- After the error is caught, later fulfillment interceptors run again, just like in a promise chain.\n\nRead [the interceptor tests](./test/specs/interceptors.spec.js) to see all this in code.\n\n## Error types\n\nAxios error messages include details that can help you debug the request.\n\nAxios errors use this structure:\n| Property | Definition |\n| -------- | ---------- |\n| message | A quick summary of the error message and the status it failed with. |\n| name | This defines where the error originated from. For axios, it will always be an 'AxiosError'. |\n| stack | Stack trace for the error. |\n| config | An axios config object with specific instance configurations defined by the user from when the request was made |\n| code | Axios error code. The table below lists internal Axios error codes. |\n| status | HTTP response status code. See [here](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) for common HTTP response status code meanings.\n\nThese are the internal Axios error codes:\n\n| Code                      | Definition                                                                                                                                                                                                                                                                                                                                                                                     |\n| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| ERR_BAD_OPTION_VALUE      | Invalid value provided in axios configuration.                                                                                                                                                                                                                                                                                                                                                 |\n| ERR_BAD_OPTION            | Invalid option provided in axios configuration.                                                                                                                                                                                                                                                                                                                                                |\n| ERR_NOT_SUPPORT           | Feature or method not supported in the current axios environment.                                                                                                                                                                                                                                                                                                                              |\n| ERR_DEPRECATED            | Deprecated feature or method used in axios.                                                                                                                                                                                                                                                                                                                                                    |\n| ERR_INVALID_URL           | Invalid URL provided for axios request.                                                                                                                                                                                                                                                                                                                                                        |\n| ECONNABORTED              | Typically indicates that the request has been timed out (unless `transitional.clarifyTimeoutError` is set) or aborted by the browser or its plugin.                                                                                                                                                                                                                                            |\n| ERR_CANCELED              | The user explicitly canceled the request with an AbortSignal or CancelToken.                                                                                                                                                                                                                                                                                                                   |\n| ETIMEDOUT                 | Request timed out after exceeding the configured Axios timeout. Set `transitional.clarifyTimeoutError` to `true`; otherwise Axios throws a generic `ECONNABORTED` error.                                                                                                                                                                                                                       |\n| ERR_NETWORK               | Network-related issue. In the browser, this error can also be caused by a [CORS](https://developer.mozilla.org/ru/docs/Web/HTTP/Guides/CORS) or [Mixed Content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content) policy violation. The browser does not allow the JS code to clarify the real reason for the error caused by security issues, so please check the console. |\n| ERR_FR_TOO_MANY_REDIRECTS | Request exceeded the configured maximum number of redirects.                                                                                                                                                                                                                                                                                                                                   |\n| ERR_BAD_RESPONSE          | Response cannot be parsed properly or is in an unexpected format. Usually related to a response with `5xx` status code.                                                                                                                                                                                                                                                                        |\n| ERR_BAD_REQUEST           | The request has an unexpected format or is missing required parameters. Usually related to a response with `4xx` status code.                                                                                                                                                                                                                                                                  |\n\n## Handling errors\n\nBy default, Axios rejects responses with status codes outside the 2xx range.\n\n```js\naxios.get('/user/12345').catch(function (error) {\n  if (error.response) {\n    // The request was made and the server responded with a status code\n    // that falls out of the range of 2xx\n    console.log(error.response.data);\n    console.log(error.response.status);\n    console.log(error.response.headers);\n  } else if (error.request) {\n    // The request was made but no response was received\n    // `error.request` is an instance of XMLHttpRequest in the browser and an instance of\n    // http.ClientRequest in node.js\n    console.log(error.request);\n  } else {\n    // Something happened in setting up the request that triggered an Error\n    console.log('Error', error.message);\n  }\n  console.log(error.config);\n});\n```\n\nUse `validateStatus` to override the default condition (`status >= 200 && status < 300`) and choose which HTTP status codes should reject.\n\n```js\naxios.get('/user/12345', {\n  validateStatus: function (status) {\n    return status < 500; // Resolve only if the status code is less than 500\n  },\n});\n```\n\nBy default, explicit `validateStatus: undefined` keeps legacy behavior and resolves every response status because `transitional.validateStatusUndefinedResolves` defaults to `true`. Set it to `false` to make explicit `validateStatus: undefined` behave like the option was omitted, so Axios uses the configured/default validator and rejects non-2xx responses by default.\n\n`validateStatus: null` still accepts every response status. If you disable the transitional behavior and intentionally want all statuses to resolve, use `null` or `() => true`.\n\n```js\naxios.get('/user/12345', {\n  validateStatus: undefined,\n  transitional: {\n    validateStatusUndefinedResolves: false,\n  },\n});\n```\n\nUse `toJSON` to get more information about the HTTP error.\n\n```js\naxios.get('/user/12345').catch(function (error) {\n  console.log(error.toJSON());\n});\n```\n\nTo avoid logging secrets from `error.config`, pass a `redact` array in the request config. Matching config keys are masked case-insensitively at any depth when `AxiosError#toJSON()` is called.\n\n```js\naxios\n  .get('/user/12345', {\n    headers: { Authorization: 'Bearer token' },\n    redact: ['authorization'],\n  })\n  .catch(function (error) {\n    console.log(error.toJSON().config.headers.Authorization); // [REDACTED ****]\n  });\n```\n\n## Handling timeouts\n\n```js\nasync function fetchWithTimeout() {\n  try {\n    const response = await axios.get('https://example.com/data', {\n      timeout: 5000, // 5 seconds\n      transitional: {\n        // set to true if you prefer ETIMEDOUT over ECONNABORTED\n        clarifyTimeoutError: false,\n      },\n    });\n\n    console.log('Response:', response.data);\n  } catch (error) {\n    if (axios.isAxiosError(error)) {\n      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT') {\n        console.error('Request timed out. Please try again.');\n        return;\n      }\n\n      console.error('Axios error:', error.message);\n      return;\n    }\n\n    console.error('Unexpected error:', error);\n  }\n}\n```\n\n## Cancellation\n\n### AbortController\n\nSince `v0.22.0`, Axios supports AbortController:\n\n```js\nconst controller = new AbortController();\n\naxios\n  .get('/foo/bar', {\n    signal: controller.signal,\n  })\n  .then(function (response) {\n    //...\n  });\n// cancel the request\ncontroller.abort();\n```\n\n### CancelToken (deprecated)\n\nYou can also cancel a request using a _CancelToken_.\n\n> The axios cancel token API is based on the withdrawn [cancellable promises proposal](https://github.com/tc39/proposal-cancelable-promises).\n\n> This API is deprecated since v0.22.0 and should not be used in new projects.\n\nCreate a cancel token with the `CancelToken.source` factory:\n\n```js\nconst CancelToken = axios.CancelToken;\nconst source = CancelToken.source();\n\naxios\n  .get('/user/12345', {\n    cancelToken: source.token,\n  })\n  .catch(function (thrown) {\n    if (axios.isCancel(thrown)) {\n      console.log('Request canceled', thrown.message);\n    } else {\n      // handle error\n    }\n  });\n\naxios.post(\n  '/user/12345',\n  {\n    name: 'new name',\n  },\n  {\n    cancelToken: source.token,\n  }\n);\n\n// cancel the request (the message parameter is optional)\nsource.cancel('Operation canceled by the user.');\n```\n\nYou can also pass an executor function to the `CancelToken` constructor:\n\n```js\nconst CancelToken = axios.CancelToken;\nlet cancel;\n\naxios.get('/user/12345', {\n  cancelToken: new CancelToken(function executor(c) {\n    // An executor function receives a cancel function as a parameter\n    cancel = c;\n  }),\n});\n\n// cancel the request\ncancel();\n```\n\n`CancelToken` also exposes low-level helpers for legacy integrations:\n\n```js\nconst source = axios.CancelToken.source();\n\nconst listener = (cancel) => {\n  console.log(cancel.message);\n};\n\nsource.token.subscribe(listener);\n\nconst signal = source.token.toAbortSignal();\n// Pass `signal` to APIs that accept AbortSignal.\n\nsource.cancel('Operation canceled by the user.');\nsource.token.unsubscribe(listener);\n```\n\nCanceled requests reject with `axios.CanceledError`. The legacy `axios.Cancel` export is an alias of `axios.CanceledError`, and cancellation errors include `__CANCEL__` for `axios.isCancel` compatibility.\n\n> Note: You can cancel several requests with the same cancel token or abort controller.\n> If a cancellation token is already cancelled when an Axios request starts, Axios cancels the request immediately without making a real request.\n\n> During the transition period, you can use both cancellation APIs, even for the same request:\n\n```js\nconst controller = new AbortController();\nconst source = axios.CancelToken.source();\n\naxios.get('/user/12345', {\n  cancelToken: source.token,\n  signal: controller.signal,\n});\n\ncontroller.abort();\nsource.cancel('Operation canceled by the user.');\n```\n\n## Using `application/x-www-form-urlencoded` format\n\n### URLSearchParams\n\nBy default, axios serializes JavaScript objects to `JSON`. To send data as [`application/x-www-form-urlencoded`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST), use the [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) API. It works in most browsers and in [Node](https://nodejs.org/api/url.html#url_class_urlsearchparams) v10 and later.\n\n```js\nconst params = new URLSearchParams({ foo: 'bar' });\nparams.append('extraparam', 'value');\naxios.post('/foo', params);\n```\n\n### Query string (older browsers)\n\nFor very old browsers, use a [polyfill](https://github.com/WebReflection/url-search-params) and make sure it patches the global environment.\n\nAlternatively, you can encode data using the [`qs`](https://github.com/ljharb/qs) library:\n\n```js\nconst qs = require('qs');\naxios.post('/foo', qs.stringify({ bar: 123 }));\n```\n\nWith ES modules:\n\n```js\nimport qs from 'qs';\nconst data = { bar: 123 };\nconst options = {\n  method: 'POST',\n  headers: { 'content-type': 'application/x-www-form-urlencoded' },\n  data: qs.stringify(data),\n  url,\n};\naxios(options);\n```\n\n### Older Node.js versions\n\nFor older Node.js engines, use the [`querystring`](https://nodejs.org/api/querystring.html) module:\n\n```js\nconst querystring = require('querystring');\naxios.post('https://something.com/', querystring.stringify({ foo: 'bar' }));\n```\n\nYou can also use the [`qs`](https://github.com/ljharb/qs) library.\n\n> Note: The `qs` library is preferable if you need to stringify nested objects, as the `querystring` method has [known issues](https://github.com/nodejs/node-v0.x-archive/issues/1665) with that use case.\n\n### Automatic serialization to URLSearchParams\n\nAxios automatically serializes the data object to urlencoded format if the content-type header is set to \"application/x-www-form-urlencoded\".\n\n```js\nconst data = {\n  x: 1,\n  arr: [1, 2, 3],\n  arr2: [1, [2], 3],\n  users: [\n    { name: 'Peter', surname: 'Griffin' },\n    { name: 'Thomas', surname: 'Anderson' },\n  ],\n};\n\nawait axios.postForm('https://postman-echo.com/post', data, {\n  headers: { 'content-type': 'application/x-www-form-urlencoded' },\n});\n```\n\nThe server receives these fields:\n\n```js\n  {\n    x: '1',\n    'arr[]': [ '1', '2', '3' ],\n    'arr2[0]': '1',\n    'arr2[1][0]': '2',\n    'arr2[2]': '3',\n    'arr3[]': [ '1', '2', '3' ],\n    'users[0][name]': 'Peter',\n    'users[0][surname]': 'griffin',\n    'users[1][name]': 'Thomas',\n    'users[1][surname]': 'Anderson'\n  }\n```\n\nIf your backend body parser, such as `body-parser` for `express.js`, supports nested object decoding, the server receives the same object structure:\n\n```js\nconst app = express();\n\napp.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies\n\napp.post('/', function (req, res, next) {\n  // echo body as JSON\n  res.send(JSON.stringify(req.body));\n});\n\nserver = app.listen(3000);\n```\n\n## Using `multipart/form-data` format\n\n### FormData\n\nTo send data as `multipart/form-data`, pass a FormData instance as the payload.\nYou do not need to set the `Content-Type` header. Axios detects it from the payload type.\nFor browser, web worker, and React Native `FormData`, leave `Content-Type` unset so the runtime can add the multipart boundary.\n\n```js\nconst formData = new FormData();\nformData.append('foo', 'bar');\n\naxios.post('https://httpbin.org/post', formData);\n```\n\nIn node.js, use the [`form-data`](https://github.com/form-data/form-data) library:\n\n```js\nconst FormData = require('form-data');\n\nconst form = new FormData();\nform.append('my_field', 'my value');\nform.append('my_buffer', Buffer.alloc(10));\nform.append('my_file', fs.createReadStream('/foo/bar.jpg'));\n\naxios.post('https://example.com', form);\n```\n\nIn node.js, when a `FormData` object provides `getHeaders()`, axios copies all returned headers by default for v1 compatibility. If the `FormData` object is custom or not fully trusted, set `formDataHeaderPolicy: 'content-only'` to copy only `Content-Type` and `Content-Length`, and set any other request headers explicitly with the request `headers` config.\n\n### Automatic serialization to FormData\n\nSince `v0.27.0`, Axios can serialize an object to FormData if the request `Content-Type`\nheader is set to `multipart/form-data`.\n\nThis request submits data as FormData in browsers and Node.js:\n\n```js\nimport axios from 'axios';\n\naxios\n  .post(\n    'https://httpbin.org/post',\n    { x: 1 },\n    {\n      headers: {\n        'Content-Type': 'multipart/form-data',\n      },\n    }\n  )\n  .then(({ data }) => console.log(data));\n```\n\nThe Node.js build uses the [`form-data`](https://github.com/form-data/form-data) polyfill by default.\n\nYou can override the FormData class with the `env.FormData` config option, but most applications do not need this:\n\n```js\nconst axios = require('axios');\nvar FormData = require('form-data');\n\naxios\n  .post(\n    'https://httpbin.org/post',\n    { x: 1, buf: Buffer.alloc(10) },\n    {\n      headers: {\n        'Content-Type': 'multipart/form-data',\n      },\n    }\n  )\n  .then(({ data }) => console.log(data));\n```\n\nThe Axios FormData serializer supports these special endings:\n\n- `{}` - serialize the value with JSON.stringify\n- `[]` - unwrap the array-like object as separate fields with the same key\n\n> Note: Arrays and FileList objects are unwrapped by default.\n\nFormData serializer supports additional options via `config.formSerializer: object` property to handle rare cases:\n\n- `visitor: Function` - user-defined visitor function that Axios calls recursively to serialize the data object\n  to a `FormData` object by following custom rules.\n\n- `dots: boolean = false` - use dot notation instead of brackets to serialize arrays and objects;\n\n- `metaTokens: boolean = true` - add the special ending (e.g `user{}: '{\"name\": \"John\"}'`) in the FormData key.\n  A backend body parser can use this meta-information to parse the value as JSON.\n\n- `indexes: null|false|true = false` - controls how Axios adds indexes to unwrapped keys of `flat` array-like objects.\n  - `null` - don't add brackets (`arr: 1`, `arr: 2`, `arr: 3`)\n  - `false`(default) - add empty brackets (`arr[]: 1`, `arr[]: 2`, `arr[]: 3`)\n  - `true` - add brackets with indexes (`arr[0]: 1`, `arr[1]: 2`, `arr[2]: 3`)\n- `maxDepth: number = 100` - maximum object nesting depth the serializer will recurse into. If the\n  input object exceeds this depth, an `AxiosError` with `code: 'ERR_FORM_DATA_DEPTH_EXCEEDED'` is\n  thrown instead of overflowing the call stack. This protects server applications from DoS\n  attacks via deeply nested payloads. Set to `Infinity` to disable the limit and restore pre-fix behaviour.\n- `Blob: typeof Blob` - Blob constructor used when converting ArrayBuffer-like values for spec-compliant\n  `FormData`. Override it only for runtimes that provide a compatible `Blob` constructor under a\n  different binding.\n\n```js\n// Raise the limit for a schema that genuinely nests deeper than 100 levels:\naxios.postForm('/api', data, { formSerializer: { maxDepth: 200 } });\n\n// Same protection applies to params serialization:\naxios.get('/api', { params: data, paramsSerializer: { maxDepth: 200 } });\n```\n\nGiven this object:\n\n```js\nconst obj = {\n  x: 1,\n  arr: [1, 2, 3],\n  arr2: [1, [2], 3],\n  users: [\n    { name: 'Peter', surname: 'Griffin' },\n    { name: 'Thomas', surname: 'Anderson' },\n  ],\n  'obj2{}': [{ x: 1 }],\n};\n```\n\nThe Axios serializer appends these fields:\n\n```js\nconst formData = new FormData();\nformData.append('x', '1');\nformData.append('arr[]', '1');\nformData.append('arr[]', '2');\nformData.append('arr[]', '3');\nformData.append('arr2[0]', '1');\nformData.append('arr2[1][0]', '2');\nformData.append('arr2[2]', '3');\nformData.append('users[0][name]', 'Peter');\nformData.append('users[0][surname]', 'Griffin');\nformData.append('users[1][name]', 'Thomas');\nformData.append('users[1][surname]', 'Anderson');\nformData.append('obj2{}', '[{\"x\":1}]');\n```\n\nAxios supports `postForm`, `putForm`, and `patchForm` as shortcuts for the matching HTTP methods with the `Content-Type` header preset to `multipart/form-data`.\n\n## Posting files\n\nSubmit a single file:\n\n```js\nawait axios.postForm('https://httpbin.org/post', {\n  myVar: 'foo',\n  file: document.querySelector('#fileInput').files[0],\n});\n```\n\nor multiple files as `multipart/form-data`:\n\n```js\nawait axios.postForm('https://httpbin.org/post', {\n  'files[]': document.querySelector('#fileInput').files,\n});\n```\n\n`FileList` object can be passed directly:\n\n```js\nawait axios.postForm('https://httpbin.org/post', document.querySelector('#fileInput').files);\n```\n\nAxios sends all files with the same field name: `files[]`.\n\n## HTML form posting (browser)\n\nPass an HTML Form element as a payload to submit it as `multipart/form-data` content.\n\n```js\nawait axios.postForm('https://httpbin.org/post', document.querySelector('#htmlForm'));\n```\n\n`FormData` and `HTMLForm` objects can also be posted as `JSON` by explicitly setting the `Content-Type` header to `application/json`:\n\n```js\nawait axios.post('https://httpbin.org/post', document.querySelector('#htmlForm'), {\n  headers: {\n    'Content-Type': 'application/json',\n  },\n});\n```\n\nFor example, the Form\n\n```html\n<form id=\"form\">\n  <input type=\"text\" name=\"foo\" value=\"1\" />\n  <input type=\"text\" name=\"deep.prop\" value=\"2\" />\n  <input type=\"text\" name=\"deep prop spaced\" value=\"3\" />\n  <input type=\"text\" name=\"baz\" value=\"4\" />\n  <input type=\"text\" name=\"baz\" value=\"5\" />\n\n  <select name=\"user.age\">\n    <option value=\"value1\">Value 1</option>\n    <option value=\"value2\" selected>Value 2</option>\n    <option value=\"value3\">Value 3</option>\n  </select>\n\n  <input type=\"submit\" value=\"Save\" />\n</form>\n```\n\nsubmits this JSON object:\n\n```js\n{\n  \"foo\": \"1\",\n  \"deep\": {\n    \"prop\": {\n      \"spaced\": \"3\"\n    }\n  },\n  \"baz\": [\n    \"4\",\n    \"5\"\n  ],\n  \"user\": {\n    \"age\": \"value2\"\n  }\n}\n```\n\nSending `Blobs`/`Files` as JSON (`base64`) is not currently supported.\n\n## Progress capturing\n\nAxios can capture request upload and download progress in browsers and Node.js.\nProgress events are limited to `3` times per second.\n\n```js\nawait axios.post(url, data, {\n  onUploadProgress: function (axiosProgressEvent) {\n    /*{\n      loaded: number;\n      total?: number;\n      progress?: number; // in range [0..1]\n      bytes: number; // how many bytes have been transferred since the last trigger (delta)\n      estimated?: number; // estimated time in seconds\n      rate?: number; // upload speed in bytes\n      upload: true; // upload sign\n    }*/\n  },\n\n  onDownloadProgress: function (axiosProgressEvent) {\n    /*{\n      loaded: number;\n      total?: number;\n      progress?: number;\n      bytes: number;\n      estimated?: number;\n      rate?: number; // download speed in bytes\n      download: true; // download sign\n    }*/\n  },\n});\n```\n\nYou can also track stream upload/download progress in node.js:\n\n```js\nconst { data } = await axios.post(SERVER_URL, readableStream, {\n  onUploadProgress: ({ progress }) => {\n    console.log((progress * 100).toFixed(2));\n  },\n\n  headers: {\n    'Content-Length': contentLength,\n  },\n\n  maxRedirects: 0, // avoid buffering the entire stream\n});\n```\n\n> Note:\n> Capturing FormData upload progress is not currently supported in node.js environments.\n\n> Warning:\n> Set `maxRedirects: 0` when uploading streams in node.js.\n> The follow-redirects package buffers the entire stream in RAM and does not follow the \"backpressure\" algorithm.\n\n## Rate limiting\n\nDownload and upload rate limits can only be set for the http adapter (node.js):\n\n```js\nconst { data } = await axios.post(LOCAL_SERVER_URL, myBuffer, {\n  onUploadProgress: ({ progress, rate }) => {\n    console.log(`Upload [${(progress * 100).toFixed(2)}%]: ${(rate / 1024).toFixed(2)}KB/s`);\n  },\n\n  maxRate: [100 * 1024], // 100KB/s limit\n});\n```\n\n## AxiosHeaders\n\nAxios includes an `AxiosHeaders` class for working with headers through a Map-like API.\nHTTP header names are case-insensitive, but Axios keeps the original header case for style and for servers that incorrectly depend on case.\nDirectly manipulating the headers object still works, but it is deprecated.\n\n### Working with headers\n\nAn `AxiosHeaders` instance can contain several internal value types that control setting and merging.\nAxios gets the final headers object with string values by calling `toJSON`.\n\n> Note: By JSON here we mean an object consisting only of string values intended to be sent over the network.\n\nThe header value can be one of the following types:\n\n- `string` - normal string value sent to the server\n- `null` - skip header when rendering to JSON\n- `false` - skip header when rendering to JSON. Also indicates that the `set` method must be called with `rewrite` set to `true`\n  to overwrite this value (Axios uses this internally to allow users to opt out of installing certain headers like `User-Agent` or `Content-Type`)\n- `undefined` - value is not set\n\n> Note: The header value is considered set if it is not equal to undefined.\n\nThe headers object is always initialized inside interceptors and transformers:\n\n```ts\naxios.interceptors.request.use((request: InternalAxiosRequestConfig) => {\n  request.headers.set('My-header', 'value');\n\n  request.headers.set({\n    'My-set-header1': 'my-set-value1',\n    'My-set-header2': 'my-set-value2',\n  });\n\n  request.headers.set('User-Agent', false); // prevent Axios from setting this header later\n\n  request.headers.setContentType('text/plain');\n\n  request.headers['My-set-header2'] = 'newValue'; // direct access is deprecated\n\n  return request;\n});\n```\n\nYou can iterate over an `AxiosHeaders` instance using a `for...of` statement:\n\n```js\nconst headers = new AxiosHeaders({\n  foo: '1',\n  bar: '2',\n  baz: '3',\n});\n\nfor (const [header, value] of headers) {\n  console.log(header, value);\n}\n\n// foo 1\n// bar 2\n// baz 3\n```\n\n### Preserving a specific header case\n\nHeader names are case-insensitive, but `AxiosHeaders` keeps the case of the first matching key it sees.\nIf you need a specific case for non-standard case-sensitive servers, define a case preset with `undefined` and then set the value later:\n\n```js\nconst api = axios.create();\n\napi.defaults.headers.common = {\n  'content-type': undefined,\n  accept: undefined,\n};\n\nawait api.put(url, data, {\n  headers: {\n    'Content-Type': 'application/octet-stream',\n    Accept: 'application/json',\n  },\n});\n```\n\nYou can also compose the same behavior with `AxiosHeaders.concat`:\n\n```js\nconst headers = axios.AxiosHeaders.concat(\n  { 'content-type': undefined },\n  { 'Content-Type': 'application/octet-stream' }\n);\n\nawait axios.put(url, data, { headers });\n```\n\n### new AxiosHeaders(headers?)\n\nConstructs a new `AxiosHeaders` instance.\n\n```\nconstructor(headers?: RawAxiosHeaders | AxiosHeaders | string);\n```\n\nIf the headers object is a string, Axios parses it as raw HTTP headers.\n\n```js\nconst headers = new AxiosHeaders(`\nHost: www.bing.com\nUser-Agent: curl/7.54.0\nAccept: */*`);\n\nconsole.log(headers);\n\n// Object [AxiosHeaders] {\n//   host: 'www.bing.com',\n//   'user-agent': 'curl/7.54.0',\n//   accept: '*/*'\n// }\n```\n\n### AxiosHeaders#set\n\n```ts\nset(headerName, value: Axios, rewrite?: boolean);\nset(headerName, value, rewrite?: (this: AxiosHeaders, value: string, name: string, headers: RawAxiosHeaders) => boolean);\nset(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean);\nset(headers?: Iterable<[string, AxiosHeaderValue]>, rewrite?: boolean);\n```\n\nThe `rewrite` argument controls the overwriting behavior:\n\n- `false` - do not overwrite if the header's value is set (is not `undefined`)\n- `undefined` (default) - overwrite the header unless its value is set to `false`\n- `true` - rewrite anyway\n\nThe option can also accept a user-defined function that determines whether to overwrite the value.\n\nEmpty or whitespace-only header names are ignored.\n\nIterable key/value pairs, such as a `Map`, are accepted:\n\n```js\nconst headers = new AxiosHeaders();\n\nheaders.set(\n  new Map([\n    ['X-Trace-Id', 'abc123'],\n    ['Accept', 'application/json'],\n  ])\n);\n```\n\nReturns `this`.\n\n### AxiosHeaders#get(header)\n\n```\n  get(headerName: string, matcher?: true | AxiosHeaderMatcher): AxiosHeaderValue;\n  get(headerName: string, parser: RegExp): RegExpExecArray | null;\n```\n\nReturns the internal value of the header. It can take an extra argument to parse the header's value with `RegExp.exec`,\nmatcher function or internal key-value parser.\n\n```ts\nconst headers = new AxiosHeaders({\n  'Content-Type': 'multipart/form-data; boundary=Asrf456BGe4h',\n});\n\nconsole.log(headers.get('Content-Type'));\n// multipart/form-data; boundary=Asrf456BGe4h\n\nconsole.log(headers.get('Content-Type', true)); // parse key-value pairs from a string separated with \\s,;= delimiters:\n// [Object: null prototype] {\n//   'multipart/form-data': undefined,\n//    boundary: 'Asrf456BGe4h'\n// }\n\nconsole.log(\n  headers.get('Content-Type', (value, name, headers) => {\n    return String(value).replace(/a/g, 'ZZZ');\n  })\n);\n// multipZZZrt/form-dZZZtZZZ; boundZZZry=Asrf456BGe4h\n\nconsole.log(headers.get('Content-Type', /boundary=(\\w+)/)?.[0]);\n// boundary=Asrf456BGe4h\n```\n\nReturns the value of the header.\n\n### AxiosHeaders#has(header, matcher?)\n\n```\nhas(header: string, matcher?: AxiosHeaderMatcher): boolean;\n```\n\nReturns `true` if the header is set (has no `undefined` value).\n\n### AxiosHeaders#delete(header, matcher?)\n\n```\ndelete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean;\n```\n\nReturns `true` if at least one header has been removed.\n\n### AxiosHeaders#clear(matcher?)\n\n```\nclear(matcher?: AxiosHeaderMatcher): boolean;\n```\n\nRemoves all headers.\nUnlike the `delete` method matcher, this optional matcher matches the header name rather than the value.\n\n```ts\nconst headers = new AxiosHeaders({\n  foo: '1',\n  'x-foo': '2',\n  'x-bar': '3',\n});\n\nconsole.log(headers.clear(/^x-/)); // true\n\nconsole.log(headers.toJSON()); // [Object: null prototype] { foo: '1' }\n```\n\nReturns `true` if at least one header has been cleared.\n\n### AxiosHeaders#normalize(format);\n\nIf the headers object was changed directly, it can have duplicates with the same name but in different cases.\nThis method normalizes the headers object by combining duplicate keys into one.\nAxios uses this method internally after calling each interceptor.\nSet `format` to true for converting header names to lowercase and capitalizing the initial letters (`cOntEnt-type` => `Content-Type`)\n\n```js\nconst headers = new AxiosHeaders({\n  foo: '1',\n});\n\nheaders.Foo = '2';\nheaders.FOO = '3';\n\nconsole.log(headers.toJSON()); // [Object: null prototype] { foo: '1', Foo: '2', FOO: '3' }\nconsole.log(headers.normalize().toJSON()); // [Object: null prototype] { foo: '3' }\nconsole.log(headers.normalize(true).toJSON()); // [Object: null prototype] { Foo: '3' }\n```\n\nReturns `this`.\n\n### AxiosHeaders#concat(...targets)\n\n```\nconcat(...targets: Array<AxiosHeaders | RawAxiosHeaders | string | undefined | null>): AxiosHeaders;\n```\n\nMerges the instance with targets into a new `AxiosHeaders` instance. If the target is a string, Axios parses it as raw HTTP headers.\n\nReturns a new `AxiosHeaders` instance.\n\n### AxiosHeaders#toJSON(asStrings?)\n\n```\ntoJSON(asStrings: true): Record<string, string>;\ntoJSON(asStrings?: false): Record<string, string | string[]>;\n```\n\nResolves all internal header values into a new null prototype object.\nSet `asStrings` to true to resolve arrays as a string containing all elements, separated by commas.\n\n### AxiosHeaders#toString()\n\n```\ntoString(): string;\n```\n\nReturns the headers as a CRLF-free HTTP header block, one `name: value` pair per line.\n\n### AxiosHeaders.from(thing?)\n\n```\nfrom(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders;\n```\n\nReturns a new `AxiosHeaders` instance created from the raw headers passed in,\nor returns the given headers object if it's already an `AxiosHeaders` instance.\n\n### AxiosHeaders.concat(...targets)\n\n```\nconcat(...targets: Array<AxiosHeaders | RawAxiosHeaders | string | undefined | null>): AxiosHeaders;\n```\n\nReturns a new `AxiosHeaders` instance created by merging the target objects.\n\n### Shortcuts\n\nThe following shortcuts are available:\n\n- `setContentType`, `getContentType`, `hasContentType`\n\n- `setContentLength`, `getContentLength`, `hasContentLength`\n\n- `setAccept`, `getAccept`, `hasAccept`\n\n- `setUserAgent`, `getUserAgent`, `hasUserAgent`\n\n- `setContentEncoding`, `getContentEncoding`, `hasContentEncoding`\n\n## Fetch adapter\n\nAxios introduced the fetch adapter in `v1.7.0`. By default, Axios uses it when the `xhr` and `http` adapters are not available in the build or not supported by the environment.\nTo use it by default, select it explicitly:\n\n```js\nconst { data } = axios.get(url, {\n  adapter: 'fetch', // by default ['xhr', 'http', 'fetch']\n});\n```\n\nYou can create a separate instance for this:\n\n```js\nconst fetchAxios = axios.create({\n  adapter: 'fetch',\n});\n\nconst { data } = fetchAxios.get(url);\n```\n\nThe adapter supports the same features as the `xhr` adapter, including upload and download progress capturing.\nIt also supports response types such as `stream` and `formdata` when the environment supports them.\n\nWhen `auth` is omitted, the fetch adapter can read HTTP Basic auth credentials from the request URL, for example `https://user:pass@example.com`. Percent-encoded URL credentials are decoded before the `Authorization` header is generated, and `auth` takes precedence over URL-embedded credentials.\n\n### Custom fetch\n\nSince `v1.12.0`, you can configure the fetch adapter to use a custom fetch API instead of environment globals.\nPass a custom `fetch` function, `Request`, and `Response` constructors through `env` config.\nThis helps in custom environments and app frameworks.\n\nWhen using a custom fetch, you may also need to set custom `Request` and `Response` constructors. If you do not set them, Axios uses the global objects.\nIf your custom fetch API does not provide these objects and the globals are incompatible with it, pass `null` to disable them inside the fetch adapter.\n\n> Note: Setting `Request` and `Response` to `null` prevents the fetch adapter from capturing upload and download progress.\n\nBasic example:\n\n```js\nimport customFetchFunction from 'customFetchModule';\n\nconst instance = axios.create({\n  adapter: 'fetch',\n  onDownloadProgress(e) {\n    console.log('downloadProgress', e);\n  },\n  env: {\n    fetch: customFetchFunction,\n    Request: null, // undefined -> use the global constructor\n    Response: null,\n  },\n});\n```\n\n#### Using with Tauri\n\nA minimal example of setting up Axios for use in a [Tauri](https://tauri.app/plugin/http-client/) app with a platform fetch function that ignores CORS policy for requests.\n\n```js\nimport { fetch } from '@tauri-apps/plugin-http';\nimport axios from 'axios';\n\nconst instance = axios.create({\n  adapter: 'fetch',\n  onDownloadProgress(e) {\n    console.log('downloadProgress', e);\n  },\n  env: {\n    fetch,\n  },\n});\n\nconst { data } = await instance.get('https://google.com');\n```\n\n#### Using with SvelteKit\n\n[SvelteKit](https://svelte.dev/docs/kit/web-standards#Fetch-APIs) uses a custom fetch function for server rendering in `load` functions. It also uses relative paths, which are incompatible with the standard URL API. Configure Axios to use SvelteKit's custom fetch API:\n\n```js\nexport async function load({ fetch }) {\n  const { data: post } = await axios.get('https://jsonplaceholder.typicode.com/posts/1', {\n    adapter: 'fetch',\n    env: {\n      fetch,\n      Request: null,\n      Response: null,\n    },\n  });\n\n  return { post };\n}\n```\n\n#### HTTP/2 support\n\nAxios supports HTTP/2 through the Node.js `http` adapter, introduced in v1.13.0.\n\nSupport depends on the runtime environment. Axios relies on Node.js APIs, so HTTP/2 works in supported Node.js versions but may not work in other environments such as Bun or Deno.\n\nOptions like `httpVersion` and `http2Options` are adapter-specific and may not behave the same way in every environment.\n\nNote: HTTP/2 redirects are currently not supported by the HTTP/2 adapter.\n\n```js\nconst form = new FormData();\n\nform.append('foo', '123');\n\nconst { data, headers, status } = await axios.post('https://httpbin.org/post', form, {\n  onUploadProgress(e) {\n    console.log('upload progress', e);\n  },\n  onDownloadProgress(e) {\n    console.log('download progress', e);\n  },\n  responseType: 'arraybuffer',\n});\n```\n\n## Semver\n\nAxios follows [semver](https://semver.org/) since `v1.0.0`.\n\n## Promises\n\naxios depends on a native ES6 Promise implementation to be [supported](https://caniuse.com/promises).\nIf your environment doesn't support ES6 Promises, you can [polyfill](https://github.com/jakearchibald/es6-promise).\n\n## TypeScript\n\naxios includes [TypeScript](https://typescriptlang.org) definitions and a type guard for axios errors.\n\n```typescript\nlet user: User = null;\ntry {\n  const { data } = await axios.get('/user?ID=12345');\n  user = data.userDetails;\n} catch (error) {\n  if (axios.isAxiosError(error)) {\n    handleAxiosError(error);\n  } else {\n    handleUnexpectedError(error);\n  }\n}\n```\n\nUse `axios.isCancel<T>()` to narrow cancellation errors to `CanceledError<T>`:\n\n```typescript\nconst controller = new AbortController();\n\ntry {\n  await axios.get<User>('/user?ID=12345', { signal: controller.signal });\n} catch (error) {\n  if (axios.isCancel<User>(error)) {\n    handleCancellation(error);\n  }\n}\n```\n\nBecause axios publishes an ESM default export and a CJS `module.exports`, TypeScript has a few caveats.\nThe recommended setting is `\"moduleResolution\": \"node16\"`, which is implied by `\"module\": \"node16\"`. This requires TypeScript 4.7 or greater.\nIf you use ESM, your settings should be fine.\nIf you compile TypeScript to CJS and can't use `\"moduleResolution\": \"node 16\"`, enable `esModuleInterop`.\nIf you use TypeScript to type check CJS JavaScript code, your only option is to use `\"moduleResolution\": \"node16\"`.\n\nYou can also create a custom instance with typed interceptors:\n\n```typescript\nimport axios, { AxiosInstance, InternalAxiosRequestConfig } from 'axios';\n\nconst apiClient: AxiosInstance = axios.create({\n  baseURL: 'https://api.example.com',\n  timeout: 10000,\n});\n\napiClient.interceptors.request.use((config: InternalAxiosRequestConfig) => {\n  // Add auth token\n  return config;\n});\n```\n\n## Online one-click setup\n\nYou can use Gitpod, a free online IDE for open source projects, to contribute or run the examples online.\n\n[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/axios/axios/blob/main/examples/server.js)\n\n## Contributing\n\n### Local setup\n\nAs a supply-chain hardening measure, this repository ships a project-level `.npmrc` that sets `ignore-scripts=true`. This blocks npm lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency when you run `npm install` or `npm ci` inside the repo. See [THREATMODEL.md](./THREATMODEL.md) (threat T-S2) for the rationale.\n\nOne consequence: the repository's own `prepare` hook (which installs Husky's git hooks) will **not** run automatically. After your first install, enable the git hooks manually:\n\n```bash\nnpm ci\nnpm rebuild husky && npx husky\n```\n\nRun those two commands once per fresh checkout. You do **not** need to re-run them after every subsequent `npm install`.\n\nDo not remove `ignore-scripts=true` from `.npmrc` to \"fix\" this. That reopens the lifecycle-script attack surface for every other package in the tree. All CI workflows already invoke npm with `--ignore-scripts`, so local behaviour matches CI.\n\n## Resources\n\n- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)\n- [Ecosystem](https://github.com/axios/axios/blob/v1.x/ECOSYSTEM.md)\n- [Contributing Guide](https://github.com/axios/axios/blob/v1.x/CONTRIBUTING.md)\n- [Code of Conduct](https://github.com/axios/axios/blob/v1.x/CODE_OF_CONDUCT.md)\n\n## Credits\n\naxios is heavily inspired by the [$http service](https://docs.angularjs.org/api/ng/service/$http) in [AngularJS](https://angularjs.org/). It provides a standalone `$http`-like service for use outside AngularJS.\n\n## License\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n\n\n# THREATMODEL.md\n# Axios threat model\n\nThis document describes the threat model for axios: a library used at runtime by millions of applications, and an open-source project with a build pipeline, release infrastructure, and human maintainers.\n\nIt is for maintainers, security researchers, and downstream consumers doing supply chain due diligence. If you find a gap, open a security advisory rather than a public issue.\n\n---\n\n## 1. Scope and methodology\n\nWe model two distinct systems:\n\n| System             | What is being protected                     | Who attacks it                                                    |\n| ------------------ | ------------------------------------------- | ----------------------------------------------------------------- |\n| Runtime            | Applications that `import axios`            | Malicious servers, network attackers, malicious application input |\n| Project / SDLC     | The integrity of what gets published to npm | Supply-chain attackers, phishers, malicious contributors          |\n\nFor each system, we list assets, trust boundaries, threat actors, and threats, rated by likelihood x impact. When mitigations exist in the codebase, we cite the file. When they do not, we say so.\n\nThe runtime model is general by design. axios is a transport library and cannot know what its callers consider sensitive. The project model is specific and actionable.\n\n---\n\n## 2. Runtime threat model\n\n### 2.1 System overview\n\n```\n  ┌─────────────────┐\n  │  Application    │  ← trusted: writes the config, owns the secrets\n  │  (caller code)  │\n  └────────┬────────┘\n           │ axios(config)\n  ┌────────▼────────┐\n  │  Interceptors   │  ← caller-supplied code, runs in-process\n  ├─────────────────┤\n  │  Config merge   │  ← lib/core/mergeConfig.js\n  │  URL build      │  ← lib/core/buildFullPath.js, lib/helpers/buildURL.js\n  │  Header build   │  ← lib/core/AxiosHeaders.js\n  ├─────────────────┤\n  │  Adapter        │  ← http.js / xhr.js / fetch.js\n  └────────┬────────┘\n           │\n  ═════════▼═════════  ← TRUST BOUNDARY (network)\n           │\n  ┌────────▼────────┐\n  │  Proxy (opt.)   │  ← partially trusted (sees plaintext if HTTP)\n  └────────┬────────┘\n  ┌────────▼────────┐\n  │  Origin server  │  ← UNTRUSTED in the general case\n  │  + redirects    │\n  └─────────────────┘\n```\n\n### 2.2 Assets\n\n| Asset                          | Why it matters                                               |\n| ------------------------------ | ------------------------------------------------------------ |\n| Credentials in transit         | `config.auth`, `Authorization` headers, cookies, XSRF tokens |\n| Request/response bodies        | May contain PII, business secrets                            |\n| The caller's process integrity | Prototype pollution can lead to RCE in some downstream gadgets |\n| The caller's internal network  | SSRF can pivot through the host running axios                |\n| Availability                   | Decompression bombs, redirect loops, slow-loris responses    |\n\n### 2.3 Trust boundaries\n\n1. Caller to axios. The caller is fully trusted. Anything the caller passes in `config` is assumed intentional. axios does not defend against a malicious caller; that is a non-goal.\n2. axios to network. Everything past the socket is untrusted: response status, headers, body, redirect `Location`, proxy responses.\n3. axios to environment variables. `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` are read by `proxy-from-env`. An attacker who controls the environment can redirect all traffic. This is treated as trusted because it has the same privilege as the process, but it is a relevant pivot in container-escape and CI scenarios.\n4. Caller-supplied hooks to axios internals. Interceptors, `transformRequest`, `transformResponse`, `paramsSerializer`, `beforeRedirect`, and custom adapters run with full process privilege. axios does not sandbox them.\n\n### 2.4 Threat actors\n\n| Actor                         | Capability                                                                                                           |\n| ----------------------------- | -------------------------------------------------------------------------------------------------------------------- |\n| Malicious server              | Controls every byte of the response. Most common.                                                                    |\n| On-path network attacker      | MITM. Mitigated by TLS unless the caller disabled validation.                                                        |\n| Malicious redirect target     | A trusted server redirects to an attacker. The attacker sees whatever axios forwards.                                |\n| Application user              | Controls part of the request (e.g. a URL path segment, a query param, a header value) via the calling application.   |\n\n### 2.5 Threats\n\n> Severity = Likelihood x Impact, rated for a typical server-side deployment. Browser deployments inherit the browser's same-origin policy and are generally lower risk for SSRF and credential leakage.\n\n---\n\n#### T-R1: SSRF via caller-controlled URL\n\n|                   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |\n| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Application interpolates user input into `config.url` or `config.baseURL`. Attacker supplies `http://169.254.169.254/`, `http://localhost:6379/`, `file://`, `gopher://`, etc.                                                                                                                                                                                                                                                                                                                 |\n| **Likelihood**    | **High.** This is the #1 real-world axios misuse pattern.                                                                                                                                                                                                                                                                                                                                                                                                                                      |\n| **Impact**        | **High.** Cloud metadata theft, internal service access.                                                                                                                                                                                                                                                                                                                                                                                                                                       |\n| **In scope?**     | **Partially.** axios cannot know which URLs the caller intends to allow.                                                                                                                                                                                                                                                                                                                                                                                                                       |\n| **Mitigations**   | • `allowAbsoluteUrls: false` prevents a relative `url` from overriding `baseURL` (`lib/core/buildFullPath.js`). Defaults to `true` for back-compat. <br>• The HTTP adapter only speaks `http:`/`https:`/`file:`/`data:` (Node) or `http:`/`https:`/`file:`/`blob:`/`url:`/`data:` (browser); exotic schemes like `gopher:` are rejected (`lib/platform/node/index.js`, `lib/platform/browser/index.js`). <br>• No built-in host allowlist. Callers must validate destinations themselves. |\n| **Residual risk** | Substantial. This is documented as caller responsibility.                                                                                                                                                                                                                                                                                                                                                                                                                                      |\n\n---\n\n#### T-R2: Credential leakage on cross-origin redirect\n\n|                   |                                                                                                                                                                                                                                                                                                                                                                                                                                          |\n| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Caller sets `Authorization: Bearer …` and requests `https://api.trusted.com/x`. Server responds `302 Location: https://evil.com/`. Does the bearer token go to evil.com?                                                                                                                                                                                                                                                                 |\n| **Likelihood**    | Medium                                                                                                                                                                                                                                                                                                                                                                                                                                   |\n| **Impact**        | High (full credential theft)                                                                                                                                                                                                                                                                                                                                                                                                             |\n| **Mitigations**   | • Node adapter delegates to `follow-redirects@^1.16.0`, which strips `Authorization`, `Cookie`, and `Proxy-Authorization` on cross-host redirects and on HTTPS→HTTP downgrades. <br>• `sensitiveHeaders` lets callers list custom secret-bearing headers (for example `X-API-Key`) that axios strips on cross-origin redirects. <br>• `maxRedirects` defaults to 5; set to `0` to handle redirects manually. <br>• `beforeRedirect` callback allows custom inspection. <br>• Browser adapters (XHR/fetch) delegate to the browser, which applies its own cross-origin credential rules. |\n| **Residual risk** | Low for standard credential headers and configured custom secret headers. We inherit `follow-redirects`' security posture - it is a critical transitive dependency and its CVEs are our CVEs. Callers must list any custom secret headers they want stripped.                                                                                                                                                                                                                                                                                                                 |\n\n---\n\n#### T-R3: Header injection (CRLF)\n\n|                   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |\n| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Application puts user input into a header value: `headers: { 'X-User': req.query.name }`. Attacker supplies `foo\\r\\nX-Injected: bar\\r\\n\\r\\n<body>`. A related surface is multipart per-part headers: attacker-controlled `blob.type` or `blob.name` flowing into the multipart body.                                                                                                                                                                                                                              |\n| **Likelihood**    | Low                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |\n| **Impact**        | Medium to High (request smuggling, response splitting, multipart parser confusion)                                                                                                                                                                                                                                                                                                                                                                                                                          |\n| **Mitigations**   | • `lib/core/AxiosHeaders.js` rejects header values containing `\\r` or `\\n`, and validates header names against an RFC-7230-shaped charset. Node's own `http` module also rejects these. <br>• `lib/helpers/formDataToStream.js` strips CRLF from `value.type` and percent-encodes CRLF/`\"` in `value.name` via `escapeName()` before interpolating them into per-part headers (GHSA-445q-vr5w-6q77). Node's `http` module does not defend here; multipart injection is in body bytes, not request headers. |\n| **Residual risk** | Very low for HTTP headers (defense in depth: axios + Node). Low for multipart body headers (single layer of defense; regressions here would be silent).                                                                                                                                                                                                                                                                                                                                                         |\n\n---\n\n#### T-R4: Prototype pollution, write side (polluting response / merge into a target object)\n\n|                   |                                                                                                                                                                                                                                                                                                                                                                                                   |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Server returns `{\"__proto__\": {\"isAdmin\": true}}`. If axios merged this into an object naively, every `{}` in the process would gain `.isAdmin`.                                                                                                                                                                                                                                                  |\n| **Likelihood**    | Low (requires a downstream gadget to be exploitable)                                                                                                                                                                                                                                                                                                                                              |\n| **Impact**        | High (process-wide state corruption, sometimes RCE)                                                                                                                                                                                                                                                                                                                                               |\n| **Mitigations**   | • `JSON.parse` itself does not pollute (it creates own-properties named `__proto__`, not prototype links). <br>• Internal merge paths filter dangerous keys: `lib/utils.js` and `lib/core/mergeConfig.js` filter `__proto__` / `constructor` / `prototype`; `lib/helpers/formDataToJSON.js` filters `__proto__`. <br>• These were added in response to past advisories. A regression here is a P0. |\n| **Residual risk** | Low, but this is an area of active attacker interest. New merge helpers must go through the same filtering.                                                                                                                                                                                                                                                                                       |\n\n---\n\n#### T-R4b: Prototype pollution, read-side gadgets (polluted `Object.prototype` drives axios behavior)\n\n|                   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |\n| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | A _different_ library in the caller's dependency tree pollutes `Object.prototype` (e.g. `Object.prototype.validateStatus = () => true`). axios code that reads a config property through the prototype chain then picks up the attacker's value and executes the associated behavior. Each reachable property is a distinct **gadget**: `validateStatus` (bypass HTTP error handling), `parseReviver` (silently tamper JSON response bodies), `transport` / `httpAgent` / `lookup` (MITM / intercept), `withXSRFToken` (leak XSRF token cross-origin), `transformResponse` (response replacement), and so on.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |\n| **Likelihood**    | Low to Medium (requires a polluted prototype somewhere in the process, historically common).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |\n| **Impact**        | High. Arbitrary behavior change across every axios call (auth bypass, response tampering, credential leakage). Unlike T-R4, this does not require axios itself to pollute; any polluted process is enough.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |\n| **Mitigations**   | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen: <br>• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63). <br>• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23). <br>• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set). <br>• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `\"false\"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c). <br>• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). |\n| **Residual risk** | Low, but the surface is every config property read. Any new code path that reads `config.foo` / `this.foo` / destructures from a merged config must use a `hasOwnProp` guard. The non-goal that axios does not defend a caller with a polluted prototype is narrower than it sounds. The pollution typically comes from a transitive dependency, not from the caller's own intent, and the above mitigations neutralize the reachable gadgets even when the prototype is polluted.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |\n\n---\n\n#### T-R5: Decompression bomb\n\n|                   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Server sends `Content-Encoding: gzip` with a 10 KB body that decompresses to 10 GB.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |\n| **Likelihood**    | Low                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |\n| **Impact**        | Medium (DoS, OOM kill of the calling process)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |\n| **Mitigations**   | • `maxContentLength` bounds the decompressed response size in the Node adapter (`lib/adapters/http.js`), enforced chunk-by-chunk on the decompressed stream for both buffered and `responseType: 'stream'` responses (stream path fixed in GHSA-vf2m-468p-8v99). <br>• `maxBodyLength` bounds the request side, including when `maxRedirects === 0` (previously bypassed). <br>• Both default to `-1` (unlimited). Callers handling untrusted servers should set these. The README carries a top-level \"security notice\" call-out and `docs/pages/misc/security.md` documents the exact mitigation snippet in all four locales. <br>• Decompression uses Node's `zlib`, which streams. Memory is bounded by the limit, not the full expansion. |\n| **Residual risk** | Medium when limits are not configured. The defaults favor compatibility over safety; the reasoning is that tightening the default would silently break every legitimate download larger than whatever cap were chosen.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |\n\n---\n\n#### T-R6: TLS validation bypass\n\n|                   |                                                                                                                                   |\n| ----------------- | --------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Caller passes `httpsAgent: new https.Agent({ rejectUnauthorized: false })` to \"fix\" a certificate error in dev, ships it to prod. |\n| **Likelihood**    | Medium (very common copy-paste anti-pattern)                                                                                      |\n| **Impact**        | High (silent MITM)                                                                                                                |\n| **In scope?**     | **No.** axios delegates TLS entirely to Node's `https` module / the browser. We do not inspect or warn on agent configuration.    |\n| **Mitigations**   | None at the axios layer. Documentation responsibility only.                                                                       |\n| **Residual risk** | High, but explicitly out of scope. This is caller misconfiguration, not an axios vulnerability.                                   |\n\n---\n\n#### T-R7: XSRF token sent cross-origin\n\n|                   |                                                                                                                                                                                       |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Browser deployment. `xsrfCookieName` is set; attacker tricks the app into requesting `https://evil.com` and the XSRF token cookie value is attached as a header.                      |\n| **Likelihood**    | Low                                                                                                                                                                                   |\n| **Impact**        | Medium                                                                                                                                                                                |\n| **Mitigations**   | `lib/helpers/resolveConfig.js` only attaches the XSRF header when `isURLSameOrigin()` passes (or when `withXSRFToken` is explicitly forced). This was the fix for **CVE-2023-45857**. |\n| **Residual risk** | Low. The same-origin check uses the WHATWG `URL` parser (`lib/helpers/isURLSameOrigin.js`), which is robust against parser-differential attacks.                                      |\n\n---\n\n#### T-R8: Sensitive data in error objects\n\n|                   |                                                                                                                                                                                                                                                                                                    |\n| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Request fails. `AxiosError` includes `config`, which includes `config.auth`, `config.headers.Authorization`, `config.httpsAgent` (with embedded client cert/key). Caller logs the error, exposing secrets in logs.                                                                                  |\n| **Likelihood**    | **High**                                                                                                                                                                                                                                                                                           |\n| **Impact**        | Medium to High                                                                                                                                                                                                                                                                                     |\n| **Mitigations**   | `AxiosError.toJSON()` (`lib/core/AxiosError.js`) produces a reduced view, but the live error object still carries the full config by reference.                                                                                                                                                    |\n| **Residual risk** | Medium. Callers using structured loggers that walk object graphs (Winston, Pino with serializers, Sentry) will capture credentials unless they configure redaction. This is a documented risk, not a vulnerability, but it is the most common way axios users leak secrets in practice. |\n\n---\n\n#### T-R9: Proxy environment variable hijack\n\n|                   |                                                                                                                                                                                                                                                                                                                                                                                                  |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| **Description**   | Attacker controls the process environment (compromised CI step, container escape, `.env` injection) and sets `HTTPS_PROXY=http://evil.com:8080`. All axios traffic is now MITM'd.                                                                                                                                                                                                                |\n| **Likelihood**    | Low (requires prior foothold)                                                                                                                                                                                                                                                                                                                                                                    |\n| **Impact**        | High                                                                                                                                                                                                                                                                                                                                                                                             |\n| **Mitigations**   | • `config.proxy: false` disables environment-based proxy detection entirely. <br>• `NO_PROXY` is honored (`lib/helpers/shouldBypassProxy.js`), with recent hardening for CIDR ranges, IPv6 literals, and wildcard patterns to close parser-differential edge cases. <br>• HTTPS through any proxy uses CONNECT tunneling via `https-proxy-agent` so the origin's cert is validated end-to-end and the proxy sees only SNI, never the URL, headers, or body. `Proxy-Authorization` is sent on the CONNECT request only, never on the wrapped TLS-protected request. |\n| **Residual risk** | Low for HTTPS. High for plain HTTP: the proxy sees and can modify everything.                                                                                                                                                                                                                                                                                                                   |\n\n---\n\n#### T-R10: Malicious interceptor / adapter\n\n|                   |                                                                                                                                                        |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| **Description**   | Caller installs a third-party \"axios plugin\" from npm that registers an interceptor exfiltrating every `Authorization` header.                         |\n| **Likelihood**    | Low to Medium                                                                                                                                          |\n| **Impact**        | High                                                                                                                                                   |\n| **In scope?**     | **No.** Interceptors are caller-supplied code running in the caller's process. axios provides the hook; vetting what goes into it is the caller's job. |\n| **Residual risk** | Out of scope, but worth documenting: there is no meaningful difference between `axios.interceptors.request.use(evil)` and `require('evil')`.           |\n\n---\n\n#### T-R11: Form-data recursion DoS (deeply nested input)\n\n|                   |                                                                                                                                                                                                                                                                                                                                                                             |\n| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**   | Caller passes untrusted object input as request `data` in a context that serializes to `multipart/form-data` or `application/x-www-form-urlencoded`. A pathological input with thousands of nesting levels causes `lib/helpers/toFormData.js` to recurse until stack overflow or the process is killed.                                                                     |\n| **Likelihood**    | Low (requires the caller to serialize attacker-controlled object input without validation)                                                                                                                                                                                                                                                                                  |\n| **Impact**        | Medium (DoS, stack overflow / process termination)                                                                                                                                                                                                                                                                                                                          |\n| **Mitigations**   | • `formSerializer.maxDepth` caps recursion depth; default is 100, can be set to `Infinity` to disable. <br>• Exceeding the cap throws `AxiosError` with code `ERR_FORM_DATA_DEPTH_EXCEEDED` rather than crashing the process. <br>• Documented per locale in `docs/pages/advanced/multipart-form-data-format.md` and `docs/pages/advanced/x-www-form-urlencoded-format.md`. |\n| **Residual risk** | Low when callers leave the default in place. Setting `maxDepth: Infinity` reintroduces the risk.                                                                                                                                                                                                                                                                            |\n\n---\n\n### 2.6 Explicit non-goals (runtime)\n\naxios will not:\n\n- Sandbox or validate caller-supplied functions (interceptors, transforms, adapters, serializers).\n- Validate that `config.url` points somewhere \"safe.\" We don't know what safe means for your application.\n- Warn when TLS validation is disabled via a custom agent.\n- Redact `config` from thrown errors. The caller may legitimately need it for retry logic.\n- Defend against a fully compromised caller process (e.g. attacker-controlled code running inside the caller). For the narrower case of a polluted `Object.prototype` arriving via a transitive dependency, axios does defend the reachable config-read gadgets (see T-R4b), but any new config-read path must continue to use `hasOwnProp` guards to stay on this side of the line.\n- Defend against monkey-patched JavaScript or Node.js runtime APIs (`Object.keys`, `http.request`, `ClientRequest.prototype.setHeader`, `fetch`, etc.). If attacker-controlled code is already running in the same process, it can observe or alter requests below axios and this is outside axios' security boundary.\n\n---\n\n## 3. Project / supply chain threat model\n\nThis model protects what gets published as `axios` on npm. A successful attack here compromises every downstream consumer at once. Given axios' install base, this is the higher-risk half of the document.\n\n### 3.1 System overview\n\n```\n  ┌──────────────────┐    ┌──────────────────┐    ┌──────────────────┐\n  │  Maintainer's    │    │  Contributor's   │    │  GitHub.com      │\n  │  workstation     │    │  fork + PR       │    │  (source of      │\n  │                  │    │                  │    │   truth)         │\n  │  ! npm token?    │    │  untrusted code  │    │                  │\n  │  ! SSH keys      │    │                  │    │                  │\n  │  ! GPG keys      │    │                  │    │                  │\n  └────────┬─────────┘    └────────┬─────────┘    └────────▲─────────┘\n           │                       │                       │\n           │  git push             │  PR                   │\n           └───────────────────────┴───────────────────────┘\n                                                           │\n                                              tag push: v1.x.y\n                                                           │\n                                            ┌──────────────▼─────────────┐\n                                            │  GitHub Actions            │\n                                            │  .github/workflows/        │\n                                            │    publish.yml             │\n                                            │                            │\n                                            │  • npm ci --ignore-scripts │\n                                            │  • npm run build           │\n                                            │  • npm publish             │\n                                            │      --provenance          │\n                                            │                            │\n                                            │  OIDC to npm (no token)    │\n                                            └──────────────┬─────────────┘\n                                                           │\n                                            ═══════════════▼═══════════════\n                                                  registry.npmjs.org\n                                                    axios@1.x.y\n                                                  + provenance attestation\n```\n\n### 3.2 Assets\n\n| Asset                                 | Compromise means…                                                                                                                        |\n| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |\n| **The npm `axios` package name**      | Attacker can publish malware as `axios@1.x.y+1`. Game over for the ecosystem.                                                            |\n| **npm publish capability**            | Whether via token, OIDC trust, or account takeover.                                                                                      |\n| **GitHub `axios/axios` write access** | Attacker can push a tag, which triggers publish. Or modify `publish.yml` itself.                                                         |\n| **Maintainer GitHub accounts**        | Transitively grants the above.                                                                                                           |\n| **Maintainer workstation secrets**    | SSH keys (GitHub push), `~/.npmrc` token if present (direct publish), GPG keys (signed commits), cloud creds (lateral movement).         |\n| **Build determinism**                 | If `dist/` doesn't match `lib/`, a backdoor can hide in the minified bundle.                                                             |\n| **Runtime dependency integrity**      | `follow-redirects`, `form-data`, `proxy-from-env`, `https-proxy-agent` ship inside every axios install.                                  |\n\n### 3.3 Trust boundaries\n\n1. Contributor PRs to main branch. PRs from forks are untrusted. CI runs them, but `pull_request` workflows have no access to secrets and use a read-only `GITHUB_TOKEN`.\n2. Main branch to release tag. Pushing to `v1.x` does not publish. Only pushing a `v1.*.*` tag does. Tag push requires write access.\n3. GitHub Actions to npm. This boundary is crossed via OIDC (`id-token: write` to npm trusted publisher). The repo has no long-lived `NPM_TOKEN` secret.\n4. Maintainer workstation to everything else. This is the softest boundary. A maintainer's laptop is a high-value, low-assurance environment. See §3.5.\n\n### 3.4 Threat actors\n\n| Actor                                           | Capability                                                                                                       | Motivation                              |\n| ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | --------------------------------------- |\n| Drive-by contributor                            | Open a PR. No secrets, no write.                                                                                 | Sneak a backdoor past review.           |\n| Compromised dependency                          | Attempt to run code on `npm install` via lifecycle scripts. Blocked on maintainer workstations (project `.npmrc`) and in CI (`--ignore-scripts` on every job). Residual execution path: plugin code under `npm run build` / `test` / `lint`. | Steal tokens, inject into build.        |\n| Phisher                                         | Send convincing emails/DMs. No technical access.                                                                 | Maintainer GitHub/npm credential theft. |\n| Compromised maintainer account                  | Full write. Can push tags. Can edit workflows.                                                                   | Direct publish of malware.              |\n| GitHub / npm insider or platform compromise     | Out of scope. We trust the platforms.                                                                            | -                                       |\n\n### 3.5 Threats\n\n---\n\n#### T-S1: Malicious code in a contributor PR\n\n|                 |                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description** | Attacker opens a PR with a subtle backdoor: an obfuscated payload in a test fixture, a Unicode homoglyph in a comparison, or a malicious `rollup` plugin in the config.                                                                                                                                                                                                                                                                                                |\n| **Likelihood**  | **High** (attempts are constant on high-profile repos)                                                                                                                                                                                                                                                                                                                                                                                                                 |\n| **Impact**      | Critical, _if_ it lands                                                                                                                                                                                                                                                                                                                                                                                                                                                |\n| **Mitigations** | • Mandatory review before merge. <br>• `pull_request` workflows run with no secrets and a read-only token, so a malicious test cannot exfiltrate anything from CI. <br>• `pull_request_target` is not used because it would grant secrets to fork code. <br>• `zizmor` lints workflow files for known-dangerous patterns. <br>• Branch protection on `v1.x`. <br>• Package, lockfile, and GitHub Actions update PRs are maintainer/bot-only; outside-collaborator PRs for those updates are closed. <br>• Path-scoped `.github/CODEOWNERS` flags sensitive paths explicitly: runtime source (`/lib/`, `/index.*`), build/release infrastructure (`rollup.config.js`, `package.json`, `package-lock.json`, `.npmrc`), CI automation (`.github/workflows/`, `.github/dependabot.yml`, `CODEOWNERS` itself), and security-critical docs (`THREATMODEL.md`, `SECURITY.md`). Changes to these paths surface the scoped ownership rule in the PR review UI distinct from the catch-all. The audit trail shows that the PR touched a sensitive path.                                                                                                               |\n| **Gaps**        | • Review is human and fallible. Obfuscated changes to `dist/` (if checked in) or to large test fixtures are hard to spot. <br>• No automated diffing of `lib/` to `dist/` to catch build-output tampering. <br>Single-maintainer constraint: with `@jasonsaayman` as sole owner on every scoped path, CODEOWNERS cannot enforce a second reviewer. Two-person review on sensitive paths remains unavailable until a co-maintainer is added. Path-scoping is pre-staged for that event. |\n\n---\n\n#### T-S2: Compromised dev dependency steals maintainer keys\n\n> Historically the weakest link. The project-level `.npmrc` and hardware-backed maintainer keys materially improve it, but build-tool plugin execution (Rollup/Babel/Vitest/ESLint) is still the top residual investment area. `ignore-scripts` does not affect those tools, and they run whenever a maintainer builds or tests.\n\n|                            |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |\n| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description**            | One of the ~45 direct dev dependencies, or one of their thousands of transitive dependencies, is compromised (maintainer account takeover, expired domain re-registration, the usual). It ships a `postinstall` script that reads `~/.npmrc`, `~/.ssh/id_*`, `~/.config/gh/hosts.yml`, `~/.aws/credentials`, `~/.gnupg/` and POSTs them to an attacker. <br><br>The next time a maintainer runs `npm install` on their workstation, the script runs as the maintainer's user, with full filesystem access. No exploit needed. This is npm working as designed. |\n| **Likelihood**             | Medium and rising. This exact pattern has hit `event-stream`, `ua-parser-js`, `coa`, `rc`, `node-ipc`, `@solana/web3.js`, the Ledger connect-kit, the 2024 polyfill.io incident, and dozens more. axios' dev tree includes Babel, Rollup, Gulp, ESLint, Vitest, and Playwright, each pulling hundreds of transitives. The attack surface is enormous and refreshes on every `npm install`.                                                                                                                                                                                   |\n| **Impact**                 | Critical. A stolen npm token with publish rights means direct malware publish. A stolen SSH key with GitHub push rights means tag push, then publish via CI. Either path ends the same way.                                                                                                                                                                                                                                                                                                                                                                                |\n| **Current mitigations**    | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build. <br>• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal. <br>• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update. <br>• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency. <br>• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README \"Contributing / Local setup\" section.                                                                     |\n| **Gaps: workstation**      | `ignore-scripts=true` neutralizes the lifecycle-script path, but it does not neutralize build-time code execution. A malicious Rollup / Babel / Terser / ESLint / Vitest plugin still runs when a maintainer executes `npm run build` / `npm test` / `npm run lint`. Those are not lifecycle scripts; they are tools the maintainer explicitly invoked. <br><br>The lockfile pins which packages install, but if one of those pinned packages was already malicious when the lock was generated, or the maintainer runs `npm update` / `npm install <new-pkg>` without re-setting `ignore-scripts`, fresh lifecycle scripts can land. <br><br>The development environment still has full read access to every credential the maintainer's user can read once a build tool runs. Isolation (devcontainer / VM) remains the strongest control.                                                                                                                                      |\n\nMitigations adopted and recommended. Adopted items are enforced via the repo; others depend on per-maintainer discipline.\n\n1. Don't keep a publish-capable npm token on your workstation.\n   Publishing happens via GitHub Actions OIDC. There is no workflow that requires `npm publish` from a laptop. If `~/.npmrc` has a token, it should be read-only or scoped to unrelated packages. If there is nothing to steal, this attack path is defanged.\n\n2. Run `npm install` / `npm ci` with `--ignore-scripts` locally. Adopted: project ships a `.npmrc` with `ignore-scripts=true`.\n   All `npm install` / `npm ci` runs in a contributor or maintainer checkout skip lifecycle scripts by default. To set up git hooks after install, run the one trusted script manually:\n\n   ```\n   npm rebuild husky && npx husky\n   ```\n\n   The minor inconvenience of manually running known-good post-install steps is the price of not running thousands of unknown ones. Contributors adding a new dev dependency must not override this flag.\n\n3. Develop in an isolated environment.\n   A devcontainer, VM, or sandbox profile that does not have:\n   - `~/.ssh/` mounted (use a separate deploy key or SSH agent forwarding only when pushing)\n   - `~/.npmrc` with publish tokens\n   - `~/.config/gh/` with a `repo`-scoped GitHub token\n   - `~/.aws/`, `~/.config/gcloud/`, etc.\n\n   The dev environment should be able to read/write the repo working tree and reach the network for tests. Nothing else.\n\n4. Use hardware-backed keys for GitHub. Adopted project-wide.\n   All maintainers use FIDO2/WebAuthn for GitHub auth and `sk-ssh-ed25519@openssh.com` for git push. A stolen `~/.ssh/id_ed25519_sk` is useless without the physical key. This converts \"steal a file\" into \"steal a file and a physical object.\" Each maintainer should keep a backup key registered and stored separately.\n\n5. Audit lockfile diffs on dependency-update PRs as carefully as code.\n   A 4000-line `package-lock.json` diff hides a lot. Tooling: `npm diff`, `lockfile-lint`, Socket.dev's PR integration. Pay particular attention to new packages with install scripts (`hasInstallScript: true` in the lockfile).\n\n6. Don't add dev dependencies casually.\n   Each one is a recurring trust decision delegated to a stranger. Prefer tools that can run via `npx` on demand (not in `node_modules`) or that are already in the tree.\n\n---\n\n#### T-S3: Phishing to maintainer account takeover\n\n|                 |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description** | Maintainer receives a convincing email: <br>• \"npm security alert: your axios package has been flagged, log in to verify ownership\" links to a fake npm login; password + TOTP are captured and replayed in real time. <br>• \"GitHub: @axios has been added to a new organization, review access\" links to a fake GitHub OAuth consent screen; the attacker app gets `repo` scope. <br>• Social: a \"recruiter\" asks the maintainer to clone and `npm install` a \"take-home assignment\" repo. <br><br>npm and GitHub credentials for axios maintainers have been specifically targeted by these campaigns in the past. This is not theoretical. |\n| **Likelihood**  | High. These campaigns are continuous.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |\n| **Impact**      | Critical. GitHub account to push tag to publish. npm account to publish directly.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |\n| **Mitigations** | • npm 2FA is required for publish on the `axios` package. <br>• OIDC publishing means there is no maintainer npm session involved in a normal release. This narrows the attack to GitHub. <br>• All maintainers authenticate to GitHub with hardware-backed WebAuthn/passkeys (FIDO2 security keys / platform authenticators). Origin-bound credentials cannot be relayed by a phishing proxy (Evilginx, Modlishka). TOTP alone is not permitted for maintainer accounts. <br>• Git push uses `sk-ssh-ed25519@openssh.com` hardware-resident SSH keys where supported. A stolen key file is useless without the physical device.                                                                                                                           |\n| **Gaps**        | • Enforcement is per-account policy, not verifiable from the repo itself. Onboarding/offboarding checklist should confirm hardware-key status. <br>• Incident-response runbook is documented in §3.7 and needs periodic rehearsal to stay useful. <br>• Each maintainer should register at least 2 hardware keys (primary + backup stored separately) to avoid lockout-driven fallback to weaker recovery methods.                                                                                                                                                                                                                                                                                                                                                             |\n\n---\n\n#### T-S4: Compromised runtime dependency\n\n|                 |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| **Description** | `follow-redirects`, `form-data`, `proxy-from-env`, or `https-proxy-agent` ships a malicious version. Unlike T-S2, this code ends up in the published axios bundle / runtime rather than being limited to maintainer machines. Every axios consumer runs it.                                                                                                                                                                                                                                                                                                                                                                                            |\n| **Likelihood**  | Low (only 4 deps; all are mature, narrowly-scoped, and watched)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |\n| **Impact**      | Critical                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |\n| **Mitigations** | • Three runtime deps total, minimal by design. <br>• `^` ranges in `package.json` mean consumers may get newer patch versions than the lockfile pins. This is intentional, because consumers get security fixes, but it also means a malicious patch release of `follow-redirects` propagates without an axios release. <br>• `follow-redirects` is security-conscious and well-maintained; we track its advisories closely (multiple past axios releases were just `follow-redirects` bumps). <br>• Dependabot is configured (`.github/dependabot.yml`) for both npm and GitHub Actions, running weekly with grouped updates for production and development dependencies. The 7-day cooldown stays in place unless a critical vulnerability requires a maintainer-led manual update. |\n| **Gaps**        | • No vendoring/inlining considered. The deps are small enough that vendoring is plausible, but it would forfeit upstream security fixes. Current judgment: not worth it.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |\n\n---\n\n#### T-S5: Build-output tampering (`dist/` != `lib/`)\n\n|                 |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |\n| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description** | The published tarball contains a `dist/axios.min.js` that does not match what `rollup` would produce from `lib/`. Nobody reads minified bundles. A backdoor here is invisible to source review. <br><br>Vectors: a malicious dev-dep Rollup/Babel/Terser plugin injects code at build time (T-S2 applied to CI), or a maintainer with a compromised workstation accidentally publishes a tampered local build.                                                                                                                                                                                                                                                                                                        |\n| **Likelihood**  | Low                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |\n| **Impact**      | Critical                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |\n| **Mitigations** | • Builds run only in CI as part of `publish.yml`, from a clean `npm ci --ignore-scripts` checkout. There is no \"publish from laptop\" path. <br>• `--ignore-scripts` means a malicious dev dependency cannot tamper with `node_modules` before the build, but it can still tamper during the build if it is a Rollup/Babel plugin. Those run as part of `npm run build`, not as lifecycle scripts. <br>• npm provenance (`--provenance`) cryptographically attests which workflow on which commit produced the tarball. Consumers can verify with `npm audit signatures`. This proves the build ran in GitHub Actions on a known SHA. It does not prove the build is correct, only that it is traceable. |\n| **Gaps**        | • The build is not currently reproducible in the strict sense. A third party cannot independently rebuild and get a byte-identical `dist/`. Timestamps, plugin ordering, and minifier nondeterminism would need to be locked down. <br>• `.github/workflows/verify-build-reproducibility.yml` performs a two-pass build-and-diff on PRs that touch build-related paths (`lib/**`, `rollup.config.js`, `package.json`, `package-lock.json`, and the workflow itself). It is currently non-blocking (`continue-on-error: true`). It surfaces divergence in the CI summary so reproducibility regressions are visible, without gating merges until the build is deterministic. Once divergence is eliminated, remove `continue-on-error` to promote this to a hard gate. |\n\n---\n\n#### T-S6: Workflow file tampering\n\n|                 |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description** | Attacker with write access (or a merged PR that was not reviewed carefully) modifies `.github/workflows/publish.yml` to `curl` the OIDC token somewhere, or to add a step that patches `dist/` after the build.                                                                                                                                                                                                                                                                                                                           |\n| **Likelihood**  | Low                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |\n| **Impact**      | Critical                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |\n| **Mitigations** | • All actions are pinned to full commit SHAs, not tags: `actions/checkout@de0fac...`, not `@v6`. A compromised action tag can't silently change behavior. <br>• `permissions:` are minimal (`contents: read`, `id-token: write`). <br>• `persist-credentials: false` on checkout, so the build steps cannot push back to the repo. <br>• `zizmor` lints workflows on every PR and push to `v1.x` (`.github/workflows/zizmor.yml`); results surface as GitHub code-scanning alerts via the `security-events: write` permission on that job. This job must remain in the required-checks set on `v1.x` branch protection for the mitigation to be binding. <br>• The `npm-publish` GitHub Environment can require designated reviewers before the job runs; a tampered workflow still pauses for human approval. <br>• CODEOWNERS carries a path-scoped rule for `/.github/workflows/` and `/.github/CODEOWNERS` itself, so workflow and ownership changes surface in the review UI as touching a scoped path rather than being folded into the default approval. |\n| **Gaps**        | • Single-maintainer constraint (see T-S1): with one owner, the path-scoped rule cannot enforce a second reviewer on workflow changes. The rule surfaces the sensitivity but does not block single-maintainer approval. Closing this requires adding a co-maintainer.                                                                                                                                                                                                          |\n\n---\n\n#### T-S7: Tag confusion / replay\n\n|                 |                                                                                                                                                                                                                                                                                                      |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Description** | Attacker with write access force-pushes an existing tag to point at a malicious commit, or pushes `v1.99.99` so that a release is published out of band.                                                                                                                                             |\n| **Likelihood**  | Low (requires write access; assumed compromised at that point)                                                                                                                                                                                                                                      |\n| **Impact**      | High                                                                                                                                                                                                                                                                                                 |\n| **Mitigations** | • npm rejects re-publishing an existing version. Re-tagging cannot overwrite the published `1.15.0`. <br>• Provenance attestation records the commit SHA the tag pointed to at publish time, which is forensically verifiable. Consumers can confirm with `npm audit signatures axios` (documented in SECURITY.md). <br>• Tag protection rules: repository setting must forbid tag deletion and force-push for the `v1.*.*` pattern. This is a GitHub UI setting (Settings > Tags > rulesets), not file-based; enforcement is auditable via the Rulesets REST API. |\n| **Gaps**        | A new malicious version (`v1.x.x`) is still publishable by anyone with tag-push rights. This collapses back into T-S3 (account security).                                                                                                                                                           |\n\n---\n\n#### T-S8: Typosquatting / dependency confusion\n\n|                 |                                                                                                                                                                                                                                                                                      |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| **Description** | Attacker publishes `axois`, `axios-http`, `@axios/core`, etc., and waits for typos. Or publishes a package shadowing an internal name used in a consumer's monorepo.                                                                                                                 |\n| **Likelihood**  | High (these packages already exist)                                                                                                                                                                                                                                                  |\n| **Impact**      | Medium. Affects confused consumers, not axios itself                                                                                                                                                                                                                                  |\n| **In scope?**   | Mostly out of scope; the axios project cannot police the npm namespace.                                                                                                                                                                                                              |\n| **Mitigations** | • npm has typosquat detection at publish time (imperfect). <br>• The `@axios/` npm scope is not owned by the project. `@axios/anything` can be registered by anyone. This is a gap, not a mitigation. <br>• Provenance gives consumers a way to verify they got the real thing. |\n\n---\n\n### 3.6 Summary: project risk posture\n\n| Threat                       | Likelihood | Impact       | Current Posture | Priority Gap                                                          |\n| ---------------------------- | ---------- | ------------ | --------------- | --------------------------------------------------------------------- |\n| T-S1 Malicious PR            | High       | Critical     | Good         | Second maintainer to enable two-person review on scoped paths         |\n| T-S2 Dev-dep steals keys     | Medium     | Critical     | Partial      | Isolated dev environment (devcontainer/VM); no publish tokens on workstations. Lifecycle scripts now blocked via project `.npmrc`, but build-tool plugins still execute |\n| T-S3 Phishing                | High       | Critical     | Good         | Document phish-response runbook; require registered backup hardware key |\n| T-S4 Runtime dep compromise  | Low        | Critical     | Good         | -                                                                     |\n| T-S5 Build tampering         | Low        | Critical     | Adequate     | Eliminate build non-determinism, then promote reproducibility check to blocking |\n| T-S6 Workflow tampering      | Low        | Critical     | Good         | Second maintainer (two-person review) for `/.github/workflows/`       |\n| T-S7 Tag replay              | Low        | High         | Good         | -                                                                     |\n| T-S8 Typosquat               | High       | Medium       | Out of scope | -                                                                     |\n\nThe top remaining investment is T-S2 (dev-dependency compromise of maintainer workstations). Lifecycle-script execution is now blocked by the project-level `.npmrc`, and T-S3 phishing risk dropped materially once all maintainers moved to hardware-backed WebAuthn. Real-time credential relay no longer works. The residual T-S2 gap is build-tool plugin execution (Rollup/Babel/Vitest/ESLint), which `ignore-scripts` does not cover. Closing it requires running builds in an isolated environment without access to long-lived credentials.\n\n---\n\n### 3.7 Incident response runbook\n\nIf a maintainer suspects credential compromise (phish clicked, lost hardware key, unexpected tag/publish, leaked token in logs), execute the steps below in order. Speed matters more than completeness. A published malicious version affects every downstream consumer.\n\n#### 1. Contain, minutes 0 to 15\n\n- GitHub: revoke all active sessions (`https://github.com/settings/sessions`), revoke all OAuth/PAT tokens (`/settings/tokens`, `/settings/applications`), review authorized SSH keys and remove any unrecognised. If a PAT with `repo` or `admin:org` scope existed, assume leak.\n- npm: run `npm token list` and `npm token revoke <token>` for any publish-capable token. If no CLI access, revoke via `https://www.npmjs.com/settings/<user>/tokens`. Rotate npm password and force sign-out of all sessions.\n- Workstation: if a build/install ran malicious code, assume full-user compromise of the laptop. Unplug from trusted networks. Do not rely on AV; move to a clean machine for rotation steps.\n\n#### 2. Assess, minutes 15 to 60\n\n- Check `https://github.com/axios/axios/settings/security-log` and `https://github.com/<maintainer>/security/log` for unrecognised events (key adds, org changes, force-pushes, new tags).\n- Verify recent tags match intent: `git log --tags --oneline -n 20`. Compare with `https://www.npmjs.com/package/axios?activeTab=versions`.\n- For each recent publish, verify provenance: `npm audit signatures axios@<version>` and cross-check the `sourceCommit` in the provenance attestation against the tag's SHA. Divergence = investigate.\n- Review `~/.npmrc`, `~/.ssh/`, `~/.config/gh/hosts.yml`, `~/.gnupg/` for tampering and unexpected files.\n\n#### 3. Rotate, hour 1 to 4\n\n- Generate new SSH keys on clean hardware. Remove old keys from GitHub. If using `sk-ssh-ed25519@openssh.com`, register new hardware key first, then deregister the old one. Do not leave the account with zero registered keys.\n- Re-enrol WebAuthn authenticators (both primary and backup). Deregister lost/compromised authenticators.\n- Rotate GPG keys if signed commits are used; upload new key to GitHub.\n- Rotate any cloud credentials (`~/.aws/`, `~/.config/gcloud/`) and any tokens present on the compromised machine.\n\n#### 4. Notify, hour 1 onward\n\n- npm security: `security@npmjs.com`. Include package name, suspected versions, timeline.\n- GitHub security: `https://github.com/contact`, Security category. Request an investigation of the account.\n- Downstream: open a GitHub security advisory (`https://github.com/axios/axios/security/advisories/new`) as soon as a malicious version is confirmed published. Do not wait for a fix. Users need to pin away from the bad version.\n- Co-maintainers (when present): notify via out-of-band channel (phone/Signal), not through the compromised channel.\n\n#### 5. Unpublish / deprecate, hour 1 to 24\n\n- npm allows `npm unpublish <pkg>@<version>` within 72 hours of publish. After that, use `npm deprecate <pkg>@<version> \"<reason>\"` with a message pointing to the advisory.\n- Publish a patched version that bumps semver above the malicious one, so `^` consumers move forward automatically.\n\n#### 6. Post-mortem, within 1 week\n\n- Write up timeline: initial vector, dwell time, scope, mitigations applied.\n- Update this threat model if the incident reveals a gap not captured here.\n- File a PR if any mitigation can be codified (new CI check, new lint rule, new CODEOWNERS path).\n\nKeep this runbook current. A runbook no one has rehearsed is a document, not a control.\n\n---\n\n_This document describes intent and current understanding. It does not constitute a security guarantee. To report a gap in the model itself, use the same private advisory channel as for code vulnerabilities._\n"
  },
  "state": {
    "files": [
      ".gitignore",
      ".npmrc",
      ".prettierignore",
      ".prettierrc",
      "AGENTS.md",
      "CHANGELOG.md",
      "CLAUDE.md",
      "CODE_OF_CONDUCT.md",
      "COLLABORATOR_GUIDE.md",
      "CONTRIBUTING.md",
      "CONTRIBUTORS.md",
      "ECOSYSTEM.md",
      "LICENSE",
      "MIGRATION_GUIDE.md",
      "PRE_RELEASE_CHANGELOG.md",
      "PRE_RELEASE_DOCS.md",
      "README.md",
      "SECURITY.md",
      "THREATMODEL.md",
      "eslint.config.js",
      "gulpfile.js",
      "index.d.cts",
      "index.d.ts",
      "index.js",
      "package-lock.json",
      "package.json",
      "rollup.config.js",
      "tsconfig.json",
      "tslint.json",
      "vitest.config.js",
      "webpack.config.js"
    ],
    "isNodeProject": true,
    "packageManagers": [
      "npm"
    ],
    "ecosystems": []
  },
  "uninterceptedCommands": [],
  "events": [
    {
      "at": "6.1s",
      "kind": "DOC",
      "message": "Loaded 2 documentation files (depth ≤2, cap 6; external links disabled)."
    },
    {
      "at": "21.5s",
      "kind": "PROPOSAL",
      "command": "npm ci",
      "ruling": "LICENSED",
      "severity": "FRICTION",
      "cited_sentence": "After your first install, enable the git hooks manually:",
      "citation_file": "README.md",
      "readings": [
        "README.md explicitly shows `npm ci` as the first command in the local setup sequence.",
        "The state identifies this as a Node project using npm and includes `package-lock.json`.",
        "README.md states that `npm ci` runs with lifecycle scripts ignored by the project-level `.npmrc`."
      ],
      "reason": "The proposed command is explicitly shown in the repository's local setup instructions, and the project state confirms npm and a lockfile are present.",
      "bypassed": false,
      "cached": false,
      "executed": true,
      "message": "Greenhorn accepted this command; its isolated executor is the sole shell process."
    },
    {
      "at": "22.9s",
      "kind": "RESULT",
      "command": "npm ci",
      "message": "exit 1\nnpm error code EUSAGE\nnpm error\nnpm error `npm ci` can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync. Please update your lock file with `npm install` before continuing.\nnpm error\nnpm error Missing: conventional-commits-parser@6.4.0 from lock file\nnpm error\nnpm error Clean install a project\nnpm error\nnpm error Usage:\nnpm error npm ci\nnpm error\nnpm error Options:\nnpm error [--install-strategy <hoisted|nested|shallow|linked>] [--legacy-bundling]\nnpm error [--global-style] [--omit <dev|optional|peer> [--omit <dev|optional|peer> ...]]\nnpm error [--include <prod|dev|optional|peer> [--include <prod|dev|optional|peer> ...]]\nnpm error [--strict-peer-deps] [--foreground-scripts] [--ignore-scripts] [--no-audit]\nnpm error [--no-bin-links] [--no-fund] [--dry-run]\nnpm error [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]\nnpm error [-ws|--workspaces] [--include-workspace-root] [--install-links]\nnpm error\nnpm error aliases: clean-install, ic, install-clean, isntall-clean\nnpm error\nnpm error Run \"npm help ci\" for more info\nnpm notice\nnpm notice New major version of npm available! 10.9.8 -> 12.0.1\nnpm notice Changelog: https://github.com/npm/cli/releases/tag/v12.0.1\nnpm notice To update run: npm install -g npm@12.0.1\nnpm notice\nnpm error A complete log of this run can be found in: /root/.npm/_logs/2026-07-18T15_22_41_370Z-debug-0.log",
      "executed": true
    },
    {
      "at": "39.5s",
      "kind": "PROPOSAL",
      "command": "npm install",
      "ruling": "LICENSED",
      "severity": "FRICTION",
      "cited_sentence": "All `npm install` / `npm ci` runs in a contributor or maintainer checkout skip lifecycle scripts by default.",
      "citation_file": "README.md",
      "readings": [
        "The proposed command is explicitly covered by the repository's project-level `.npmrc` setting.",
        "Lifecycle scripts, including `prepare`, will not run automatically.",
        "Git hooks require the documented manual setup afterward."
      ],
      "reason": "`npm install` is explicitly documented and is licensed by the repository's default `ignore-scripts=true` configuration. It may require the documented manual Husky setup afterward, so the consequence is friction rather than a blocker.",
      "bypassed": false,
      "cached": false,
      "executed": true,
      "message": "Greenhorn accepted this command; its isolated executor is the sole shell process."
    },
    {
      "at": "57.4s",
      "kind": "RESULT",
      "command": "npm install",
      "message": "exit 0\nadded 653 packages, and audited 654 packages in 18s\n\n127 packages are looking for funding\n  run `npm fund` for details\n\nfound 0 vulnerabilities\n\nnpm warn deprecated git-raw-commits@5.0.1: Deprecated and no longer maintained. Use @conventional-changelog/git-client instead.",
      "executed": true
    },
    {
      "at": "73.6s",
      "kind": "PROPOSAL",
      "command": "npm ci",
      "ruling": "LICENSED",
      "severity": "FRICTION",
      "cited_sentence": "After your first install, enable the git hooks manually:",
      "citation_file": "README.md",
      "readings": [
        "README.md explicitly shows `npm ci` as the first command in the local setup sequence.",
        "The state identifies this as a Node project using npm and includes `package-lock.json`.",
        "README.md states that `npm ci` runs with lifecycle scripts ignored by the project-level `.npmrc`."
      ],
      "reason": "The proposed command is explicitly shown in the repository's local setup instructions, and the project state confirms npm and a lockfile are present.",
      "bypassed": false,
      "cached": true,
      "executed": true,
      "message": "Greenhorn accepted this command; its isolated executor is the sole shell process."
    },
    {
      "at": "80.3s",
      "kind": "RESULT",
      "command": "npm ci",
      "message": "exit 0\nadded 656 packages, and audited 657 packages in 6s\n\n128 packages are looking for funding\n  run `npm fund` for details\n\nfound 0 vulnerabilities\n\nnpm warn deprecated git-raw-commits@5.0.1: Deprecated and no longer maintained. Use @conventional-changelog/git-client instead.",
      "executed": true
    },
    {
      "at": "98.1s",
      "kind": "PROPOSAL",
      "command": "npm rebuild husky",
      "ruling": "LICENSED",
      "severity": "FRICTION",
      "cited_sentence": "npm rebuild husky && npx husky",
      "citation_file": "README.md",
      "readings": [
        "The proposed command is explicitly included as the first command in the documented setup sequence.",
        "The repository is an npm-managed Node project."
      ],
      "reason": "README.md explicitly instructs contributors to run `npm rebuild husky && npx husky` after installation, which unambiguously licenses `npm rebuild husky`.",
      "bypassed": false,
      "cached": false,
      "executed": true,
      "message": "Greenhorn accepted this command; its isolated executor is the sole shell process."
    },
    {
      "at": "98.4s",
      "kind": "RESULT",
      "command": "npm rebuild husky",
      "message": "exit 0\nrebuilt dependencies successfully",
      "executed": true
    },
    {
      "at": "111.8s",
      "kind": "HALT",
      "message": "I expected the documented two-command hook setup to be complete. `npm rebuild husky` exited 0, but README documents the remaining action only as the chained command `npm rebuild husky && npx husky`; it does not explicitly license `npx husky` as a standalone command, while the contract forbids chaining. The instruction that fails is: “The command must be the next ONE shell command explicitly licensed by the documentation. No … chaining.”"
    }
  ],
  "dockerfile": "# Deliberately small and inspectable: no project state, dotfiles, or cached package manager data.\nFROM ubuntu:24.04\n\nENV DEBIAN_FRONTEND=noninteractive\nRUN apt-get update \\\n && apt-get install -y --no-install-recommends ca-certificates curl git \\\n && curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \\\n && apt-get install -y --no-install-recommends nodejs \\\n && rm -rf /var/lib/apt/lists/* /root/.npm\n\nWORKDIR /workspace\nENTRYPOINT []\n",
  "turns": [
    {
      "id": 1,
      "provider": "codex",
      "status": "completed",
      "durationMs": 8856
    },
    {
      "id": 2,
      "provider": "codex",
      "status": "completed",
      "durationMs": 12030
    },
    {
      "id": 3,
      "provider": "codex",
      "status": "completed",
      "durationMs": 16272
    },
    {
      "id": 4,
      "provider": "codex",
      "status": "completed",
      "durationMs": 14232
    },
    {
      "id": 5,
      "provider": "codex",
      "status": "completed",
      "durationMs": 13454
    }
  ],
  "finishedAt": "2026-07-18T15:24:11.677Z",
  "fix": null
}
