Lodash Code Injection via Template Options (CVE-2026-4800)
Your application uses a popular JavaScript utility library called Lodash. A security flaw in versions up to 4.17.x means that if any part of your app passes user-supplied data into a specific templating feature, an attacker could run their own code on your server. This is a bypass of a previous fix — the library patched one door but left another one open.
Business Impact And Actions
high urgencyBusiness Impact
If your application uses Lodash's template feature with user-controlled input, an attacker could execute arbitrary code on your server — potentially accessing databases, environment variables, or other sensitive systems. This carries compliance and data-breach implications. Most small SaaS apps don't use this specific feature with untrusted input, so your actual exposure depends on how your code uses Lodash.
What To Do
- Ask your developer to check whether your application uses Lodash's _.template() function with any user-supplied data — this is the only scenario where you are at risk.
- Ask your developer to upgrade Lodash to version 4.18.1 or higher — this is a straightforward package update that typically takes under an hour.
- If an immediate upgrade isn't possible, ask your developer to ensure that only static, developer-written values are ever passed as template option keys — never anything from a user request.
- Run a dependency scan (tools like npm audit or Snyk are free) to check whether Lodash is also pulled in indirectly by other packages you use, and ensure those are updated too.
Lodash _.template() Code Injection via options.imports Key Names (CVE-2026-4800)
high severity CVSS 8.1Vulnerability Explanation
CVE-2026-4800 is an incomplete-fix bypass of CVE-2021-23337. The 2021 patch added validation of the `variable` option in `_.template()` against the `reForbiddenIdentifierChars` regex, but the same validation was never applied to the key names of the `options.imports` object. Both code paths feed into the same `Function()` constructor sink. An attacker who controls `options.imports` key names can inject ES6 default-parameter expressions (e.g., `x=require('child_process').execSync(...)`) that execute synchronously at template compilation time — before any template rendering occurs. A second vector exists via prototype pollution: `_.template` used `assignInWith` to merge imports, which enumerates inherited properties via `for..in`. If `Object.prototype` has been polluted by any other vector, the polluted keys are automatically copied into the imports object and passed to `Function()`.
Root Cause
The `_.template` function constructs a JavaScript `Function()` dynamically using import key names as parameter identifiers. The 2021 fix (CVE-2021-23337) applied `reForbiddenIdentifierChars` validation only to the `variable` option, leaving `options.imports` key names unvalidated. Additionally, use of `assignInWith` (which walks the prototype chain via `for..in`) instead of `assignWith` (own-properties only) created a prototype pollution amplification path.
Technical Impact
Remote code execution (RCE) on the server or in the browser. An attacker who can influence `options.imports` key names can execute arbitrary JavaScript at template compilation time, enabling data exfiltration, server takeover, environment variable leakage, or lateral movement within the host environment. The attack requires no privileges and no user interaction once the vulnerable code path is reachable.
Severity Justification
CVSS 8.1 (High) per published scoring. Network-accessible RCE with no privileges required, but attack complexity is rated High due to the prerequisite that the application must pass attacker-controlled data as options.imports key names, or that a separate prototype pollution vector must already be present.
Affected Components
lodash >= 4.0.0, < 4.18.0lodash-es >= 4.0.0, < 4.18.0lodash-amd >= 4.0.0, < 4.18.0lodash.template >= 4.0.0, < 4.18.0 (standalone package — see note)
Remediation Steps
- Upgrade `lodash` to version 4.18.1 or higher. Note: 4.18.0 was the intended fix release but was deprecated due to a breaking change; use 4.18.1+. Run: `npm install lodash@latest` or `yarn add lodash@latest`.
- Audit transitive dependencies: run `npm ls lodash` (or `yarn why lodash`) to identify any nested packages pinning an older version. Use `npm audit fix` or override the version in your `package.json` resolutions field.
- If you use the standalone `lodash.template` npm package, be aware it has historically lagged behind the main package on security fixes. Migrate to the main `lodash` package or pin a patched version once available.
- As a short-term workaround if upgrade is blocked: ensure `options.imports` key names are always static, developer-controlled identifiers — never derived from request parameters, database values, or any external input.
- To mitigate the prototype pollution amplification vector in Node.js, add `Object.freeze(Object.prototype)` at application startup as a defence-in-depth measure.
Verification Steps
- After upgrading, run `npm ls lodash` and confirm all resolved versions are >= 4.18.1.
- Run `npm audit` and verify CVE-2026-4800 no longer appears in the output.
- If you use Snyk or a similar SCA tool, re-scan the project and confirm SNYK-JS-LODASH-15869625 is resolved.
- In a test environment, attempt to call `_.template('', { imports: { 'x=1': undefined } })` — the patched version should throw an error rather than compile successfully.
Code Examples (javascript)
// Vulnerable: user-controlled key name reaches _.template options.imports
const userKey = req.body.importName; // e.g. 'x=process.env'
const compiled = _.template('<%= x %>', {
imports: { [userKey]: someValue } // UNSAFE — key is not validated
});
compiled();
// Fixed: upgrade to lodash >= 4.18.1 (patch is in the library itself)
// Additionally, always use static, developer-controlled key names:
const compiled = _.template('<%= helper %>', {
imports: { helper: myHelperFunction } // SAFE — static key
});
compiled();
Best Practices
- Never pass user-supplied data as property key names in `_.template` options — treat import key names as code identifiers, not data.
- Maintain a software composition analysis (SCA) tool (e.g., `npm audit`, Snyk, Dependabot) in your CI pipeline to catch vulnerable transitive dependencies automatically.
- When a CVE is patched in a library, re-audit adjacent code paths in the same function for similar patterns — incomplete fixes are a documented recurring issue in lodash's `_.template`.
- Apply `Object.freeze(Object.prototype)` at Node.js application startup to prevent prototype pollution from amplifying injection vulnerabilities.
Found this in your infrastructure?
VulWall scans for this and dozens of other issues automatically.
Scan Your Domain Free