From 5dbc55c29518cf16b749ad4f1764867e1eb67f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=AF=E7=84=B6?= Date: Thu, 14 Dec 2023 10:38:30 +0800 Subject: [PATCH 1/2] feat: add config recommended-legacy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit it also moves rule tests to `./test/rules`, and adds a test for the configs. fixes #131 Signed-off-by: 唯然 --- .eslint-doc-generatorrc.js | 1 + README.md | 18 ++++++++++++++++-- index.js | 10 +++++++++- test/configs/index.js | 16 ++++++++++++++++ test/{ => rules}/detect-bidi-characters.js | 4 ++-- test/{ => rules}/detect-buffer-noassert.js | 2 +- test/{ => rules}/detect-child-process.js | 2 +- .../detect-disable-mustache-escape.js | 2 +- .../{ => rules}/detect-eval-with-expression.js | 2 +- test/{ => rules}/detect-new-buffer.js | 2 +- .../detect-no-csrf-before-method-override.js | 2 +- .../detect-non-literal-fs-filename.js | 4 ++-- test/{ => rules}/detect-non-literal-regexp.js | 2 +- test/{ => rules}/detect-non-literal-require.js | 2 +- test/{ => rules}/detect-object-injection.js | 2 +- .../detect-possible-timing-attacks.js | 2 +- test/{ => rules}/detect-pseudoRandomBytes.js | 2 +- test/{ => rules}/detect-unsafe-regexp.js | 2 +- 18 files changed, 58 insertions(+), 19 deletions(-) create mode 100644 test/configs/index.js rename test/{ => rules}/detect-bidi-characters.js (97%) rename test/{ => rules}/detect-buffer-noassert.js (95%) rename test/{ => rules}/detect-child-process.js (98%) rename test/{ => rules}/detect-disable-mustache-escape.js (84%) rename test/{ => rules}/detect-eval-with-expression.js (84%) rename test/{ => rules}/detect-new-buffer.js (84%) rename test/{ => rules}/detect-no-csrf-before-method-override.js (87%) rename test/{ => rules}/detect-non-literal-fs-filename.js (99%) rename test/{ => rules}/detect-non-literal-regexp.js (89%) rename test/{ => rules}/detect-non-literal-require.js (92%) rename test/{ => rules}/detect-object-injection.js (95%) rename test/{ => rules}/detect-possible-timing-attacks.js (94%) rename test/{ => rules}/detect-pseudoRandomBytes.js (87%) rename test/{ => rules}/detect-unsafe-regexp.js (92%) diff --git a/.eslint-doc-generatorrc.js b/.eslint-doc-generatorrc.js index 6b2ce31..ca5455a 100644 --- a/.eslint-doc-generatorrc.js +++ b/.eslint-doc-generatorrc.js @@ -3,6 +3,7 @@ const prettierRC = require('./.prettierrc.json'); /** @type {import('eslint-doc-generator').GenerateOptions} */ const config = { + ignoreConfig: ['recommended-legacy'], postprocess: (doc) => format(doc, { ...prettierRC, parser: 'markdown' }), }; diff --git a/README.md b/README.md index e149735..462bbc7 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,8 @@ yarn add --dev eslint-plugin-security ## Usage +### Flat config (requires eslint >= v8.23.0) + Add the following to your `eslint.config.js` file: ```js @@ -28,6 +30,17 @@ const pluginSecurity = require('eslint-plugin-security'); module.exports = [pluginSecurity.configs.recommended]; ``` +### eslintrc config (deprecated) + +Add the following to your `.eslintrc` file: + +````js +module.exports = { + "extends": [ + "plugin:security/recommended-legacy" + ] +} + ## Developer guide - Use [GitHub pull requests](https://help.github.com/articles/using-pull-requests). @@ -52,8 +65,8 @@ npm test ⚠️ Configurations set to warn in.\ ✅ Set in the `recommended` configuration. -| Name                                  | Description | ⚠️ | -| :------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- | :-- | +| 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. | ✅ | @@ -70,3 +83,4 @@ npm test | [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/index.js b/index.js index e77966f..68f2b0b 100644 --- a/index.js +++ b/index.js @@ -66,6 +66,14 @@ const recommended = { }, }; -Object.assign(plugin.configs, { recommended }); +const recommendedLegacy = { + plugins: ['security'], + rules: recommended.rules, +}; + +Object.assign(plugin.configs, { + recommended, + 'recommended-legacy': recommendedLegacy +}); module.exports = plugin; diff --git a/test/configs/index.js b/test/configs/index.js new file mode 100644 index 0000000..d5fb093 --- /dev/null +++ b/test/configs/index.js @@ -0,0 +1,16 @@ +'use strict'; +const plugin = require('../../index.js'); +const assert = require('assert').strict; + +describe('export plugin object', () => { + it('should export rules', () => { + assert(plugin.rules); + assert(typeof plugin.rules['detect-unsafe-regex'] === 'object'); + }); + + it('should export configs', () => { + assert(plugin.configs); + assert(plugin.configs['recommended']); + assert(plugin.configs['recommended-legacy']); + }); +}); diff --git a/test/detect-bidi-characters.js b/test/rules/detect-bidi-characters.js similarity index 97% rename from test/detect-bidi-characters.js rename to test/rules/detect-bidi-characters.js index 9311b8b..cb3e09b 100644 --- a/test/detect-bidi-characters.js +++ b/test/rules/detect-bidi-characters.js @@ -4,7 +4,7 @@ const RuleTester = require('eslint').RuleTester; const tester = new RuleTester(); const ruleName = 'detect-bidi-characters'; -const Rule = require(`../rules/${ruleName}`); +const Rule = require(`../../rules/${ruleName}`); tester.run(ruleName, Rule, { valid: [ @@ -54,7 +54,7 @@ tester.run(`${ruleName} in comment-line`, Rule, { console.log("You are an admin."); /* end admins only ‮ ⁦*/ - /* end admins only ‮ + /* end admins only ‮ { ⁦*/ `, errors: [ diff --git a/test/detect-buffer-noassert.js b/test/rules/detect-buffer-noassert.js similarity index 95% rename from test/detect-buffer-noassert.js rename to test/rules/detect-buffer-noassert.js index e9bee5e..95e387b 100644 --- a/test/detect-buffer-noassert.js +++ b/test/rules/detect-buffer-noassert.js @@ -4,7 +4,7 @@ const RuleTester = require('eslint').RuleTester; const tester = new RuleTester(); const ruleName = 'detect-buffer-noassert'; -const rule = require(`../rules/${ruleName}`); +const rule = require(`../../rules/${ruleName}`); const allMethodNames = [...rule.meta.__methodsToCheck.read, ...rule.meta.__methodsToCheck.write]; diff --git a/test/detect-child-process.js b/test/rules/detect-child-process.js similarity index 98% rename from test/detect-child-process.js rename to test/rules/detect-child-process.js index efc45fd..03f9b4b 100644 --- a/test/detect-child-process.js +++ b/test/rules/detect-child-process.js @@ -9,7 +9,7 @@ const tester = new RuleTester({ }); const ruleName = 'detect-child-process'; -const rule = require(`../rules/${ruleName}`); +const rule = require(`../../rules/${ruleName}`); tester.run(ruleName, rule, { valid: [ diff --git a/test/detect-disable-mustache-escape.js b/test/rules/detect-disable-mustache-escape.js similarity index 84% rename from test/detect-disable-mustache-escape.js rename to test/rules/detect-disable-mustache-escape.js index bc3aa5a..021a49e 100644 --- a/test/detect-disable-mustache-escape.js +++ b/test/rules/detect-disable-mustache-escape.js @@ -5,7 +5,7 @@ const tester = new RuleTester(); const ruleName = 'detect-disable-mustache-escape'; -tester.run(ruleName, require(`../rules/${ruleName}`), { +tester.run(ruleName, require(`../../rules/${ruleName}`), { valid: [{ code: 'escapeMarkup = false' }], invalid: [ { diff --git a/test/detect-eval-with-expression.js b/test/rules/detect-eval-with-expression.js similarity index 84% rename from test/detect-eval-with-expression.js rename to test/rules/detect-eval-with-expression.js index 338a1bc..fe00156 100644 --- a/test/detect-eval-with-expression.js +++ b/test/rules/detect-eval-with-expression.js @@ -5,7 +5,7 @@ const tester = new RuleTester(); const ruleName = 'detect-eval-with-expression'; -tester.run(ruleName, require(`../rules/${ruleName}`), { +tester.run(ruleName, require(`../../rules/${ruleName}`), { valid: [{ code: "eval('alert()')" }], invalid: [ { diff --git a/test/detect-new-buffer.js b/test/rules/detect-new-buffer.js similarity index 84% rename from test/detect-new-buffer.js rename to test/rules/detect-new-buffer.js index 4dc1b76..6d266b9 100644 --- a/test/detect-new-buffer.js +++ b/test/rules/detect-new-buffer.js @@ -6,7 +6,7 @@ const tester = new RuleTester(); const ruleName = 'detect-new-buffer'; const invalid = 'var a = new Buffer(c)'; -tester.run(ruleName, require(`../rules/${ruleName}`), { +tester.run(ruleName, require(`../../rules/${ruleName}`), { valid: [{ code: "var a = new Buffer('test')" }], invalid: [ { diff --git a/test/detect-no-csrf-before-method-override.js b/test/rules/detect-no-csrf-before-method-override.js similarity index 87% rename from test/detect-no-csrf-before-method-override.js rename to test/rules/detect-no-csrf-before-method-override.js index 10c0670..1b65bfa 100644 --- a/test/detect-no-csrf-before-method-override.js +++ b/test/rules/detect-no-csrf-before-method-override.js @@ -5,7 +5,7 @@ const tester = new RuleTester(); const ruleName = 'detect-no-csrf-before-method-override'; -tester.run(ruleName, require(`../rules/${ruleName}`), { +tester.run(ruleName, require(`../../rules/${ruleName}`), { valid: [{ code: 'express.methodOverride();express.csrf()' }], invalid: [ { diff --git a/test/detect-non-literal-fs-filename.js b/test/rules/detect-non-literal-fs-filename.js similarity index 99% rename from test/detect-non-literal-fs-filename.js rename to test/rules/detect-non-literal-fs-filename.js index 8d5bd30..560db86 100644 --- a/test/detect-non-literal-fs-filename.js +++ b/test/rules/detect-non-literal-fs-filename.js @@ -10,7 +10,7 @@ const tester = new RuleTester({ const ruleName = 'detect-non-literal-fs-filename'; -tester.run(ruleName, require(`../rules/${ruleName}`), { +tester.run(ruleName, require(`../../rules/${ruleName}`), { valid: [ { code: `var fs = require('fs'); @@ -29,7 +29,7 @@ tester.run(ruleName, require(`../rules/${ruleName}`), { import { promises as fsp } from 'fs'; import fs from 'fs'; import path from 'path'; - + const index = await fsp.readFile(path.resolve(__dirname, './index.html'), 'utf-8'); const key = fs.readFileSync(path.join(__dirname, './ssl.key')); await fsp.writeFile(path.resolve(__dirname, './sitemap.xml'), sitemap);`, diff --git a/test/detect-non-literal-regexp.js b/test/rules/detect-non-literal-regexp.js similarity index 89% rename from test/detect-non-literal-regexp.js rename to test/rules/detect-non-literal-regexp.js index af5e054..39037c4 100644 --- a/test/detect-non-literal-regexp.js +++ b/test/rules/detect-non-literal-regexp.js @@ -6,7 +6,7 @@ const tester = new RuleTester(); const ruleName = 'detect-non-literal-regexp'; const invalid = "var a = new RegExp(c, 'i')"; -tester.run(ruleName, require(`../rules/${ruleName}`), { +tester.run(ruleName, require(`../../rules/${ruleName}`), { valid: [ { code: "var a = new RegExp('ab+c', 'i')" }, { diff --git a/test/detect-non-literal-require.js b/test/rules/detect-non-literal-require.js similarity index 92% rename from test/detect-non-literal-require.js rename to test/rules/detect-non-literal-require.js index 1d15c21..49a6e7a 100644 --- a/test/detect-non-literal-require.js +++ b/test/rules/detect-non-literal-require.js @@ -6,7 +6,7 @@ const tester = new RuleTester({ parserOptions: { ecmaVersion: 6 } }); const ruleName = 'detect-non-literal-require'; -tester.run(ruleName, require(`../rules/${ruleName}`), { +tester.run(ruleName, require(`../../rules/${ruleName}`), { valid: [ { code: "var a = require('b')" }, { code: 'var a = require(`b`)' }, diff --git a/test/detect-object-injection.js b/test/rules/detect-object-injection.js similarity index 95% rename from test/detect-object-injection.js rename to test/rules/detect-object-injection.js index 6091ac5..8867f6c 100644 --- a/test/detect-object-injection.js +++ b/test/rules/detect-object-injection.js @@ -5,7 +5,7 @@ const tester = new RuleTester(); const ruleName = 'detect-object-injection'; -const Rule = require(`../rules/${ruleName}`); +const Rule = require(`../../rules/${ruleName}`); const valid = 'var a = {};'; // const invalidVariable = "TODO"; diff --git a/test/detect-possible-timing-attacks.js b/test/rules/detect-possible-timing-attacks.js similarity index 94% rename from test/detect-possible-timing-attacks.js rename to test/rules/detect-possible-timing-attacks.js index 34a6136..9b8c9ac 100644 --- a/test/detect-possible-timing-attacks.js +++ b/test/rules/detect-possible-timing-attacks.js @@ -4,7 +4,7 @@ const RuleTester = require('eslint').RuleTester; const tester = new RuleTester(); const ruleName = 'detect-possible-timing-attacks'; -const Rule = require(`../rules/${ruleName}`); +const Rule = require(`../../rules/${ruleName}`); const valid = 'if (age === 5) {}'; const invalidLeft = "if (password === 'mypass') {}"; diff --git a/test/detect-pseudoRandomBytes.js b/test/rules/detect-pseudoRandomBytes.js similarity index 87% rename from test/detect-pseudoRandomBytes.js rename to test/rules/detect-pseudoRandomBytes.js index 0162a46..245aeec 100644 --- a/test/detect-pseudoRandomBytes.js +++ b/test/rules/detect-pseudoRandomBytes.js @@ -6,7 +6,7 @@ const tester = new RuleTester(); const ruleName = 'detect-pseudoRandomBytes'; const invalid = 'crypto.pseudoRandomBytes'; -tester.run(ruleName, require(`../rules/${ruleName}`), { +tester.run(ruleName, require(`../../rules/${ruleName}`), { valid: [{ code: 'crypto.randomBytes' }], invalid: [ { diff --git a/test/detect-unsafe-regexp.js b/test/rules/detect-unsafe-regexp.js similarity index 92% rename from test/detect-unsafe-regexp.js rename to test/rules/detect-unsafe-regexp.js index 077a355..09095fd 100644 --- a/test/detect-unsafe-regexp.js +++ b/test/rules/detect-unsafe-regexp.js @@ -4,7 +4,7 @@ const RuleTester = require('eslint').RuleTester; const tester = new RuleTester(); const ruleName = 'detect-unsafe-regex'; -const Rule = require(`../rules/${ruleName}`); +const Rule = require(`../../rules/${ruleName}`); tester.run(ruleName, Rule, { valid: [{ code: '/^d+1337d+$/' }], From 88741a3741d8f5f755de5ceed5fef5794d278b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=AF=E7=84=B6?= Date: Fri, 15 Dec 2023 00:43:33 +0800 Subject: [PATCH 2/2] fix: eslint-docs --- README.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 462bbc7..d2b77ec 100644 --- a/README.md +++ b/README.md @@ -34,12 +34,11 @@ module.exports = [pluginSecurity.configs.recommended]; Add the following to your `.eslintrc` file: -````js +```js module.exports = { - "extends": [ - "plugin:security/recommended-legacy" - ] -} + extends: ['plugin:security/recommended-legacy'], +}; +``` ## Developer guide @@ -65,8 +64,8 @@ npm test ⚠️ Configurations set to warn in.\ ✅ Set in the `recommended` configuration. -| Name                                  | Description | ⚠️ | -| :------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- | :- | +| 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. | ✅ | @@ -83,4 +82,3 @@ npm test | [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. | ✅ | -````