diff --git a/CHANGELOG.md b/CHANGELOG.md
index 08da799fc4..1b2aacf7e6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+
+## [2.13.4](https://github.com/jshint/jshint/compare/2.13.3...v2.13.4) (2022-01-24)
+
+### Bug Fixes
+
+* Remove shelljs ([eb4609a](https://github.com/jshint/jshint/commit/eb4609a))
+
## [2.13.3](https://github.com/jshint/jshint/compare/2.13.2...v2.13.3) (2022-01-05)
diff --git a/dist/jshint-rhino.js b/dist/jshint-rhino.js
index 068e40bcc0..7ff7ff6544 100755
--- a/dist/jshint-rhino.js
+++ b/dist/jshint-rhino.js
@@ -1,6 +1,6 @@
#!/usr/bin/env rhino
var window = {};
-/*! 2.13.3 */
+/*! 2.13.4 */
var JSHINT;
if (typeof window === 'undefined') window = {};
(function () {
@@ -1442,14 +1442,15 @@ function isUndefined(arg) {
var undefined;
/** Used as the semantic version number. */
- var VERSION = '4.17.20';
+ var VERSION = '4.17.21';
/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;
/** 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__';
@@ -1582,10 +1583,11 @@ function isUndefined(arg) {
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
reHasRegExpChar = RegExp(reRegExpChar.source);
- /** Used to match leading and trailing whitespace. */
- var reTrim = /^\s+|\s+$/g,
- reTrimStart = /^\s+/,
- reTrimEnd = /\s+$/;
+ /** Used to match leading whitespace. */
+ var reTrimStart = /^\s+/;
+
+ /** Used to match a single whitespace character. */
+ var reWhitespace = /\s/;
/** Used to match wrap detail comments. */
var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
@@ -1595,6 +1597,18 @@ function isUndefined(arg) {
/** 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;
@@ -2423,6 +2437,19 @@ function isUndefined(arg) {
});
}
+ /**
+ * The base implementation of `_.trim`.
+ *
+ * @private
+ * @param {string} string The string to trim.
+ * @returns {string} Returns the trimmed string.
+ */
+ function baseTrim(string) {
+ return string
+ ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')
+ : string;
+ }
+
/**
* The base implementation of `_.unary` without support for storing metadata.
*
@@ -2756,6 +2783,21 @@ function isUndefined(arg) {
: asciiToArray(string);
}
+ /**
+ * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
+ * character of `string`.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @returns {number} Returns the index of the last non-whitespace character.
+ */
+ function trimmedEndIndex(string) {
+ var index = string.length;
+
+ while (index-- && reWhitespace.test(string.charAt(index))) {}
+ return index;
+ }
+
/**
* Used by `_.unescape` to convert HTML entities to characters.
*
@@ -13924,7 +13966,7 @@ function isUndefined(arg) {
if (typeof value != 'string') {
return value === 0 ? value : +value;
}
- value = value.replace(reTrim, '');
+ value = baseTrim(value);
var isBinary = reIsBinary.test(value);
return (isBinary || reIsOctal.test(value))
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
@@ -16296,6 +16338,12 @@ function isUndefined(arg) {
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')
@@ -16409,7 +16457,7 @@ function isUndefined(arg) {
function trim(string, chars, guard) {
string = toString(string);
if (string && (guard || chars === undefined)) {
- return string.replace(reTrim, '');
+ return baseTrim(string);
}
if (!string || !(chars = baseToString(chars))) {
return string;
@@ -16444,7 +16492,7 @@ function isUndefined(arg) {
function trimEnd(string, chars, guard) {
string = toString(string);
if (string && (guard || chars === undefined)) {
- return string.replace(reTrimEnd, '');
+ return string.slice(0, trimmedEndIndex(string) + 1);
}
if (!string || !(chars = baseToString(chars))) {
return string;
diff --git a/dist/jshint.js b/dist/jshint.js
index d0cf46993f..13bc2fe3e5 100644
--- a/dist/jshint.js
+++ b/dist/jshint.js
@@ -1,4 +1,4 @@
-/*! 2.13.3 */
+/*! 2.13.4 */
var JSHINT;
if (typeof window === 'undefined') window = {};
(function () {
@@ -1440,14 +1440,15 @@ function isUndefined(arg) {
var undefined;
/** Used as the semantic version number. */
- var VERSION = '4.17.20';
+ var VERSION = '4.17.21';
/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;
/** 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__';
@@ -1580,10 +1581,11 @@ function isUndefined(arg) {
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
reHasRegExpChar = RegExp(reRegExpChar.source);
- /** Used to match leading and trailing whitespace. */
- var reTrim = /^\s+|\s+$/g,
- reTrimStart = /^\s+/,
- reTrimEnd = /\s+$/;
+ /** Used to match leading whitespace. */
+ var reTrimStart = /^\s+/;
+
+ /** Used to match a single whitespace character. */
+ var reWhitespace = /\s/;
/** Used to match wrap detail comments. */
var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
@@ -1593,6 +1595,18 @@ function isUndefined(arg) {
/** 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;
@@ -2421,6 +2435,19 @@ function isUndefined(arg) {
});
}
+ /**
+ * The base implementation of `_.trim`.
+ *
+ * @private
+ * @param {string} string The string to trim.
+ * @returns {string} Returns the trimmed string.
+ */
+ function baseTrim(string) {
+ return string
+ ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')
+ : string;
+ }
+
/**
* The base implementation of `_.unary` without support for storing metadata.
*
@@ -2754,6 +2781,21 @@ function isUndefined(arg) {
: asciiToArray(string);
}
+ /**
+ * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
+ * character of `string`.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @returns {number} Returns the index of the last non-whitespace character.
+ */
+ function trimmedEndIndex(string) {
+ var index = string.length;
+
+ while (index-- && reWhitespace.test(string.charAt(index))) {}
+ return index;
+ }
+
/**
* Used by `_.unescape` to convert HTML entities to characters.
*
@@ -13922,7 +13964,7 @@ function isUndefined(arg) {
if (typeof value != 'string') {
return value === 0 ? value : +value;
}
- value = value.replace(reTrim, '');
+ value = baseTrim(value);
var isBinary = reIsBinary.test(value);
return (isBinary || reIsOctal.test(value))
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
@@ -16294,6 +16336,12 @@ function isUndefined(arg) {
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')
@@ -16407,7 +16455,7 @@ function isUndefined(arg) {
function trim(string, chars, guard) {
string = toString(string);
if (string && (guard || chars === undefined)) {
- return string.replace(reTrim, '');
+ return baseTrim(string);
}
if (!string || !(chars = baseToString(chars))) {
return string;
@@ -16442,7 +16490,7 @@ function isUndefined(arg) {
function trimEnd(string, chars, guard) {
string = toString(string);
if (string && (guard || chars === undefined)) {
- return string.replace(reTrimEnd, '');
+ return string.slice(0, trimmedEndIndex(string) + 1);
}
if (!string || !(chars = baseToString(chars))) {
return string;
diff --git a/package-lock.json b/package-lock.json
index dc2ddde935..59796046e2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "jshint",
- "version": "2.13.3",
+ "version": "2.13.4",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "jshint",
- "version": "2.13.3",
+ "version": "2.13.4",
"license": "MIT",
"dependencies": {
"cli": "~1.0.0",
diff --git a/package.json b/package.json
index cd7033c0d3..bde37c08db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "jshint",
- "version": "2.13.3",
+ "version": "2.13.4",
"homepage": "http://jshint.com/",
"description": "Static analysis tool for JavaScript",
"author": {