VYPR
High severityNVD Advisory· Published Feb 15, 2021· Updated Sep 16, 2024

Command Injection

CVE-2021-23337

Description

Lodash versions prior to 4.17.21 are vulnerable to Command Injection via the template function.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Lodash <4.17.21 allows Command Injection via template's `variable` option, enabling remote code execution.

Lodash's _.template function is vulnerable to command injection through the variable option. The option was not sanitized for characters that could alter function parameter definitions, allowing malicious input to inject arbitrary JavaScript code [2][3].

Exploitation requires control over the variable option passed to _.template. An attacker can inject characters like ()=,{}[]/ to modify the generated Function constructor, leading to code execution [3].

Successful exploitation allows arbitrary command execution in the context of the application, potentially compromising the entire system [1].

This vulnerability is fixed in Lodash version 4.17.21, which rejects the variable option if it contains forbidden characters [2]. Users should upgrade immediately.

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
lodashnpm
< 4.17.214.17.21
lodash-esnpm
< 4.17.214.17.21
lodash.templatenpm
<= 4.5.0
lodash-templatenpm
<= 1.0.0
lodash-railsRubyGems
< 4.17.214.17.21

Affected products

6

Patches

1
3469357cff39

Prevent command injection through `_.template`'s `variable` option

https://github.com/lodash/lodashChristophe CoevoetFeb 17, 2021via ghsa
2 files changed · +28 1
  • lodash.js+20 1 modified
    @@ -19,7 +19,8 @@
     
       /** Error message constants. */
       var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
    -      FUNC_ERROR_TEXT = 'Expected a function';
    +      FUNC_ERROR_TEXT = 'Expected a function',
    +      INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`';
     
       /** Used to stand-in for `undefined` hash values. */
       var HASH_UNDEFINED = '__lodash_hash_undefined__';
    @@ -165,6 +166,18 @@
       /** Used to match words composed of alphanumeric characters. */
       var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
     
    +  /**
    +   * Used to validate the `validate` option in `_.template` variable.
    +   *
    +   * Forbids characters which could potentially change the meaning of the function argument definition:
    +   * - "()," (modification of function parameters)
    +   * - "=" (default value)
    +   * - "[]{}" (destructuring of function parameters)
    +   * - "/" (beginning of a comment)
    +   * - whitespace
    +   */
    +  var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;
    +
       /** Used to match backslashes in property paths. */
       var reEscapeChar = /\\(\\)?/g;
     
    @@ -14866,6 +14879,12 @@
           if (!variable) {
             source = 'with (obj) {\n' + source + '\n}\n';
           }
    +      // Throw an error if a forbidden character was found in `variable`, to prevent
    +      // potential command injection attacks.
    +      else if (reForbiddenIdentifierChars.test(variable)) {
    +        throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT);
    +      }
    +
           // Cleanup code by stripping empty strings.
           source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
             .replace(reEmptyStringMiddle, '$1')
    
  • test/test.js+8 0 modified
    @@ -22296,6 +22296,14 @@
           }
         });
     
    +    QUnit.test('should forbid code injection through the "variable" options', function(assert) {
    +      assert.expect(1);
    +
    +      assert.raises(function () {
    +        _.template('', { 'variable': '){console.log(process.env)}; with(obj' });
    +      });
    +    });
    +
         QUnit.test('should support custom delimiters', function(assert) {
           assert.expect(2);
     
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

19

News mentions

0

No linked articles in our index yet.