Skip to content

Commit 11ba022

Browse files
committed
fix: ignore inherited enumerable properties
harden object merging against prototype-derived keys
1 parent 3942bfb commit 11ba022

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

src/defu.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ function _defu<T>(baseObject: T, defaults: any, namespace = ".", merger?: Merger
99

1010
const object = { ...defaults };
1111

12-
for (const key in baseObject) {
12+
for (const key of Object.keys(baseObject as Record<string, any>)) {
1313
if (key === "__proto__" || key === "constructor") {
1414
continue;
1515
}
1616

17-
const value = baseObject[key];
17+
const value = (baseObject as Record<string, any>)[key];
1818

1919
if (value === null || value === undefined) {
2020
continue;

test/defu.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,25 @@ describe("defu", () => {
116116
expect({}.isAdmin).toBe(undefined);
117117
});
118118

119+
it("should ignore inherited enumerable properties", () => {
120+
Object.defineProperty(Object.prototype, "pollutedEnum", {
121+
value: 123,
122+
enumerable: true,
123+
configurable: true,
124+
writable: true,
125+
});
126+
127+
try {
128+
const result = defu({ nested: {} }, { nested: {} });
129+
130+
expect(result).toEqual({ nested: {} });
131+
expect(Object.keys(result)).toEqual(["nested"]);
132+
expect(Object.keys(result.nested)).toEqual([]);
133+
} finally {
134+
delete (Object.prototype as Record<string, unknown>)["pollutedEnum"];
135+
}
136+
});
137+
119138
it("should ignore non-object arguments", () => {
120139
expect(defu(null, { foo: 1 }, false, 123, { bar: 2 })).toEqual({
121140
foo: 1,

0 commit comments

Comments
 (0)