A modern JavaScript utility library delivering modularity, performance, & extras.
[Security Critical] _.template() compiles untrusted input as executable code (CVE-2021-23337 / CWE-94) #3
Summary
The bundled lodash.js (v4.17.23) includes _.template(), which compiles template strings into live JavaScript functions using new Function(...). The function is explicitly acknowledged as insecure in the project's own threat-model.md and is associated with CVE-2021-23337 (CVSS 7.2 HIGH).
Affected File
| File | Lines | Description |
|---|---|---|
lodash.js |
~14885–15050 | _.template() implementation using new Function(importsKeys, sourceURL + 'return ' + source) |
lodash.js |
~1750–1813 | templateSettings with evaluate delimiter (<% ... %>) enabling arbitrary JS execution |
threat-model.md |
entire file | Self-documents _.template as insecure and slated for removal in v5 |
Technical Detail
_.template() works by:
- Parsing the template string for
<% ... %>(evaluate),<%= ... %>(interpolate), and<%- ... %>(escape) delimiters. - Building a JavaScript source string from that input.
- Executing it via
new Function(...)— equivalent toeval().
If an attacker controls the template string or the variable option, arbitrary JavaScript can be injected and executed in the same privilege context as the calling application.
The library's own documentation (threat-model.md) states:
"The current implementation of
_.templatecompiles template strings into executable code, which can lead to code injection when given untrusted input (e.g., CVE-2021-23337). For that reason we consider it insecure and advise against its use."
CVE Reference
- CVE-2021-23337 — Command Injection via
_.templatein lodash < 4.17.21
Recommendation
- Do not pass user-controlled data as the template string to
_.template(). - If template rendering is required, migrate to a safe, sandboxed alternative (e.g.,
mustache,handlebarswith strict escaping). - Plan removal of
_.templateusage ahead of the Lodash v5 upgrade, which will drop this function entirely. - Add a linting rule (e.g.,
eslint-plugin-security) to flag_.templateusage in the codebase.
Severity
Critical — Code injection / RCE if untrusted input reaches _.template().
Reported by Morph Code automated security scanner.