Lodash — the utility library that quietly powers a staggering share of the JavaScript ecosystem — shipped a code injection flaw in its template function that was assigned CVE-2021-23337. The bug lets an attacker who controls template input, or certain template configuration options, break out of the templating sandbox and get arbitrary JavaScript executed in the host application. Because _.template compiles strings into executable functions under the hood, a successful exploit can escalate to full remote code execution on the server or build machine running the vulnerable code — not a denial-of-service or minor data leak, but code execution in whatever process context lodash is running in. Given that lodash is downloads-per-week counted in the tens of millions and is buried as a transitive dependency in an enormous fraction of npm's package graph, the practical blast radius of this CVE has far less to do with how the vulnerability works and far more to do with how many places it's silently sitting unpatched.
What Went Wrong in _.template
Lodash's template function is a small templating engine: you pass it a string with <%= %>-style interpolation markers, and it compiles that string into a JavaScript function using an internal Function constructor — conceptually similar to a scoped eval. That compilation step is the entire attack surface. The function is supposed to escape or reject property names and expressions that fall outside the expected template syntax before they're spliced into the generated function body.
CVE-2021-23337 exists because that sanitization was incomplete. When lodash builds the variable-reference portion of the compiled function — particularly when a caller supplies a custom variable option, or when default variable resolution processes attacker-influenced object keys — a crafted string can smuggle in code that isn't properly neutralized. The compiled function then contains attacker-controlled JavaScript that runs with the full privileges of the calling process the moment the template is invoked. There's no need for eval() to be called explicitly anywhere in application code; lodash is doing the equivalent internally on the developer's behalf, and that's precisely what makes the bug easy to miss in a code review — the dangerous execution path is inside a dependency, not inside the application's own logic.
This is the same broad vulnerability class that has hit lodash's templating and merge/set functions repeatedly over the years (prototype pollution issues like CVE-2020-8203 and CVE-2019-10744 share the same root cause: the library trusts structure that should be treated as untrusted). CVE-2021-23337 is the "command injection via template" variant of that lineage, and it's a useful reminder that a single utility library reused across an entire dependency tree turns one class of bug into hundreds of independent exposure points.
Affected Versions and Components
- Vulnerable: all
lodashversions prior to 4.17.21. - Fixed in:
lodash4.17.21, released April 2021. - Component: the
_.templatefunction (and the internal compilation helpers it relies on), reachable both via direct calls and via any code path — including other npm packages — that constructs or renders lodash templates from external input. - Related packages: the standalone modular packages published from the same source tree, including
lodash.templateandlodash-es, carried the same defect and needed independent remediation since npm treats them as separate published artifacts with their own version histories. - Ecosystem exposure: lodash is one of the most depended-upon packages in the npm registry. It is pulled in transitively by build tools, CLI frameworks, testing harnesses, and countless application-level packages, which means a project can be exposed to CVE-2021-23337 without ever importing lodash directly — a classic "phantom dependency" supply chain scenario.
The practical risk depends heavily on how _.template is used. Applications that template only static, developer-authored strings have limited exposure. Applications that build templates from user input, from configuration values sourced externally, from CMS content, or from any data an attacker can influence are the ones where this CVE converts from "theoretical" to "exploitable."
Severity: CVSS, EPSS, and KEV Context
NVD scores CVE-2021-23337 at CVSS 3.1 Base Score 7.2 (High), with a vector reflecting network attack vector, low attack complexity, and high impact to confidentiality, integrity, and availability once a privileged code path is reached (AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H). The "High" privileges-required component in that vector matters in practice: exploitation generally requires the attacker to already have some ability to influence data that flows into the template compilation step, rather than being reachable from a fully anonymous, zero-touch network request. That nuance is exactly why reachability matters more than the raw score — a 7.2 sitting on a dead code path is a very different risk than a 7.2 sitting behind a public-facing form handler.
CVE-2021-23337 does not currently appear on CISA's Known Exploited Vulnerabilities (KEV) catalog, and EPSS exploitation-probability scoring for it has historically sat in the low single digits, consistent with no confirmed widespread automated exploitation campaigns. Security teams should read that as "not urgent because it's being mass-exploited in the wild" rather than "safe to ignore" — the combination of lodash's ubiquity, the maturity of public proof-of-concept exploit code, and the tendency of this dependency to go unnoticed in dependency trees means the real-world risk is driven far more by exposure and reachability than by KEV/EPSS scoring alone.
Timeline
- Prior years — Lodash's templating and object-manipulation functions (
merge,set,template) had already been the subject of multiple prototype-pollution and injection disclosures, establishing a known pattern of risk in this part of the library. - February 2021 — CVE-2021-23337 is publicly disclosed and assigned, documenting the command/code injection weakness in
_.template. - April 20, 2021 — Lodash 4.17.21 is released, patching the vulnerability along with several other outstanding security issues in the same release.
- 2021–present — CVE-2021-23337 continues to surface repeatedly in software composition analysis (SCA) scans and audits, almost always via transitive dependencies rather than direct usage — a durability pattern typical of foundational utility libraries that get pinned by other packages'
package-lock.jsonoryarn.lockfiles long after the fix is available.
Remediation Steps
- Upgrade lodash to 4.17.21 or later everywhere it appears. Run
npm ls lodashoryarn why lodashto enumerate every direct and transitive instance in your dependency graph — in most real codebases this surfaces multiple pinned versions across unrelated packages. - Patch the modular packages independently. If your project (or a dependency of it) imports
lodash.templateorlodash-esdirectly rather than the umbrellalodashpackage, confirm those packages have also been bumped past their fixed versions; they are published and versioned separately. - Force resolution when upstream maintainers haven't updated. Use
overrides(npm) orresolutions(Yarn) in your rootpackage.jsonto pin a safe lodash version even when an outdated transitive dependency still requests a vulnerable range. - Treat
_.templateas code execution, not string formatting. Regardless of patch status, never pass user-controlled or externally sourced strings into_.templatewithout strict allow-listing of expected structure. If you don't control every character of the input, don't compile it into a function. - Audit template usage for the
variableoption. Code that customizes thevariablesetting is the specific area implicated in this CVE; review any such usage for how the resulting variable name is validated before being embedded in the compiled function. - Regenerate lockfiles and rebuild container images after bumping versions — pinned transitive versions in existing lockfiles and cached image layers will silently preserve the vulnerable version even after
package.jsonconstraints are corrected. - Re-scan after remediation to confirm no other package in the tree reintroduces a pre-4.17.21 lodash version, which is common when multiple dependencies each specify their own loose lodash range.
How Safeguard Helps
Finding "lodash somewhere in my dependency tree" is trivial; knowing whether your application actually calls the vulnerable _.template code path with attacker-influenced data is the harder — and more actionable — question, and it's exactly where Safeguard's reachability analysis is built to help, cutting through alert noise generated by transitively-included but never-invoked functions. Safeguard's SBOM generation and ingest continuously map every direct and nested occurrence of lodash across your services and containers, so CVE-2021-23337 exposure is visible the moment a vulnerable version lands in a build rather than weeks later during a periodic audit. Griffin AI correlates that dependency data with real call-graph and data-flow context to prioritize instances where template input can actually be influenced by external users, letting security teams focus remediation effort on genuinely exploitable code instead of chasing every hit an SCA scanner flags. When action is needed, Safeguard's auto-fix PRs open version bumps (and, where relevant, overrides/resolutions entries) directly against affected repositories, turning a multi-team dependency-hunt into a reviewable pull request. Together, this workflow closes the gap between "a CVE exists somewhere in our stack" and "here is the exact service, the exact call path, and the exact fix" — the difference that determines whether a vulnerability like this gets remediated in hours or lingers for years.