Skip to content
This repository was archived by the owner on Dec 19, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/set.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import each from 'lodash/each'
import get from 'lodash/get'
import _set from 'lodash/set'
import { disallowProtoPath } from './utils'

type Many<T> = T | ReadonlyArray<T>

export const set = <T extends object>(object: T, value: any, ...paths: Array<Many<string | number | symbol>>) => {

each(paths, path => _set(object, path, typeof value !== 'function' ? value : value(get(object, path), path, object)))
each(paths, path => {
disallowProtoPath(path)
return _set(object, path, typeof value !== 'function' ? value : value(get(object, path), path, object))
})

return object

Expand Down
26 changes: 26 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* Utilities and helper functions
*/

import { toPath } from "lodash";

type Many<T> = T | ReadonlyArray<T>

const ILLEGAL_KEYS = new Set(["constructor", "__proto__"]);

export const isIllegalKey = (key: Many<string | number | symbol>): boolean => typeof key === "string"
? ILLEGAL_KEYS.has(key)
: false

export const isProtoPath = (path: Array<Many<string | number | symbol>> | Many<string | number | symbol>): boolean => Array.isArray(path)
? path.some(isIllegalKey)
: typeof path === "string"
? isIllegalKey(path)
: false;

export const disallowProtoPath = (paths: Array<Many<string | number | symbol>> | Many<string | number | symbol>): void => {
const path = toPath(paths)
if (isProtoPath(path)) {
throw new Error(`Unsafe path encountered: ${path.toString()}`)
}
}
6 changes: 5 additions & 1 deletion test/set.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ test(`Value can bea function that invoked to preduce the actual value to set`, (
prop: 2,
anotherProp: 1,
0: [1]
}))
}))

test(`Disallow protopath override by throwing exception when unsafe path encountered`, () => expect(() => set({}, 'test', '__proto__.polluted')).toThrow())

test(`Disallow protopath override by throwing exception when unsafe path encountered`, () => expect(() => set({}, 'test', 'constructor.prototype.polluted')).toThrow())