8000 Prevent command injection through `_.template`'s `variable` option · lodash/lodash@3469357 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3469357

Browse files
stofbnjmnt4n
authored andcommitted
Prevent command injection through _.template's variable option
Closes #5085.
1 parent ded9bc6 commit 3469357

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

lodash.js

+20-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919

2020
/** Error message constants. */
2121
var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
22-
FUNC_ERROR_TEXT = 'Expected a function';
22+
FUNC_ERROR_TEXT = 'Expected a function',
23+
INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`';
2324

2425
/** Used to stand-in for `undefined` hash values. */
2526
var HASH_UNDEFINED = '__lodash_hash_undefined__';
@@ -165,6 +166,18 @@
165166
/** Used to match words composed of alphanumeric characters. */
166167
var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
167168

169+
/**
170+
* Used to validate the `validate` option in `_.template` variable.
171+
*
172+
* Forbids characters which could potentially change the meaning of the function argument definition:
173+
* - "()," (modification of function parameters)
174+
* - "=" (default value)
175+
* - "[]{}" (destructuring of function parameters)
176+
* - "/" (beginning of a comment)
177+
* - whitespace
178+
*/
179+
var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;
180+
168181
/** Used to match backslashes in property paths. */
169182
var reEscapeChar = /\\(\\)?/g;
170183

@@ -14866,6 +14879,12 @@
1486614879
if (!variable) {
1486714880
source = 'with (obj) {\n' + source + '\n}\n';
1486814881
}
14882+
// Throw an error if a forbidden character was found in `variable`, to prevent
14883+
// potential command injection attacks.
14884+
else if (reForbiddenIdentifierChars.test(variable)) {
14885+
throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT);
14886+
}
14887+
1486914888
// Cleanup code by stripping empty strings.
1487014889
source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
1487114890
.replace(reEmptyStringMiddle, '$1')

test/test.js

+8
Original file line numberDiff line numberDiff line change
@@ -22296,6 +22296,14 @@
2229622296
}
2229722297
});
2229822298

22299+
QUnit.test('should forbid code injection through the "variable" options', function(assert) {
22300+
assert.expect(1);
22301+
22302+
assert.raises(function () {
22303+
_.template('', { 'variable': '){console.log(process.env)}; with(obj' });
22304+
});
22305+
});
22306+
2229922307
QUnit.test('should support custom delimiters', function(assert) {
2230022308
assert.expect(2);
2230122309

0 commit comments

Comments
 (0)
0