diff --git a/src/react/__tests__/base/useUnit.test.tsx b/src/react/__tests__/base/useUnit.test.tsx index 4f71a7778..26639189c 100644 --- a/src/react/__tests__/base/useUnit.test.tsx +++ b/src/react/__tests__/base/useUnit.test.tsx @@ -1226,6 +1226,15 @@ describe('useUnit', () => { ) expect(failed).toBe(false) }) + test('avoiding prototype pollution', async () => { + const base = {fk: function fk() {}} + const $foo = createStore(0) + const App = () => { + const {foo} = useUnit({foo: $foo, __proto__: base}) + return
{foo}
+ } + await render() + }) }) describe('@effector/next custom hydration triggers hooks', () => { diff --git a/src/react/apiBase.ts b/src/react/apiBase.ts index 0ab2f10dd..2b0a48905 100644 --- a/src/react/apiBase.ts +++ b/src/react/apiBase.ts @@ -75,8 +75,12 @@ export function useUnitBase}>( const eventKeys: string[] = [] const eventValues: Array> = [] for (const key in normShape) { + if (!Object.prototype.hasOwnProperty.call(normShape, key)) continue const unit = normShape[key] - if (!is.unit(unit)) throwError('expect useUnit argument to be a unit') + if (!is.unit(unit)) { + const keyMessage = isSingleUnit ? 'argument' : `value in key "${key}"` + throwError(`expect useUnit ${keyMessage} to be a unit`) + } if (is.event(unit) || is.effect(unit)) { shape[key] = scope ? scopeBind(unit as Event, {scope}) : unit eventKeys.push(key)