8000 Backport resolve CVE-2021-23337 based on lodash/lodash commit 3469357 · tencyle-dev/lodash@edc1957 · GitHub
[go: up one dir, main page]

Skip to content

Commit edc1957

Browse files
tencyle-devyair
authored andcommitted
Backport resolve CVE-2021-23337 based on lodash/lodash commit 3469357
Prevent command injection through `_.template`'s `variable` option Closes lodash#5085.
1 parent c3a99c1 commit edc1957

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

lodash.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@
4040
/** Used to indicate the type of lazy iteratees. */
4141
var LAZY_FILTER_FLAG = 1,
4242
LAZY_MAP_FLAG = 2;
43-
44-
/** Used as the `TypeError` message for "Functions" methods. */
45-
var FUNC_ERROR_TEXT = 'Expected a function';
43+
/** Error message constants. */
44+
var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
45+
FUNC_ERROR_TEXT = 'Expected a function',
46+
INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`';
4647

4748
/** Used as the internal argument placeholder. */
4849
var PLACEHOLDER = '__lodash_placeholder__';
@@ -104,6 +105,18 @@
104105
/** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */
105106
var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g;
106107

108+
/**
109+
* Used to validate the `validate` option in `_.template` variable.
110+
*
111+
* Forbids characters which could potentially change the meaning of the function argument definition:
112+
* - "()," (modification of function parameters)
113+
* - "=" (default value)
114+
* - "[]{}" (destructuring of function parameters)
115+
* - "/" (beginning of a comment)
116+
* - whitespace
117+
*/
118+
var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;
119+
107120
/** Used to match backslashes in property paths. */
108121
var reEscapeChar = /\\(\\)?/g;
109122

@@ -10818,6 +10831,12 @@
1081810831
if (!variable) {
1081910832
source = 'with (obj) {\n' + source + '\n}\n';
1082010833
}
10834+
// Throw an error if a forbidden character was found in `variable`, to prevent
10835+
// potential command injection attacks.
10836+
else if (reForbiddenIdentifierChars.test(variable)) {
10837+
throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT);
10838+
}
10839+
1082110840
// Cleanup code by stripping empty strings.
1082210841
source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
1082310842
.replace(reEmptyStringMiddle, '$1')

lodash.src.js

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@
4040
var LAZY_FILTER_FLAG = 1,
4141
LAZY_MAP_FLAG = 2;
4242

43-
/** Used as the `TypeError` message for "Functions" methods. */
44-
var FUNC_ERROR_TEXT = 'Expected a function';
43+
/** Error message constants. */
44+
var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
45+
FUNC_ERROR_TEXT = 'Expected a function',
46+
INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`';
4547

4648
/** Used as the internal argument placeholder. */
4749
var PLACEHOLDER = '__lodash_placeholder__';
@@ -103,6 +105,18 @@
103105
/** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */
104106
var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g;
105107

108+
/**
109+
* Used to validate the `validate` option in `_.template` variable.
110+
*
111+
* Forbids characters which could potentially change the meaning of the function argument definition:
112+
* - "()," (modification of function parameters)
113+
* - "=" (default value)
114+
* - "[]{}" (destructuring of function parameters)
115+
* - "/" (beginning of a comment)
116+
* - whitespace
117+
*/
118+
var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;
119+
106120
/** Used to match backslashes in property paths. */
107121
var reEscapeChar = /\\(\\)?/g;
108122

@@ -10196,6 +10210,10 @@
1019610210

1019710211
while (nested != null && ++index < length) {
1019810212
var key = path[index];
10213+
//if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
10214+
// return object;
10215+
//}
10216+
1019910217
if (isObject(nested)) {
1020010218
if (index == lastIndex) {
1020110219
nested[key] = value;
@@ -11010,6 +11028,13 @@
1101011028
if (!variable) {
1101111029
source = 'with (obj) {\n' + source + '\n}\n';
1101211030
}
11031+
// Throw an error if a forbidden character was found in `variable`, to prevent
11032+
// potential command injection attacks.
11033+
else if (reForbiddenIdentifierChars.test(variable)) {
11034+
throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT);
11035+
}
11036+
11037+
1101311038
// Cleanup code by stripping empty strings.
1101411039
source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
1101511040
.replace(reEmptyStringMiddle, '$1')

test/test.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15415,6 +15415,10 @@
1541515415
}
1541615416
});
1541715417

15418+
test('should forbid code injection through the "variable" options', 1, function() {
15419+
raises(function() {_.template('', { 'variable': '){console.log(process.env)}; with(obj'});}, Error);
15420+
15421+
});
1541815422
test('should support the legacy `options` param signature', 1, function() {
1541915423
var compiled = _.template('<%= data.a %>', null, { 'variable': 'data' }),
1542015424
data = { 'a': 1 };

0 commit comments

Comments
 (0)
0