diff --git a/jest.config.js b/jest.config.js index c109c65382..6a7cab682b 100644 --- a/jest.config.js +++ b/jest.config.js @@ -30,4 +30,12 @@ module.exports = { transformIgnorePatterns: [ 'node_modules/(?!((jest-)?react-native|@firebase|@react-native(-community)?))', ], + // Packages cross-import each other's built output (e.g. database imports + // `@react-native-firebase/app/dist/module/common/deeps`), which resolves + // through the workspace symlink to `packages/*/dist/**`. Without this, + // Jest instruments both that build artifact and the original `lib/**.ts` + // source it was compiled from, so any shared file with branches gets a + // second, all-zero coverage entry alongside the real one, and codecov's + // patch coverage misreports lines that are actually fully tested. + coveragePathIgnorePatterns: ['/node_modules/', '/dist/'], }; diff --git a/packages/app/__tests__/common.test.ts b/packages/app/__tests__/common.test.ts index 511f657b01..2ddd03ad61 100644 --- a/packages/app/__tests__/common.test.ts +++ b/packages/app/__tests__/common.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from '@jest/globals'; import { Base64, getDataUrlParts } from '../lib/common'; +import { deepSet } from '../lib/common/deeps'; describe('common utilities', () => { describe('getDataUrlParts', () => { @@ -42,4 +43,25 @@ describe('common utilities', () => { }, ); }); + + describe('deepSet', () => { + it('rejects paths that mutate the target prototype', () => { + const target = {}; + + expect(deepSet(target, '__proto__.polluted', true)).toBe(false); + expect((target as Record).polluted).toBeUndefined(); + }); + + it('rejects paths that mutate Object.prototype', () => { + expect(deepSet({}, 'constructor.prototype.polluted', true, false)).toBe(false); + expect(({} as Record).polluted).toBeUndefined(); + }); + + it('still assigns values along an ordinary nested path', () => { + const target: Record = {}; + + expect(deepSet(target, 'a.b', 5)).toBe(true); + expect(target).toEqual({ a: { b: 5 } }); + }); + }); }); diff --git a/packages/app/lib/common/deeps.ts b/packages/app/lib/common/deeps.ts index 8ca859ac99..fda8723ad6 100644 --- a/packages/app/lib/common/deeps.ts +++ b/packages/app/lib/common/deeps.ts @@ -69,6 +69,9 @@ export function deepSet( return false; } const keys = path.split(joiner); + if (keys.some(key => ['__proto__', 'prototype', 'constructor'].includes(key))) { + return false; + } let i = 0; let _object: unknown = object;