CodeVetter
← All unpacks
CodeVetter · Repo Unpack evidence

axios/axios

Scanned commit 56a5f1acdc dated 2026-09-16 — last upstream commit. Generated by codevetter 1.12.0 on 2026-09-22.

github.com/axios/axios ↗ · 457 files · 2.7 MB

💎 Platinum sponsors We're passionate about making open source sustainable.

Deep analysis by claude-opus-5 via the claude CLI on 2026-09-22 (380s) — every claim below links to its cited source files.

Overview

axios is the promise-based HTTP client library for browsers and Node.js, shipped as ESM source in `lib/` and Rollup-built UMD/ESM/CJS bundles in `dist/`. Its distinguishing shape is a single request pipeline (`Axios._request` → interceptors → `dispatchRequest` → adapter) that fans out to three interchangeable adapters — XHR, Node HTTP/HTTP2, and Fetch — selected by capability probe rather than environment name. This particular fork/branch (v1.x at 1.20.0) is unusually security-hardened: config reads go through own-property guards (`utils.getSafeProp`, `utils.toSafeFlatObject`), merges produce null-prototype objects, and there is a 94KB `THREATMODEL.md` plus a 1600-line prototype-pollution test suite. It is consumed by application developers as a dependency, and its contributor surface is governed by `AGENTS.md` plus a pre-release changelog/docs staging workflow.

System map

The public ESM entry is `index.js`, which unwraps the default instance built by `lib/axios.js` and re-exports its statics as named exports; CJS consumers get the Rollup-built `dist/node/axios.cjs`. Domain logic lives in `lib/core/` (Axios class, dispatch, merge, headers, errors, interceptors), I/O in `lib/adapters/`, environment selection in `lib/platform/` (Node by default, browser via package.json `browser` aliasing), and generic utilities in `lib/helpers/`. There is no storage layer — the only persistent state is browser cookies read for XSRF (`lib/helpers/cookies.js`) and pooled HTTP/2 sessions (`lib/helpers/Http2Sessions.js`). Build is `gulp clear && rollup -c` producing five bundles; tests are Vitest with three projects (unit/browser/browser-headless) plus packed-tarball smoke and module suites. Deployment shape is an npm package published on `v1.*.*` tags with provenance.

All 14 system map claims →

Feature catalog

The user-facing surface is the axios instance API: a callable default export, per-method aliases generated onto `Axios.prototype`, interceptor managers, cancellation via both `CancelToken` and `AbortSignal`, and a large `AxiosRequestConfig` surface typed in `index.d.ts`/`index.d.cts`. Beyond the classic v1 surface this branch carries newer options: `httpVersion: 2`, `allowedSocketPaths`, `sensitiveHeaders`, `redact`, `formDataHeaderPolicy`, `parseReviver`, and `query` as a first-class HTTP method. Transport features include transparent gzip/deflate/br/zstd decompression, upload/download progress with rate throttling (`maxRate`), proxy handling with CIDR-aware `NO_PROXY` bypass, and `maxContentLength`/`maxBodyLength` enforcement on buffered *and* streamed bodies in all three adapters. Form-data handling is bidirectional: `toFormData`/`formToJSON` plus `formDataToStream` for Node uploads.

All 15 feature catalog claims →

Data flow

Input boundaries are the user config object (or URL string), instance defaults, and environment state (env proxy vars, `document.cookie`, platform globals). `mergeConfig` is the single state-materialization point: it emits a **null-prototype** object with `hasOwnProperty` restored as a non-enumerable own slot, skipping `__proto__`/`constructor`/`prototype` keys entirely. `dispatchRequest` re-flattens whatever interceptors handed back via `utils.toSafeFlatObject`, normalizes headers into `AxiosHeaders`, runs `transformRequest`, then hands off to the adapter. Adapters own the outbound byte boundary (header sanitization to byte strings, body size accounting, stream piping) and produce a raw `{data, status, statusText, headers, config, request}`, which flows back through `transformResponse`, `AxiosHeaders.from`, `settle`, and finally the response interceptor chain.

All 14 data flow claims →

Behavior traces

Three flows dominate: module load/instance creation, a Node GET through the HTTP adapter, and a browser POST through XHR with XSRF. A fourth worth tracing is cancellation, which has to unwind listeners at every stage. Interceptor ordering is the subtle part — request interceptors currently default to LIFO via the `legacyInterceptorReqResOrdering: true` transitional flag, and the whole chain has a synchronous fast path that bypasses Promise wrapping when every request interceptor declares `synchronous: true`.

All 14 behavior traces claims →

Testing signals

Vitest is the only runner for source tests, split into three projects; unit tests run in node, browser tests run under Playwright against chromium/firefox/webkit. Coverage of security behavior is unusually deep — `tests/unit/prototypePollution.test.js` is 1619 lines and `tests/unit/adapters/http.test.js` is 7252 lines, together ~39% of the 22.8k unit-test lines. Beyond the source tree there are four packed-tarball suites (CJS/ESM smoke via mocha/vitest, Bun via `bun test`, Deno via `deno task`) plus two TypeScript declaration suites pinned to different TS versions. The gaps are mostly at the edges: no coverage numbers or coverage gate is configured, the reproducibility workflow is explicitly non-blocking, and `sandbox/`, `examples/`, and `gulpfile.js` have no tests at all.

All 14 testing signals claims →

Risk map

This is a library whose entire job is attacker-adjacent I/O, and the code reflects that: nearly every security control is a hand-rolled invariant with a comment explaining the CVE or issue behind it, which means the blast radius of an innocuous-looking refactor is large. The highest-risk surfaces are `lib/adapters/http.js` (proxy/redirect/socketPath/decompression, 1490 lines, one function), `lib/core/mergeConfig.js` + `utils.toSafeFlatObject` (the prototype-pollution boundary), and `lib/helpers/resolveConfig.js` (XSRF cross-origin decision). Fragile coupling exists between the package.json `browser` alias map and any new Node-only import; adding one to a browser-reachable module silently ships `http2`/`zlib` into browser bundles. Legacy surface (`CancelToken`, `axios.Cancel`, `legacyInterceptorReqResOrdering`, `tslint.json`, `webpack.config.js`) is retained for compatibility and is easy to break inadvertently.

All 16 risk map claims →

Extension points

The intended extension seams are well-marked. Adapters plug in through `knownAdapters` or by passing a function/array to `config.adapter`; `config.transport` overrides the Node transport wholesale; `config.env.{fetch,Request,Response,FormData,Blob}` lets a runtime inject its own primitives. Data shaping extends through `transformRequest`/`transformResponse` arrays, `paramsSerializer`, `formSerializer`, and `parseReviver`. Cross-cutting behavior extends through interceptors (with `synchronous` and `runWhen` modifiers) and through `AxiosHeaders.accessor()` for new header shorthands. New error codes are added as UPPER_SNAKE constants on `AxiosError`, new behavior flags as `transitional` keys validated in `Axios._request`.

All 14 extension points claims →

Contributor handoff

Read `AGENTS.md` first — it is the canonical contributor contract and encodes rules that are not derivable from the code (pre-release changelog/docs staging, `ignore-scripts` safety, dependency policy, error-handling conventions). Then read `lib/core/Axios.js`, `lib/core/dispatchRequest.js`, `lib/core/mergeConfig.js`, and whichever adapter you're touching. The cheapest verification loop is `npm run test:vitest:unit -- tests/unit/<file>.test.js` plus `npx eslint lib/<file>.js`; a full build is only needed for packaging/type changes. The two traps that catch most newcomers are (1) editing `README.md`/`CHANGELOG.md` instead of `PRE_RELEASE_DOCS.md`/`PRE_RELEASE_CHANGELOG.md`, and (2) using ordinary property reads on config where the file uses `own()`/`getSafeProp`, which silently reopens a prototype-pollution hole with no test failure unless you add one.

All 15 contributor handoff claims →

Languages

LanguageFilesShare of source
JavaScript21688%
Markdown160docs/config
TypeScript2912%
JSON12docs/config
YAML10docs/config
HTML9docs/config
CSS1docs/config

Start reading here

Probable source entrypoint: index.js — inferred from the directory tree and manifest, not the upstream docs.

Source roots

lib/ (73 files)

Repository structure

Top-level pathFiles
tests/162
docs/155
lib/73
examples/17
.github/14
sandbox/3
.husky/1
scripts/1

Docs found: AGENTS.mdCLAUDE.mdCONTRIBUTING.mdREADME.mddocs/es/index.mddocs/es/pages/advanced/adapters.mddocs/es/pages/advanced/api-reference.mddocs/es/pages/advanced/authentication.mddocs/es/pages/advanced/cancellation.mddocs/es/pages/advanced/config-defaults.md

Package

package.json — axios v1.20.0, 43 declared dependencies.

@babel/core@babel/preset-env@commitlint/cli@commitlint/config-conventional@eslint/js@rollup/plugin-alias@rollup/plugin-babel@rollup/plugin-commonjs@rollup/plugin-json@rollup/plugin-node-resolve@rollup/plugin-terser@vitest/browser

CI & config entrypoints

Structural health signals

Average score 9.2/10 across 92 analyzed source files; 3 hotspots surfaced.

These are deterministic review leads — size, churn, and structural signals — not proof of a bug in this project.

Recent history