fix(core): avoid mutating caller's config object in axios(url, config) - #11154
fix(core): avoid mutating caller's config object in axios(url, config)#11154koreahghg wants to merge 7 commits into
Conversation
_request() wrote `url` directly onto the config object passed by the caller when using the axios(url, config) shorthand, silently mutating it. Build a shallow copy instead so a config object reused across multiple calls is left untouched. :surfer:
The shorthand's shallow copy read every enumerable own property, including __proto__/constructor/prototype, before mergeConfig's filter runs. Route it through the same safe-materialization helper already used at the dispatchRequest boundary so unsafe keys are skipped before their values are ever read, and add a regression test covering getter-backed unsafe keys. :surfer:
|
Thanks for the review — the P1 was real. Fixed in 323b623 by routing the shorthand's config copy through the same For anyone following along, One nuance worth recording for reviewers of the original commit (417939e): a repro showed the plain-spread version didn't actually change the net exposure versus the pre-PR code, because Added a regression test ( 🏄 |
There was a problem hiding this comment.
All reported issues were addressed across 3 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
toSafeFlatObject reads every own property name via Object.getOwnPropertyNames, including non-enumerable ones, so a config object with a throwing non-enumerable getter unrelated to __proto__/constructor/prototype caused axios(url, config) to reject before dispatch - behavior a native object spread would never have triggered, since spread only touches enumerable own properties. It also doesn't short-circuit on undefined/null, though the call site already guarded that. Replace it with a small local copy that mirrors mergeConfig's own "enumerable own keys (incl. symbols), skip the three reserved names before reading their value" semantics, without touching non-enumerable properties. Added regression tests for the no-config shorthand call and for a non-enumerable throwing getter. :surfer:
There was a problem hiding this comment.
All reported issues were addressed across 3 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
Guard the symbol filter against a config Proxy whose ownKeys trap reports a symbol with no matching property descriptor (getOwnPropertyDescriptor returning undefined), and build the copy on a null-prototype object so an Object.prototype setter placed under an ordinary key name can't intercept the copy's plain assignments the way a native spread's CreateDataProperty semantics never would. Added regression tests for both. :surfer:

Summary
Axios#_request()wroteurldirectly onto theconfigobject passed by the caller when using theaxios(url, config)shorthand (e.g.axios('example/url', config)), silently mutating an object the library does not own.const shared = {...}; axios('/first', shared); axios('/second', shared);leavesshared.urlset to'/second'afterwards, even though the caller never asked for that field to be added.config = { ...config, url: configOrUrl }) instead of mutating in place, consistent with the project's existing "do not mutate config objects" convention used elsewhere inmergeConfig/utils.merge.Test plan
tests/unit/axios.test.jsasserting the originalconfigobject is unchanged (nourlkey added) afteraxios.request(url, config).npm run test:vitest:unit— full unit suite passes (one pre-existing, unrelated failure intests/unit/adapters/fetch.test.jsreproduces identically onv1.xwithout this change).npx eslint lib/core/Axios.js tests/unit/axios.test.js— clean.PRE_RELEASE_CHANGELOG.mdentry under Bug Fixes.🏄
Summary by cubic
Prevents
axios(url, config)from mutating the caller’s config and from invoking unsafe getters. Previously_requestwroteurlonto the provided object; now it builds a fresh null-prototype copy that copies only enumerable own keys (including symbols) and skips__proto__/constructor/prototype.Description
Object.prototypesetters from intercepting assignments.mergeConfigbehavior.Docs
/docs/(request configuration andaxios(url, config)shorthand) to state the input config is not mutated, only enumerable own keys are read, and__proto__/constructor/prototypeare ignored.Testing
Object.prototypesetter isn’t invoked.v1.x.Semantic version impact
Patch (no API changes).
Written for commit e130935. Summary will update on new commits.