diff --git a/CHANGELOG.md b/CHANGELOG.md index df58ff5..d19c54c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.1.1](https://www.github.com/eslint-community/eslint-plugin-security/compare/v2.1.0...v2.1.1) (2024-02-14) + + +### Bug Fixes + +* Ensure empty eval() doesn't crash detect-eval-with-expression ([#139](https://www.github.com/eslint-community/eslint-plugin-security/issues/139)) ([8a7c7db](https://www.github.com/eslint-community/eslint-plugin-security/commit/8a7c7db1e2b49e2831d510b8dc1db235dee0edf0)) + ## [2.1.0](https://www.github.com/eslint-community/eslint-plugin-security/compare/v2.0.0...v2.1.0) (2023-12-15) diff --git a/README.md b/README.md index d2b77ec..bf5c9fc 100644 --- a/README.md +++ b/README.md @@ -64,21 +64,21 @@ npm test ⚠️ Configurations set to warn in.\ ✅ Set in the `recommended` configuration. -| Name                                  | Description | ⚠️ | -| :------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- | :-- | -| [detect-bidi-characters](docs/rules/detect-bidi-characters.md) | Detects trojan source attacks that employ unicode bidi attacks to inject malicious code. | ✅ | -| [detect-buffer-noassert](docs/rules/detect-buffer-noassert.md) | Detects calls to "buffer" with "noAssert" flag set. | ✅ | -| [detect-child-process](docs/rules/detect-child-process.md) | Detects instances of "child_process" & non-literal "exec()" calls. | ✅ | -| [detect-disable-mustache-escape](docs/rules/detect-disable-mustache-escape.md) | Detects "object.escapeMarkup = false", which can be used with some template engines to disable escaping of HTML entities. | ✅ | -| [detect-eval-with-expression](docs/rules/detect-eval-with-expression.md) | Detects "eval(variable)" which can allow an attacker to run arbitrary code inside your process. | ✅ | -| [detect-new-buffer](docs/rules/detect-new-buffer.md) | Detects instances of new Buffer(argument) where argument is any non-literal value. | ✅ | -| [detect-no-csrf-before-method-override](docs/rules/detect-no-csrf-before-method-override.md) | Detects Express "csrf" middleware setup before "method-override" middleware. | ✅ | -| [detect-non-literal-fs-filename](docs/rules/detect-non-literal-fs-filename.md) | Detects variable in filename argument of "fs" calls, which might allow an attacker to access anything on your system. | ✅ | -| [detect-non-literal-regexp](docs/rules/detect-non-literal-regexp.md) | Detects "RegExp(variable)", which might allow an attacker to DOS your server with a long-running regular expression. | ✅ | -| [detect-non-literal-require](docs/rules/detect-non-literal-require.md) | Detects "require(variable)", which might allow an attacker to load and run arbitrary code, or access arbitrary files on disk. | ✅ | -| [detect-object-injection](docs/rules/detect-object-injection.md) | Detects "variable[key]" as a left- or right-hand assignment operand. | ✅ | -| [detect-possible-timing-attacks](docs/rules/detect-possible-timing-attacks.md) | Detects insecure comparisons (`==`, `!=`, `!==` and `===`), which check input sequentially. | ✅ | -| [detect-pseudoRandomBytes](docs/rules/detect-pseudoRandomBytes.md) | Detects if "pseudoRandomBytes()" is in use, which might not give you the randomness you need and expect. | ✅ | -| [detect-unsafe-regex](docs/rules/detect-unsafe-regex.md) | Detects potentially unsafe regular expressions, which may take a very long time to run, blocking the event loop. | ✅ | +| Name                                  | Description | ⚠️ | +| :------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-- | +| [detect-bidi-characters](docs/rules/detect-bidi-characters.md) | Detects trojan source attacks that employ unicode bidi attacks to inject malicious code. | ✅ | +| [detect-buffer-noassert](docs/rules/detect-buffer-noassert.md) | Detects calls to "buffer" with "noAssert" flag set. | ✅ | +| [detect-child-process](docs/rules/detect-child-process.md) | Detects instances of "child_process" & non-literal "exec()" calls. | ✅ | +| [detect-disable-mustache-escape](docs/rules/detect-disable-mustache-escape.md) | Detects "object.escapeMarkup = false", which can be used with some template engines to disable escaping of HTML entities. | ✅ | +| [detect-eval-with-expression](docs/rules/detect-eval-with-expression.md) | Detects "eval(variable)" which can allow an attacker to run arbitrary code inside your process. | ✅ | +| [detect-new-buffer](docs/rules/detect-new-buffer.md) | Detects instances of new Buffer(argument) where argument is any non-literal value. ([new Buffer(number) is unsafe](https://github.com/nodejs/node/issues/4660)) | ✅ | +| [detect-no-csrf-before-method-override](docs/rules/detect-no-csrf-before-method-override.md) | Detects Express "csrf" middleware setup before "method-override" middleware. | ✅ | +| [detect-non-literal-fs-filename](docs/rules/detect-non-literal-fs-filename.md) | Detects variable in filename argument of "fs" calls, which might allow an attacker to access anything on your system. | ✅ | +| [detect-non-literal-regexp](docs/rules/detect-non-literal-regexp.md) | Detects "RegExp(variable)", which might allow an attacker to DOS your server with a long-running regular expression. | ✅ | +| [detect-non-literal-require](docs/rules/detect-non-literal-require.md) | Detects "require(variable)", which might allow an attacker to load and run arbitrary code, or access arbitrary files on disk. | ✅ | +| [detect-object-injection](docs/rules/detect-object-injection.md) | Detects "variable[key]" as a left- or right-hand assignment operand. | ✅ | +| [detect-possible-timing-attacks](docs/rules/detect-possible-timing-attacks.md) | Detects insecure comparisons (`==`, `!=`, `!==` and `===`), which check input sequentially. | ✅ | +| [detect-pseudoRandomBytes](docs/rules/detect-pseudoRandomBytes.md) | Detects if "pseudoRandomBytes()" is in use, which might not give you the randomness you need and expect. | ✅ | +| [detect-unsafe-regex](docs/rules/detect-unsafe-regex.md) | Detects potentially unsafe regular expressions, which may take a very long time to run, blocking the event loop. | ✅ | diff --git a/docs/rules/detect-new-buffer.md b/docs/rules/detect-new-buffer.md index cd8c71c..e5eda5e 100644 --- a/docs/rules/detect-new-buffer.md +++ b/docs/rules/detect-new-buffer.md @@ -3,3 +3,7 @@ ⚠️ This rule _warns_ in the ✅ `recommended` config. + +`new Buffer()` now emits a deprecation warning in Node.js. + +More information: [new Buffer(number) is unsafe](https://github.com/nodejs/node/issues/4660) diff --git a/docs/rules/detect-object-injection.md b/docs/rules/detect-object-injection.md index ff42a5a..de3a778 100644 --- a/docs/rules/detect-object-injection.md +++ b/docs/rules/detect-object-injection.md @@ -4,4 +4,35 @@ +JavaScript allows you to use expressions to access object properties in addition to using dot notation. So instead of writing this: + +```js +object.name = 'foo'; +``` + +You can write this: + +```js +object['name'] = 'foo'; +``` + +Square bracket notation allows any expression to be used in place of an identifier, so you can also do this: + +```js +const key = 'name'; +object[key] = 'foo'; +``` + +By doing so, you've now obfuscated the property name from the reader, which makes it easy for a malicious actor to replace the value of `key` and change the behavior of the code. + +This rule flags any expression in the form of `object[expression]` no matter where it occurs. Examples of patterns this will be flagged are: + +```js +object[key] = value; + +value = object[key]; + +doSomething(object[key]); +``` + More information: [The Dangers of Square Bracket Notation](../the-dangers-of-square-bracket-notation.md) diff --git a/package-lock.json b/package-lock.json index 07c3f42..7123ad8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "eslint-plugin-security", - "version": "2.1.0", + "version": "2.1.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "eslint-plugin-security", - "version": "2.1.0", + "version": "2.1.1", "license": "Apache-2.0", "dependencies": { "safe-regex": "^2.1.1" diff --git a/package.json b/package.json index aa5fe6e..56e6bc9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-security", - "version": "2.1.0", + "version": "2.1.1", "description": "Security rules for eslint", "main": "index.js", "scripts": { diff --git a/rules/detect-eval-with-expression.js b/rules/detect-eval-with-expression.js index 59b428c..4005475 100644 --- a/rules/detect-eval-with-expression.js +++ b/rules/detect-eval-with-expression.js @@ -19,10 +19,10 @@ module.exports = { url: 'https://github.com/eslint-community/eslint-plugin-security/blob/main/docs/rules/detect-eval-with-expression.md', }, }, - create: function (context) { + create(context) { return { - CallExpression: function (node) { - if (node.callee.name === 'eval' && node.arguments[0].type !== 'Literal') { + CallExpression(node) { + if (node.callee.name === 'eval' && node.arguments.length && node.arguments[0].type !== 'Literal') { context.report({ node: node, message: `eval with argument of type ${node.arguments[0].type}` }); } }, diff --git a/test/rules/detect-eval-with-expression.js b/test/rules/detect-eval-with-expression.js index fe00156..28a49f6 100644 --- a/test/rules/detect-eval-with-expression.js +++ b/test/rules/detect-eval-with-expression.js @@ -6,7 +6,7 @@ const tester = new RuleTester(); const ruleName = 'detect-eval-with-expression'; tester.run(ruleName, require(`../../rules/${ruleName}`), { - valid: [{ code: "eval('alert()')" }], + valid: [{ code: "eval('alert()')" }, { code: 'eval("some nefarious code");' }, { code: 'eval()' }], invalid: [ { code: 'eval(a);',