Safeguard
Vulnerabilities

Lodash 4.17.21: The Security History Behind the Version Bump

Lodash 4.17.21 closed a ReDoS path in its number-parsing helpers and a command-injection risk in its templating function — here's the security history that led up to it.

Safeguard Research Team
Research
5 min read

Lodash 4.17.21 vulnerabilities trace back to two separate issues that had been sitting in the library's utility functions: a regular-expression denial-of-service (ReDoS) path reachable through lodash's number-parsing helpers, and an injection risk in its template function when template options came from an untrusted source. Neither was a single dramatic exploit; both were quiet fixes to a library so widely embedded that almost every Node.js project pulls it in transitively, whether or not anyone on the team ever calls lodash directly.

Why does lodash have such a long CVE history?

Lodash is one of the most-depended-upon packages in the npm ecosystem, and it functions as a utility toolkit that touches object merging, deep cloning, string templating, and type coercion — all classic sources of security bugs when input isn't trusted. That combination of massive reach and utility-function surface area means lodash has accumulated several CVEs over its lifetime, most notably a string of prototype-pollution issues in functions like merge, defaultsDeep, and zipObjectDeep that were fixed across releases leading up to 4.17.21. Prototype pollution happens when an attacker can inject a key like __proto__ into an object passed to one of these functions, silently modifying behavior across the whole application rather than just the object being merged.

What changed specifically in the 4.17.21 release?

Version 4.17.21 consolidated fixes for a ReDoS issue in lodash's trim, trimStart, and related number-parsing code paths, where a specially crafted string could cause the underlying regular expression to take a disproportionate amount of time to evaluate — a classic denial-of-service vector rather than a data-exposure one. It also addressed a command-injection concern in lodash.template, where template compilation options that came from untrusted input could be abused to execute arbitrary code during template rendering. Because lodash.template is used by build tooling and templating layers in more places than most developers realize, this fix mattered more for backend and build-pipeline usage than for typical front-end utility calls.

Does upgrading to 4.17.21 fully resolve lodash's security history?

It resolves the known CVEs current as of that release, but "fully resolve" undersells how this class of library keeps getting revisited. Prototype pollution as a vulnerability class isn't unique to lodash — it recurs across JavaScript libraries that deep-merge objects — so the safest posture is treating lodash (and any deep-merge utility) as needing ongoing monitoring rather than a one-time patch. Teams that pinned lodash years ago and never revisited the dependency are the ones still carrying the older prototype-pollution issues today, because nothing forces a transitive dependency bump without an active scan flagging it.

How do you find out which lodash version is actually running in your build?

Check the resolved version in your lockfile, not the version requested in package.json — a caret range like ^4.17.15 can resolve to an old cached version if a lockfile was never regenerated. Lodash is also commonly pulled in as a transitive dependency of other packages (build tools, testing frameworks, older UI libraries), so a project's own package.json may never mention it while a vulnerable copy still ships in node_modules. Safeguard's SCA scanning resolves the full dependency graph, including transitive lodash pulled in by unrelated packages, and layers reachability analysis on top so a team can tell whether the vulnerable template or trim code path is one their application actually exercises versus one sitting unused in a dev-only tool.

What's the practical lesson from lodash's specific version history?

The lesson isn't "lodash is unsafe" — it's that any utility library popular enough to sit in nearly every project's dependency tree becomes a high-value target for researchers looking for the next widely reachable bug, and that popularity cuts both ways. A vulnerability in a niche package with 500 weekly downloads affects a handful of projects; a vulnerability in lodash, which has historically counted tens of millions of weekly downloads across the npm ecosystem, potentially touches an enormous share of production JavaScript applications the moment it's disclosed. That asymmetry is exactly why lodash's individual CVEs, taken one at a time, look modest in severity, but the aggregate operational burden of tracking and patching them across every project that depends on it — directly or transitively — has been substantial for the ecosystem as a whole. It's also why supply-chain-focused teams increasingly treat "how many places does this dependency appear across our portfolio" as its own risk signal, independent of any specific CVE.

FAQ

Is lodash 4.17.21 the latest secure version?

As of this writing, 4.17.21 is the last major lodash release and has no outstanding known CVEs; the project has since moved slowly, so most current guidance still points teams to 4.17.21 or the lodash-es equivalent.

What is prototype pollution, in plain terms?

It's a bug class where an attacker-controlled input can add or overwrite a property on Object.prototype itself — because JavaScript objects inherit from a shared prototype, that single change can alter behavior anywhere in the application that touches an object, not just the one being modified.

Should I replace lodash with native JavaScript methods instead of patching?

For simple cases (array methods, basic object spreads) modern JavaScript's built-ins cover a lot of what lodash used to be needed for, and removing the dependency removes its attack surface entirely — but for deep-merge, templating, and some type-coercion helpers, lodash still does meaningfully more work than native methods, so a wholesale rip-and-replace isn't always worth the migration cost compared to just staying current on patched versions.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.