chore(deps): update dependency axios to v1.18.0 [security]#2073
Open
renovate[bot] wants to merge 1 commit into
Open
chore(deps): update dependency axios to v1.18.0 [security]#2073renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
1.17.0→1.18.0Axios: Prototype pollution auth subfields can inject Basic auth
GHSA-xj6q-8x83-jv6g
More information
Details
Summary
Axios versions after the
GHSA-q8qp-cvcw-x6jjfix 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 ownauthobject that omitsusernameorpassword, axios reads inheritedObject.prototype.usernameandObject.prototype.passwordvalues and uses them to construct an outboundAuthorization: Basic ...header.This 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 || {}.Impact
An attacker who can pollute
Object.prototype.usernameand/orObject.prototype.passwordcan influence the Basic auth header on affected axios requests that pass an empty or partial ownauthobject.The practical impact is outbound request tampering. The attacker can inject attacker-chosen Basic auth credentials, replace an existing
Authorizationheader because axios removes it whenauthis used, or cause downstream authorization failures.This 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.
Affected Functionality
Affected functionality:
lib/adapters/http.js.lib/helpers/resolveConfig.js.config.authis an own object butusernameand/orpasswordare absent own properties.Unaffected or not accepted as core impact:
authobject aftermergeConfig().auth.usernameandauth.passwordvalues.params/paramsSerializerafter the null-prototypemergeConfig()hardening.paramsSerializerfunctions 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.Technical Details
mergeConfig()returns a null-prototype top-level config object, which prevents top-level reads such asconfig.authfrom inheriting polluted values. However, nested plain objects returned byutils.merge()still haveObject.prototype.In
lib/adapters/http.js, axios correctly reads the top-levelauthvalue throughown('auth'), but then reads subfields directly:If the caller passes auth: {} and Object.prototype.username/password are polluted, those direct subfield reads walk the prototype chain.
The same pattern exists in
lib/helpers/resolveConfig.js:The fix should guard
usernameandpasswordwithutils.hasOwnProp, matching the proxy-auth pattern already used elsewhere.Proof of Concept of Attack
Safe local PoC against published
axios@1.16.1:Expected output:
{ "url": "/api", "authorization": "Basic dmljdGltLXVzZXI6dmljdGltLXBhc3N3b3JkLWxlYWtlZA==" }The base64 value decodes to
victim-user:victim-password-leaked.Workarounds
Avoid passing empty or partial
authobjects. Only setauthwhen the application has own username and password values.Applications that merge untrusted input should filter
__proto__,constructor, andprototype, and should read optional user options with own-property checks rather thanopts.auth || {}.Where a wrapper must materialize optional auth, use a null-prototype object or explicitly copy only own fields.
Original Report
Summary
After GHSA-q8qp-cvcw-x6jj / PR #10779 (shipped in
v1.15.2) and the further proxy-side hardening inPR #10833 (merged 2026-05-02), the top-level
config.authand the proxy authsub-fields are correctly read viautils.hasOwnProp. The regular request auth sub-fields (config.auth.usernameandconfig.auth.password) and theconfig.params/config.paramsSerializerreads insideresolveConfig.jsare still unguarded against a pollutedObject.prototype.When a polluted host process makes an axios call with the common "optional override" pattern (
auth: opts.auth || {}— an empty own{}), the sub-field readsconfigAuth.usernameandconfigAuth.passwordwalk the prototype chain and return the attacker-controlled values. Same forparamsandparamsSerializer. The outbound HTTP request then carries an attacker-chosenAuthorization: Basic <base64>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).Reproduces against
axiosmainHEAD (34723be, dated 2026-05-24)as well as the released
v1.16.1.Details
Three still-unguarded read sites on
mainHEAD:(1)
lib/adapters/http.jslines 737–740 (Node http adapter):own('auth')correctly applieshasOwnPropto the top-levelauthkey. But once
configAuthis the empty object the caller passed(
auth: {}),configAuth.usernamewalks the prototype chain andpicks up
Object.prototype.username.Contrast with the proxy-auth path that PR #10833 fixed (lines 322–324):
This is the exact pattern needed at lines 739–740 too.
(2)
lib/helpers/resolveConfig.jslines 50 + 68 (xhr/fetch adapter shared resolver):Same shape — top-level guarded, sub-fields walk prototype.
(3)
lib/helpers/resolveConfig.jslines 58–59 (params + paramsSerializer):This third site is already proposed for fix in open PR #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.PoC
This PoC contains zero direct
Object.prototype.x = ywrites. Thepollution flows entirely from attacker-shaped JSON through a real
deep-merge utility (
defaults-deep@0.2.4, ~50k weekly downloads,still walks
constructor.prototype). A hand-rolled deep merge —the canonical insecure backend pattern — exhibits the same pollution
via
__proto__and is more common in real codebases than any namedutility.
Reproduction:
Captured output (verified against released
1.16.1AND againstmainat34723be, 2026-05-24):{ "method": "GET", "url": "/api/widget?leak=ATTACKER_QUERY_TOKEN", "authorization": "Basic dmljdGltLXVzZXI6dmljdGltLXBhc3N3b3JkLWxlYWtlZA==" }dmljdGltLXVzZXI6dmljdGltLXBhc3N3b3JkLWxlYWtlZA==base64-decodes tovictim-user:victim-password-leaked. The querystring carries?leak=ATTACKER_QUERY_TOKEN, which can be a full data-exfil channelin real chains (CSRF token, session cookie via
req.headers, etc.).Impact
request. If the request URL is attacker-influenced too (common in
webhook/oauth-callback patterns), the credentials flow directly to
the attacker. If not, they flow to the legitimate destination but
expose victim credentials in any logs / proxies along the path.
params/paramsSerializer. WithparamsSerializerpolluted to an attackerfunction, axios will execute that function with each
paramsinvocation — same-process code execution from a pollution primitive.
precondition is "deep-merges attacker JSON into a config object
without
__proto__/constructorfiltering, then uses the empty-fallback wrapper
auth: opts.auth || {}/params: opts.params || {}."Both halves are very common in real codebases (we tested
defaults-deep, hand-rolled merges, and several lodash-familyutilities; many still pollute).
Attributes — amplifier sink).
Proposed fix
Two-line change in
http.js, matching the proxy-auth pattern PR#10833 already established:
Same pattern in
resolveConfig.js:The
params/paramsSerializerhalf is already handled by openPR #10922's
own('params')/own('paramsSerializer')change — thatPR should be rebased / merged.
Relationship to recent prototype-pollution work
Same vulnerability class as the existing public hardening, just at
sub-field granularity:
mergeConfigdirect-key reads. Fixed in v1.15.2.mergeDirectKeysin→hasOwnProp. Fixed in v1.15.x.auth.username/passwordsub-fields. Fixed post-1.16.1.formDataToJSONdefense-in-depth. Fixed post-1.16.1.socketPathguard. Merged 2026-05-24.params/paramsSerializerown()guard. Proposed; not merged.This report adds: regular-request
auth.username/auth.passwordsub-field reads in both the http adapter (lines 737–740) and
resolveConfig.js (line 68).
Reporter notes
findings. The bundle's public tracking entry (without the working
exploit chain) is at
georgian-io/package-runtime-security-findings/advisories/AXIOS-002-prototype-pollution-config-fields.md.prefer to fold this into open PR #10922 (whose author is actively
responding to comments), please let me know and I'll coordinate.
requires a separate prototype-pollution primitive elsewhere in the
host process. That's how the existing GHSA-q8qp-cvcw-x6jj and
PR #10833 were framed too, so the precedent for "in-scope as a
hardening fix" is established.
Severity
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
axios/axios (axios)
v1.18.0Compare Source
This release hardens redirect and URL handling, improves the validateStatus configuration semantics, and includes updates to documentation, dependencies, and release metadata.
Configuration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.