# es-toolkit@1.45.1 security report (npm)

- Verdict: **Needs review** (risk level: medium)
- Scanned: 2026-10-04T21:17:50.000Z
- Files reviewed: 1360
- Findings: 10 medium, 2 low severity findings
- Report: https://security.togoder.click/npm/es-toolkit
- Source: Togoder Security (https://security.togoder.click), AI source-code review

## Summary

Togoder Security scanned the npm package es-toolkit@1.45.1 on Oct 4, 2026. An AI review of 1360 source files produced 10 medium, 2 low severity findings. The overall verdict is medium: the findings flag risky but common patterns (dynamic code, unsafe defaults, broad file or network access) rather than confirmed malware.

## Findings

### [medium] Dynamic code execution

Finding ID: `NPS-F7C4FD56BF0B`

File: `dist/browser.global.js`

The `template` function constructs and executes arbitrary JavaScript via `new Function(...)`. While this is a standard lodash-compatible template feature, it permits code injection if untrusted templates are processed. This is a known risk surface for prototype pollution or RCE in downstream applications.

### [medium] Prototype pollution guards present but partially inconsistent

Finding ID: `NPS-71B778C8B3D5`

File: `dist/browser.global.js`

The code explicitly guards against `__proto__` in `isUnsafeProperty` and `get`/`unset`/`mergeWithDeep`/`updateWith`. However, several paths (e.g., `set`, `zipObject`, `fromPairs`, `assignValue`, `pick`, `keyBy`, `groupBy`, `mapKeys`, `toPlainObject` partially) assign arbitrary string keys without consistent `__proto__` filtering. `updateWith` skips unsafe keys but still allows `constructor`/`prototype` traversal in nested arrays. This could enable prototype pollution in some call paths if user-controlled keys are used.

### [medium] Unsafe use of `with` statement in generated code

Finding ID: `NPS-4597F834CE8C`

File: `dist/browser.global.js`

The `template` compilation embeds user template code inside a `with(obj) { ... }` block, which is a legacy, unsafe construct that can leak/observe the entire scope object and is disallowed in strict mode. Combined with `new Function`, this increases injection and sandbox-escape risk.

### [medium] Constructor invocation from untrusted input

Finding ID: `NPS-8D9BDC36B132`

File: `dist/compat/object/clone.js:36`

The clone function invokes constructors derived from the cloned object: `new Ctor(...)` for typed arrays and boxed primitives, `new obj.constructor(obj.valueOf())` for boolean/number/string objects, and `new Ctor(typedArray.buffer, ...)`. If `clone()` is called on an attacker-controlled object (e.g. from JSON parsed data or a malicious package), this can execute arbitrary constructor code and is a known gadget pattern for prototype-pollution-to-RCE chains.

### [medium] Prototype pollution / unsafe prototype copying

Finding ID: `NPS-C3683FC50AF8`

File: `dist/compat/object/clone.js:158`

copyPrototype() sets the target object's prototype to the source object's prototype using Object.setPrototypeOf. When cloning untrusted objects, this can propagate a polluted or attacker-controlled prototype (e.g. a modified Object.prototype) to the cloned object, potentially leading to prototype pollution downstream. Additionally, copyOwnProperties uses `for...in` and conditionally copies properties, and copySymbolProperties copies enumerable symbols; these patterns can carry over malicious properties from untrusted sources.

### [medium] Prototype pollution mitigation (potential bypass)

Finding ID: `NPS-FF1B832A501B`

File: `dist/compat/object/updateWith.mjs:33`

The function uses isUnsafeProperty to skip dangerous keys like __proto__, constructor, and prototype. However, if isUnsafeProperty is incomplete or bypassable (e.g., via encoded keys or alternative prototype pollution vectors), this could lead to prototype pollution. The code itself attempts to prevent this, but the security depends entirely on the correctness of the imported isUnsafeProperty implementation.

### [medium] Dynamic property assignment

Finding ID: `NPS-38E20904E3C2`

File: `dist/compat/object/updateWith.mjs:54`

The function dynamically assigns properties to objects based on user-provided paths via assignValue. While it attempts to block unsafe properties, this pattern is commonly associated with prototype pollution vulnerabilities if the guard is insufficient.

### [medium] Dynamic Code Execution

Finding ID: `NPS-2F62ADA8F437`

File: `dist/compat/string/template.js:89`

The template function uses `new Function(...)` to compile and execute a string constructed from user-supplied template content. This is inherent to the template engine design (similar to lodash.template) but creates a potential code injection risk if the template string or options are controlled by untrusted input. The constructed source includes user-supplied `evaluate` blocks, interpolated expressions, and `with(obj)` scoping.

### [medium] Dynamic code execution

Finding ID: `NPS-6162F19D4E67`

File: `dist/compat/string/template.mjs`

The template function compiles and executes arbitrary JavaScript code at runtime using `new Function()`. The `evaluate` delimiters (`<% %>`) allow embedding and executing arbitrary JavaScript expressions, which is an inherent security risk if template sources are untrusted. This is a common pattern in template engines (like lodash.template) but can lead to RCE when user-controlled input reaches the template string or options.

### [medium] Unvalidated imports into Function constructor

Finding ID: `NPS-2E6A0A647E37`

File: `dist/compat/string/template.mjs`

The `imports` option allows passing arbitrary values that are injected as parameters into the dynamically constructed function. If an attacker can control `options.imports`, they can influence the execution environment of the compiled template.

### [low] Use of with statement / scope injection

Finding ID: `NPS-AB3EBA9306A1`

File: `dist/compat/string/template.js:88`

Generated function wraps user expressions in `with(obj) { ... }`, which can expose global scope properties to user-supplied template expressions and is generally discouraged in secure code.

### [low] Use of 'with' statement / unsafe scope

Finding ID: `NPS-607C8F1BDDAF`

File: `dist/compat/string/template.mjs`

When `options.variable` is not provided, the compiled function wraps the generated source in a `with(obj) { ... }` block. The `with` statement is deprecated and can be exploited via prototype pollution to alter variable resolution, potentially enabling access to unintended global/module scope values within the template.

## Files reviewed

- `dist/browser.global.js` (medium): This is an es-toolkit/lodash-compatible bundle; no exfiltration, credential harvesting, mining, or backdoor patterns were found, but the `template` function's dynamic `new Function`/`with` code execution and inconsistent `__proto__` guards are notable security risks for callers.
- `dist/compat/object/clone.js` (medium): This is a benign-looking deep clone utility, but its use of Object.setPrototypeOf and constructor invocation on untrusted input creates prototype-pollution/constructor-gadget risks if misused; no exfiltration, obfuscation, network, file, or process-execution red flags were found.
- `dist/compat/object/updateWith.mjs` (medium): The code appears to be a legitimate utility for updating nested object properties with a customizer, but it includes prototype pollution mitigations that could be bypassed if the isUnsafeProperty guard is incomplete.
- `dist/compat/string/template.js` (medium): es-toolkit's template function intentionally uses new Function to evaluate template strings, which is a documented design feature but carries code-injection risk if templates are attacker-controlled; no exfiltration, backdoor, or install-time malicious behavior is present.
- `dist/compat/string/template.mjs` (medium): This is a template engine implementation that intentionally uses new Function and with for dynamic code evaluation; while it contains no direct malicious exfiltration or backdoor, its dynamic code execution capabilities pose inherent security risks if untrusted template input is processed.
- `array.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/add.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/after.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/ary.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/assign.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/assignIn.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/assignInWith.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/assignWith.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/at.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/attempt.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/before.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/bind.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/bindAll.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/bindKey.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/camelCase.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/capitalize.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/castArray.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/ceil.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/chunk.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/clamp.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/clone.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/cloneDeep.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/cloneDeepWith.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/cloneWith.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/compact.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/concat.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/cond.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/conforms.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/conformsTo.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/constant.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/countBy.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/create.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/curry.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/curryRight.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/debounce.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/deburr.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/defaultTo.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/defaults.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/defaultsDeep.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/defer.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/delay.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/difference.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/differenceBy.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/differenceWith.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/divide.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/drop.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/dropRight.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/dropRightWhile.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/dropWhile.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/each.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/eachRight.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/endsWith.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/eq.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/escape.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/escapeRegExp.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/every.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/extend.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/extendWith.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/fill.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/filter.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/find.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/findIndex.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/findKey.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/findLast.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/findLastIndex.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/findLastKey.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/first.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/flatMap.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/flatMapDeep.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/flatMapDepth.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/flatten.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/flattenDeep.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/flattenDepth.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/flip.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/floor.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/flow.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/flowRight.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/forEach.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/forEachRight.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/forIn.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/forInRight.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/forOwn.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/forOwnRight.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/fromPairs.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/functions.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/functionsIn.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/get.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/groupBy.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/gt.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/gte.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/has.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/hasIn.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/head.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/identity.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/inRange.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/includes.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/indexOf.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/initial.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/intersection.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/intersectionBy.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/intersectionWith.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/invert.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/invertBy.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/invoke.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/invokeMap.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isArguments.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isArray.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isArrayBuffer.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isArrayLike.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isArrayLikeObject.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isBoolean.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isBuffer.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isDate.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isElement.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isEmpty.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isEqual.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isEqualWith.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isError.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isFinite.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isFunction.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isInteger.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isLength.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isMap.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isMatch.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isMatchWith.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isNaN.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isNative.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isNil.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isNull.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isNumber.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isObject.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isObjectLike.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isPlainObject.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isRegExp.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isSafeInteger.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isSet.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isString.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isSymbol.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isTypedArray.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isUndefined.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isWeakMap.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/isWeakSet.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/iteratee.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/join.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/kebabCase.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/keyBy.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/keys.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/keysIn.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/last.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/lastIndexOf.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/lowerCase.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/lowerFirst.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/lt.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/lte.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/map.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/mapKeys.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/mapValues.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/matches.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/matchesProperty.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/max.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/maxBy.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/mean.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/meanBy.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/memoize.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/merge.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/mergeWith.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/method.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/methodOf.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/min.js` (safe): No malicious patterns detected; the file is a simple re-export of a math utility function.
- `compat/minBy.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/multiply.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/negate.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/noop.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/now.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/nth.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/nthArg.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/omit.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/omitBy.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/once.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/orderBy.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/over.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/overArgs.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/overEvery.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/overSome.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/pad.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/padEnd.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/padStart.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/parseInt.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/partial.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/partialRight.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/partition.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/pick.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/pickBy.js` (safe): Cleared by Jev triage; no further analysis needed
- `compat/property.js` (safe): Cleared by Jev triage; no further analysis needed

## Version ranges

None of the 3 scanned versions of es-toolkit are flagged high or critical. The latest scanned version, 1.52.0, is not scanned. Only versions we have scanned are listed; unscanned versions between them are not covered.

- 1.52.0 (`1.52.0`): not scanned
- 1.44.0 – 1.45.1 (`>=1.44.0 <=1.45.1`): medium (Prototype pollution / unsafe prototype copying +4 more)
- 1.43.0 (`1.43.0`): not scanned
- 1.33.0 (`1.33.0`): medium (Dynamic code execution +4 more)

## Scanned versions

- [1.45.1](https://security.togoder.click/npm/es-toolkit@1.45.1): medium, 2026-10-04T21:17:50.000Z
- [1.44.0](https://security.togoder.click/npm/es-toolkit@1.44.0): medium, 2026-10-06T14:16:10.000Z
- [1.33.0](https://security.togoder.click/npm/es-toolkit@1.33.0): medium, 2026-10-04T16:28:51.000Z

AI analysis is guidance, not a guarantee. Methodology: https://security.togoder.click/methodology
