2
0
mirror of https://github.com/tenrok/axios.git synced 2026-06-17 19:21:29 +03:00

fix(security): defense-in-depth against already-polluted Object.prototype in formDataToJSON (#7413)

* fix(security): harden prototype pollution protection in formDataToJSON

Replace falsy check with hasOwnProp in the intermediate-path branch of
formDataToJSON's buildPath to prevent write-through into inherited objects.

Without this patch, if Object.prototype is already polluted (e.g. via a
third-party library or earlier vulnerability), user-supplied FormData
paths like 'injected.hijack' traverse the inherited object and mutate
Object.prototype in place. With hasOwnProp, the inherited slot is
shadowed by a new own property, keeping writes local to the result.

This is defense-in-depth: the existing __proto__ guard blocks direct
prototype injection, while this change prevents exploitation of an
already-polluted prototype chain.

Closes #7209

* test(security): use defineProperty + toBe in prototype-pollution regression test

---------

Co-authored-by: tommyhgunz14 <tommyhgunz14@users.noreply.github.com>
Co-authored-by: Jay <jasonsaayman@gmail.com>
This commit is contained in:
TomTensor
2026-05-04 20:31:02 +01:00
committed by GitHub
parent 9e6cc4725f
commit 78e8dcf875
2 changed files with 22 additions and 1 deletions
+1 -1
View File
@@ -68,7 +68,7 @@ function formDataToJSON(formData) {
return !isNumericKey;
}
if (!target[name] || !utils.isObject(target[name])) {
if (!utils.hasOwnProp(target, name) || !utils.isObject(target[name])) {
target[name] = [];
}
+21
View File
@@ -95,4 +95,25 @@ describe('formDataToJSON', () => {
expect({}.x).toEqual(undefined);
expect({}.y).toEqual(undefined);
});
it('should not write through to inherited objects on Object.prototype', () => {
Object.defineProperty(Object.prototype, 'injected', {
value: { hijack: true },
configurable: true,
writable: true,
});
try {
const formData = new FormData();
formData.append('injected.hijack', 'STOLEN');
const result = formDataToJSON(formData);
expect(result.injected).toEqual({ hijack: 'STOLEN' });
expect(Object.prototype.injected.hijack).toBe(true);
} finally {
delete Object.prototype.injected;
}
});
});