Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

eslint-plugin-security

Package Overview
Dependencies
Maintainers
4
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-security - npm Package Compare versions

Comparing version 1.4.0 to 1.5.0

.github/workflows/ci.yml

85

CHANGELOG.md

@@ -1,34 +0,65 @@

1.4.0 / 2017-06-12
==================
* Add recommended ruleset to the usage example
* Removes filenames from error output
1.3.0 / 2017-02-09
==================
# 1.4.0 / 2017-06-12
* README.md - document detect-disable-mustache-escape rule
* README.md - documentation detect-new-buffer rule
* Fixed crash with `detect-no-csrf-before-method-override` rule.
* Style guide applied to all the code involving the tests
* Removing a repeated test and style changes
* ESLint added to the workflow
* Removed not needed variables
* Fix to a problem with a rule detected implementing the tests
* Test engine with tests for all the rules
* Add additional information to README for each rule
- 1.4.0
- Stuff and things for 1.4.0 beep boop 🤖
- Merge pull request [#14](https://github.com/nodesecurity/eslint-plugin-security/issues/14) from travi/recommended-example
Add recommended ruleset to the usage example
- Merge pull request [#19](https://github.com/nodesecurity/eslint-plugin-security/issues/19) from pdehaan/add-changelog
Add basic CHANGELOG.md file
- Merge pull request [#17](https://github.com/nodesecurity/eslint-plugin-security/issues/17) from pdehaan/issue-16
Remove filename from error output
- Add basic CHANGELOG.md file
- Remove filename from error output
- Add recommended ruleset to the usage example
for [#9](https://github.com/nodesecurity/eslint-plugin-security/issues/9)
- Merge pull request [#10](https://github.com/nodesecurity/eslint-plugin-security/issues/10) from pdehaan/issue-9
Add 'plugin:security/recommended' config to plugin
- Merge pull request [#12](https://github.com/nodesecurity/eslint-plugin-security/issues/12) from tupaschoal/patch-1
Fix broken link for detect-object-injection
- Fix broken link for detect-object-injection
The current link leads to a 404 page, the new one is the proper page.
- Add 'plugin:security/recommended' config to plugin
1.2.0 / 2016-01-21
==================
# 1.3.0 / 2017-02-09
* updated to check for new RegExp too
- 1.3.0
- Merge branch 'scottnonnenberg-update-docs'
- Fix merge conflicts because I can't figure out how to accept pr's in the right order
- Merge pull request [#7](https://github.com/nodesecurity/eslint-plugin-security/issues/7) from HamletDRC/patch-1
README.md - documentation detect-new-buffer rule
- Merge pull request [#8](https://github.com/nodesecurity/eslint-plugin-security/issues/8) from HamletDRC/patch-2
README.md - document detect-disable-mustache-escape rule
- Merge pull request [#3](https://github.com/nodesecurity/eslint-plugin-security/issues/3) from jesusprubio/master
A bit of love
- README.md - document detect-disable-mustache-escape rule
- README.md - documentation detect-new-buffer rule
- Merge pull request [#6](https://github.com/nodesecurity/eslint-plugin-security/issues/6) from mathieumg/csrf-bug
Fixed crash with `detect-no-csrf-before-method-override` rule
- Fixed crash with `detect-no-csrf-before-method-override` rule.
- Finishing last commit
- Style guide applied to all the code involving the tests
- Removing a repeated test and style changes
- ESLint added to the workflow
- Removed not needed variables
- Fix to a problem with a rule detected implementing the tests
- Test engine with tests for all the rules
- Minor typos
- A little bit of massage to readme intro
- Add additional information to README for each rule
1.1.0 / 2016-01-06
==================
# 1.2.0 / 2016-01-21
* adding eslint rule to detect new buffer hotspot
- 1.2.0
- updated to check for new RegExp too
1.0.0 / 2015-11-15
==================
# 1.1.0 / 2016-01-06
* rules disabled by default
- 1.1.0
- adding eslint rule to detect new buffer hotspot
# 1.0.0 / 2015-11-15
- updated desc
- rules disabled by default
- update links
- beep boop

@@ -40,5 +40,3 @@ /**

recommended: {
plugins: [
'security'
],
plugins: ['security'],
rules: {

@@ -45,0 +43,0 @@ 'security/detect-buffer-noassert': 'warn',

{
"name": "eslint-plugin-security",
"version": "1.4.0",
"version": "1.5.0",
"description": "Security rules for eslint",

@@ -8,5 +8,8 @@ "main": "index.js",

"changelog": "changelog eslint-plugin-security all > CHANGELOG.md",
"test": "./node_modules/.bin/mocha test/**/*",
"lint": "./node_modules/.bin/eslint .",
"cont-int": "npm test && npm run-script lint"
"release": "npx semantic-release",
"test": "mocha test/**/*",
"format": "prettier --write **/*.{md,js,yml}",
"lint": "eslint .",
"lint:fix": "eslint --fix .",
"cont-int": "npm test && npm run lint"
},

@@ -28,11 +31,27 @@ "repository": {

"homepage": "https://github.com/nodesecurity/eslint-plugin-security#readme",
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.js": [
"prettier --write",
"eslint --fix"
],
"*.md": "prettier --write",
"*.yml": "prettier --write"
},
"dependencies": {
"safe-regex": "^1.1.0"
"safe-regex": "^2.1.1"
},
"devDependencies": {
"changelog": "1.3.0",
"eslint": "^2.10.1",
"eslint": "^8.11.0",
"eslint-config-nodesecurity": "^1.3.1",
"mocha": "^2.4.5"
"eslint-config-prettier": "^8.5.0",
"lint-staged": "^12.3.7",
"mocha": "^9.2.2",
"prettier": "^2.6.2",
"semantic-release": "^19.0.2",
"yorkie": "^2.0.0"
}
}

@@ -9,3 +9,3 @@ # eslint-plugin-security

`npm install --save-dev eslint-plugin-security`
`npm install --save-dev eslint-plugin-security` or `yarn add eslint-plugin-security --dev`

@@ -17,5 +17,2 @@ ### Usage

```js
"plugins": [
"security"
],
"extends": [

@@ -26,3 +23,2 @@ "plugin:security/recommended"

## Developer guide

@@ -32,9 +28,11 @@

- Conventions:
- We use our [custom ESLint setup](https://github.com/nodesecurity/eslint-config-nodesecurity).
- Please implement a test for each new rule and use this command to be sure the new code respects the style guide and the tests keep passing:
```sh
npm run-script cont-int
```
- We use our [custom ESLint setup](https://github.com/nodesecurity/eslint-config-nodesecurity).
- Please implement a test for each new rule and use this command to be sure the new code respects the style guide and the tests keep passing:
```sh
npm run-script cont-int
```
### Tests
```sh

@@ -50,7 +48,7 @@ npm test

More information: https://blog.liftsecurity.io/2014/11/03/regular-expression-dos-and-node.js
More information: [Regular Expression DoS and Node.js](docs/regular-expression-dos-and-node.md)
#### `detect-buffer-noassert`
Detects calls to [`buffer`](https://nodejs.org/api/buffer.html) with `noAssert` flag set
Detect calls to [`buffer`](https://nodejs.org/api/buffer.html) with `noAssert` flag set.

@@ -61,5 +59,5 @@ From the Node.js API docs: "Setting `noAssert` to true skips validation of the `offset`. This allows the `offset` to be beyond the end of the `Buffer`."

Detects instances of [`child_process`](https://nodejs.org/api/child_process.html) & non-literal [`exec()`](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback)
Detect instances of [`child_process`](https://nodejs.org/api/child_process.html) & non-literal [`exec()`](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback)
More information: https://blog.liftsecurity.io/2014/08/19/Avoid-Command-Injection-Node.js
More information: [Avoiding Command Injection in Node.js](docs/avoid-command-injection-node.md)

@@ -70,9 +68,9 @@ #### `detect-disable-mustache-escape`

More information: https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
More information: [OWASP XSS](<https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)>)
#### `detect-eval-with-expression`
Detects `eval(variable)` which can allow an attacker to run arbitary code inside your process.
Detects `eval(variable)` which can allow an attacker to run arbitrary code inside your process.
More information: http://security.stackexchange.com/questions/94017/what-are-the-security-issues-with-eval-in-javascript
More information: [What are the security issues with eval in JavaScript?](http://security.stackexchange.com/questions/94017/what-are-the-security-issues-with-eval-in-javascript)

@@ -83,3 +81,3 @@ #### `detect-no-csrf-before-method-override`

More information: https://blog.liftsecurity.io/2013/09/07/bypass-connect-csrf-protection-by-abusing
More information: [Bypass Connect CSRF protection by abusing methodOverride Middleware](docs/bypass-connect-csrf-protection-by-abusing.md)

@@ -90,3 +88,3 @@ #### `detect-non-literal-fs-filename`

More information: https://www.owasp.org/index.php/Path_Traversal
More information: [OWASP Path Traversal](https://www.owasp.org/index.php/Path_Traversal)

@@ -97,3 +95,3 @@ #### `detect-non-literal-regexp`

More information: https://blog.liftsecurity.io/2014/11/03/regular-expression-dos-and-node.js
More information: [Regular Expression DoS and Node.js](docs/regular-expression-dos-and-node.md)

@@ -104,3 +102,3 @@ #### `detect-non-literal-require`

More information: http://www.bennadel.com/blog/2169-where-does-node-js-and-require-look-for-modules.htm
More information: [Where does Node.js and require look for modules?](http://www.bennadel.com/blog/2169-where-does-node-js-and-require-look-for-modules.htm)

@@ -111,3 +109,3 @@ #### `detect-object-injection`

More information: https://blog.liftsecurity.io/2015/01/14/the-dangers-of-square-bracket-notation/
More information: [The Dangers of Square Bracket Notation](docs/the-dangers-of-square-bracket-notation.md)

@@ -118,3 +116,3 @@ #### `detect-possible-timing-attacks`

More information: https://snyk.io/blog/node-js-timing-attack-ccc-ctf/
More information: [A lesson in timing attacks](https://codahale.com/a-lesson-in-timing-attacks/)

@@ -125,2 +123,6 @@ #### `detect-pseudoRandomBytes`

More information: http://stackoverflow.com/questions/18130254/randombytes-vs-pseudorandombytes
More information: [Randombytes vs pseudorandombytes](http://stackoverflow.com/questions/18130254/randombytes-vs-pseudorandombytes)
#### `detect-new-buffer`
Detect instances of new Buffer(argument) where argument is any non-literal value.
{
"appendFile": [0],
"appendFileSync": [0],
"chmod": [0],
"chmodSync": [0],
"chown": [0],
"chownSync": [0],
"createReadStream": [0],
"createWriteStream": [0],
"exists": [0],
"existsSync": [0],
"lchmod": [0],
"lchmodSync": [0],
"lchown": [0],
"lchownSync": [0],
"link": [0,1],
"linkSync": [0,1],
"lstat": [0],
"lstatSync": [0],
"mkdir": [0],
"mkdirSync": [0],
"open": [0],
"openSync": [0],
"readdir": [0],
"readdirSync": [0],
"readFile": [0],
"readFileSync": [0],
"readlink": [0],
"readlinkSync": [0],
"realpath": [0],
"realpathSync": [0],
"rename": [0,1],
"renameSync": [0,1],
"rmdir": [0],
"rmdirSync": [0],
"stat": [0],
"statSync": [0],
"symlink": [0,1],
"symlinkSync": [0,1],
"truncate": [0],
"truncateSync": [0],
"unlink": [0],
"unlinkSync": [0],
"unwatchFile": [0],
"utimes": [0],
"utimesSync": [0],
"watch": [0],
"watchFile": [0],
"writeFile": [0],
"writeFileSync": [0]
"appendFile": [0],
"appendFileSync": [0],
"chmod": [0],
"chmodSync": [0],
"chown": [0],
"chownSync": [0],
"createReadStream": [0],
"createWriteStream": [0],
"exists": [0],
"existsSync": [0],
"lchmod": [0],
"lchmodSync": [0],
"lchown": [0],
"lchownSync": [0],
"link": [0, 1],
"linkSync": [0, 1],
"lstat": [0],
"lstatSync": [0],
"mkdir": [0],
"mkdirSync": [0],
"open": [0],
"openSync": [0],
"readdir": [0],
"readdirSync": [0],
"readFile": [0],
"readFileSync": [0],
"readlink": [0],
"readlinkSync": [0],
"realpath": [0],
"realpathSync": [0],
"rename": [0, 1],
"renameSync": [0, 1],
"rmdir": [0],
"rmdirSync": [0],
"stat": [0],
"statSync": [0],
"symlink": [0, 1],
"symlinkSync": [0, 1],
"truncate": [0],
"truncateSync": [0],
"unlink": [0],
"unlinkSync": [0],
"unwatchFile": [0],
"utimes": [0],
"utimesSync": [0],
"watch": [0],
"watchFile": [0],
"writeFile": [0],
"writeFileSync": [0]
}
/**
* Tries to detect buffer read / write calls that use noAssert set to true
* @author Adam Baldwin
* @author Adam Baldwin
*/
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
'use strict';
var names = [];
//-----------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------
module.exports = function(context) {
const read = [
'readUInt8',
'readUInt16LE',
'readUInt16BE',
'readUInt32LE',
'readUInt32BE',
'readInt8',
'readInt16LE',
'readInt16BE',
'readInt32LE',
'readInt32BE',
'readFloatLE',
'readFloatBE',
'readDoubleLE',
'readDoubleBE',
];
"use strict";
const write = [
'writeUInt8',
'writeUInt16LE',
'writeUInt16BE',
'writeUInt32LE',
'writeUInt32BE',
'writeInt8',
'writeInt16LE',
'writeInt16BE',
'writeInt32LE',
'writeInt32BE',
'writeFloatLE',
'writeFloatBE',
'writeDoubleLE',
'writeDoubleBE',
];
var read = [
"readUInt8",
"readUInt16LE",
"readUInt16BE",
"readUInt32LE",
"readUInt32BE",
"readInt8",
"readInt16LE",
"readInt16BE",
"readInt32LE",
"readInt32BE",
"readFloatLE",
"readFloatBE",
"readDoubleL",
"readDoubleBE"
];
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
var write = [
"writeUInt8",
"writeUInt16LE",
"writeUInt16BE",
"writeUInt32LE",
"writeUInt32BE",
"writeInt8",
"writeInt16LE",
"writeInt16BE",
"writeInt32LE",
"writeInt32BE",
"writeFloatLE",
"writeFloatBE",
"writeDoubleLE",
"writeDoubleBE"
];
module.exports = {
meta: {
type: 'error',
docs: {
description: 'Detect calls to "buffer" with "noAssert" flag set.',
category: 'Possible Security Vulnerability',
recommended: true,
url: 'https://github.com/nodesecurity/eslint-plugin-security#detect-buffer-noassert',
},
__methodsToCheck: {
read,
write,
},
},
create: function (context) {
return {
"MemberExpression": function (node) {
var index;
if (read.indexOf(node.property.name) !== -1) {
index = 1;
} else if (write.indexOf(node.property.name) !== -1) {
index = 2;
}
MemberExpression: function (node) {
let index;
if (read.indexOf(node.property.name) !== -1) {
index = 1;
} else if (write.indexOf(node.property.name) !== -1) {
index = 2;
}
if (index && node.parent && node.parent.arguments && node.parent.arguments[index] && node.parent.arguments[index].value) {
var token = context.getTokens(node)[0];
return context.report(node, 'Found Buffer.' + node.property.name + ' with noAssert flag set true');
}
if (index && node.parent && node.parent.arguments && node.parent.arguments[index] && node.parent.arguments[index].value) {
return context.report(node, `Found Buffer.${node.property.name} with noAssert flag set true`);
}
},
};
},
};

@@ -6,2 +6,4 @@ /**

'use strict';
//------------------------------------------------------------------------------

@@ -11,34 +13,41 @@ // Rule Definition

var names = [];
/*
* Stores variable names pointing to child_process to check (child_process).exec()
*/
const names = [];
module.exports = function(context) {
"use strict";
module.exports = {
meta: {
type: 'error',
docs: {
description: 'Detect instances of "child_process" & non-literal "exec()" calls.',
category: 'Possible Security Vulnerability',
recommended: true,
url: 'https://github.com/nodesecurity/eslint-plugin-security/blob/main/docs/avoid-command-injection-node.md',
},
},
create: function (context) {
return {
"CallExpression": function (node) {
var token = context.getTokens(node)[0];
if (node.callee.name === 'require') {
var args = node.arguments[0];
if (args && args.type === 'Literal' && args.value === 'child_process') {
if (node.parent.type === 'VariableDeclarator') {
names.push(node.parent.id.name);
} else if (node.parent.type === 'AssignmentExpression' && node.parent.operator === '=') {
names.push(node.parent.left.name);
}
return context.report(node, 'Found require("child_process")');
}
CallExpression: function (node) {
if (node.callee.name === 'require') {
const args = node.arguments[0];
if (args && args.type === 'Literal' && args.value === 'child_process') {
if (node.parent.type === 'VariableDeclarator') {
names.push(node.parent.id.name);
} else if (node.parent.type === 'AssignmentExpression' && node.parent.operator === '=') {
names.push(node.parent.left.name);
}
},
"MemberExpression": function (node) {
var token = context.getTokens(node)[0];
if (node.property.name === 'exec' && names.indexOf(node.object.name) > -1) {
if (node.parent && node.parent.arguments && node.parent.arguments[0].type !== 'Literal') {
return context.report(node, 'Found child_process.exec() with non Literal first argument');
}
}
return context.report(node, 'Found require("child_process")');
}
}
},
MemberExpression: function (node) {
if (node.property.name === 'exec' && names.indexOf(node.object.name) > -1) {
if (node.parent && node.parent.arguments.length && node.parent.arguments[0].type !== 'Literal') {
return context.report(node, 'Found child_process.exec() with non Literal first argument');
}
}
},
};
},
};

@@ -1,18 +0,28 @@

module.exports = function(context) {
'use strict';
"use strict";
module.exports = {
meta: {
type: 'error',
docs: {
description: 'Detects "object.escapeMarkup = false", which can be used with some template engines to disable escaping of HTML entities.',
category: 'Possible Security Vulnerability',
recommended: true,
url: 'https://github.com/nodesecurity/eslint-plugin-security#detect-disable-mustache-escape'
}
},
create: function (context) {
return {
"AssignmentExpression": function(node) {
if (node.operator === '=') {
if (node.left.property) {
if (node.left.property.name == 'escapeMarkup') {
if (node.right.value == false) {
context.report(node, 'Markup escaping disabled.')
}
}
}
AssignmentExpression: function (node) {
if (node.operator === '=') {
if (node.left.property) {
if (node.left.property.name === 'escapeMarkup') {
if (node.right.value === false) {
context.report(node, 'Markup escaping disabled.');
}
}
}
}
}
}
}
};
}
};
/**
* Idnetifies eval with expression
* Identifies eval with expression
* @author Adam Baldwin
*/
'use strict';
//------------------------------------------------------------------------------

@@ -10,13 +12,21 @@ // Rule Definition

module.exports = function(context) {
"use strict";
module.exports = {
meta: {
type: 'error',
docs: {
description: 'Detects "eval(variable)" which can allow an attacker to run arbitrary code inside your process.',
category: 'Possible Security Vulnerability',
recommended: true,
url: 'https://github.com/nodesecurity/eslint-plugin-security#detect-eval-with-expression'
}
},
create: function (context) {
return {
"CallExpression": function(node) {
if (node.callee.name === "eval" && node.arguments[0].type !== 'Literal') {
context.report(node, "eval with argument of type " + node.arguments[0].type);
}
CallExpression: function (node) {
if (node.callee.name === 'eval' && node.arguments[0].type !== 'Literal') {
context.report(node, `eval with argument of type ${node.arguments[0].type}`);
}
}
};
}
};

@@ -1,19 +0,22 @@

module.exports = function (context) {
// Detects instances of new Buffer(argument)
// where argument is any non literal value.
'use strict';
module.exports = {
meta: {
type: 'error',
docs: {
description: 'Detect instances of new Buffer(argument) where argument is any non-literal value.',
category: 'Possible Security Vulnerability',
recommended: true,
url: 'https://github.com/nodesecurity/eslint-plugin-security/blob/main/README.md'
}
},
create: function (context) {
return {
"NewExpression": function (node) {
if (node.callee.name === 'Buffer' &&
node.arguments[0] &&
node.arguments[0].type != 'Literal') {
return context.report(node, "Found new Buffer");
NewExpression: function (node) {
if (node.callee.name === 'Buffer' && node.arguments[0] && node.arguments[0].type !== 'Literal') {
return context.report(node, 'Found new Buffer');
}
}
};
}
}
};

@@ -6,2 +6,4 @@ /**

'use strict';
//------------------------------------------------------------------------------

@@ -11,31 +13,36 @@ // Rule Definition

module.exports = {
meta: {
type: 'error',
docs: {
description: 'Detects Express "csrf" middleware setup before "method-override" middleware.',
category: 'Possible Security Vulnerability',
recommended: true,
url: 'https://github.com/nodesecurity/eslint-plugin-security/blob/main/docs/bypass-connect-csrf-protection-by-abusing.md',
},
},
create: function (context) {
let csrf = false;
module.exports = function(context) {
"use strict";
var csrf = false;
return {
"CallExpression": function(node) {
var token = context.getTokens(node)[0],
nodeType = token.type,
nodeValue = token.value;
CallExpression: function (node) {
const token = context.getTokens(node)[0];
const nodeValue = token.value;
if (nodeValue === "express") {
if (!node.callee || !node.callee.property) {
return;
}
if (nodeValue === 'express') {
if (!node.callee || !node.callee.property) {
return;
}
if (node.callee.property.name === "methodOverride" && csrf) {
context.report(node, "express.csrf() middleware found before express.methodOverride()");
}
if (node.callee.property.name === "csrf") {
// Keep track of found CSRF
csrf = true;
}
}
if (node.callee.property.name === 'methodOverride' && csrf) {
context.report(node, 'express.csrf() middleware found before express.methodOverride()');
}
if (node.callee.property.name === 'csrf') {
// Keep track of found CSRF
csrf = true;
}
}
},
};
},
};

@@ -6,2 +6,4 @@ /**

'use strict';
//------------------------------------------------------------------------------

@@ -11,41 +13,44 @@ // Rule Definition

var names = [];
var fsMetaData = require('./data/fsFunctionData.json');
var funcNames = Object.keys(fsMetaData);
const fsMetaData = require('./data/fsFunctionData.json');
const funcNames = Object.keys(fsMetaData);
module.exports = function(context) {
"use strict";
module.exports = {
meta: {
type: 'error',
docs: {
description: 'Detects variable in filename argument of "fs" calls, which might allow an attacker to access anything on your system.',
category: 'Possible Security Vulnerability',
recommended: true,
url: 'https://github.com/nodesecurity/eslint-plugin-security#detect-non-literal-fs-filename',
},
},
create: function (context) {
return {
"MemberExpression": function (node) {
var result = [];
if (funcNames.indexOf(node.property.name) !== -1) {
var meta = fsMetaData[node.property.name];
var args = node.parent.arguments;
meta.forEach(function (i) {
if (args && args.length > i) {
if (args[i].type !== 'Literal') {
result.push(i);
}
}
});
MemberExpression: function (node) {
const result = [];
if (funcNames.indexOf(node.property.name) !== -1) {
const meta = fsMetaData[node.property.name];
const args = node.parent.arguments;
meta.forEach((i) => {
if (args && args.length > i) {
if (args[i].type !== 'Literal') {
result.push(i);
}
}
});
}
if (result.length > 0) {
var token = context.getTokens(node)[0];
return context.report(node, 'Found fs.' + node.property.name + ' with non literal argument at index ' + result.join(','));
}
if (result.length > 0) {
return context.report(node, `Found fs.${node.property.name} with non literal argument at index ${result.join(',')}`);
}
/*
if (node.parent && node.parent.arguments && node.parent.arguments[index].value) {
return context.report(node, 'found Buffer.' + node.property.name + ' with noAssert flag set true');
/*
if (node.parent && node.parent.arguments && node.parent.arguments[index].value) {
return context.report(node, 'found Buffer.' + node.property.name + ' with noAssert flag set true');
}
*/
}
}
*/
},
};
},
};

@@ -6,2 +6,4 @@ /**

'use strict';
//------------------------------------------------------------------------------

@@ -11,20 +13,24 @@ // Rule Definition

module.exports = function(context) {
"use strict";
return {
"NewExpression": function(node) {
if (node.callee.name === 'RegExp') {
var args = node.arguments;
if (args && args.length > 0 && args[0].type !== 'Literal') {
var token = context.getTokens(node)[0];
return context.report(node, 'Found non-literal argument to RegExp Constructor');
}
}
}
module.exports = {
meta: {
type: 'error',
docs: {
description: 'Detects "RegExp(variable)", which might allow an attacker to DOS your server with a long-running regular expression.',
category: 'Possible Security Vulnerability',
recommended: true,
url: 'https://github.com/nodesecurity/eslint-plugin-security/blob/main/docs/regular-expression-dos-and-node.md',
},
},
create: function (context) {
return {
NewExpression: function (node) {
if (node.callee.name === 'RegExp') {
const args = node.arguments;
if (args && args.length > 0 && args[0].type !== 'Literal') {
return context.report(node, 'Found non-literal argument to RegExp Constructor');
}
}
}
},
};
},
};
/**
* Tries to detect calls to require with non-literal argument
* @author Adam Baldwin
* @author Adam Baldwin
*/
'use strict';
//------------------------------------------------------------------------------

@@ -10,21 +12,27 @@ // Rule Definition

module.exports = function(context) {
"use strict";
module.exports = {
meta: {
type: 'error',
docs: {
description: 'Detects "require(variable)", which might allow an attacker to load and run arbitrary code, or access arbitrary files on disk. ',
category: 'Possible Security Vulnerability',
recommended: true,
url: 'https://github.com/nodesecurity/eslint-plugin-security#detect-non-literal-require',
},
},
create: function (context) {
return {
"CallExpression": function (node) {
if (node.callee.name === 'require') {
var args = node.arguments;
if (args && args.length > 0 && args[0].type !== 'Literal') {
var token = context.getTokens(node)[0];
return context.report(node, 'Found non-literal argument in require');
}
}
CallExpression: function (node) {
if (node.callee.name === 'require') {
const args = node.arguments;
if (
(args && args.length > 0 && args[0].type === 'TemplateLiteral' && args[0].expressions.length > 0) ||
(args[0].type !== 'TemplateLiteral' && args[0].type !== 'Literal')
) {
return context.report(node, 'Found non-literal argument in require');
}
}
},
};
},
};

@@ -6,2 +6,4 @@ /**

'use strict';
//------------------------------------------------------------------------------

@@ -11,14 +13,28 @@ // Rule Definition

var Sinks = [];
function getSerialize (fn, decycle) {
var seen = [], keys = [];
decycle = decycle || function(key, value) {
return '[Circular ' + getPath(value, seen, keys) + ']'
};
return function(key, value) {
var ret = value;
const getPath = (value, seen, keys) => {
let index = seen.indexOf(value);
const path = [keys[index]];
for (index--; index >= 0; index--) {
if (seen[index][path[0]] === value) {
value = seen[index];
path.unshift(keys[index]);
}
}
return `~${path.join('.')}`;
};
const getSerialize = (fn, decycle) => {
const seen = [];
const keys = [];
decycle =
decycle ||
function (key, value) {
return `[Circular ${getPath(value, seen, keys)}]`;
};
return function (key, value) {
let ret = value;
if (typeof value === 'object' && value) {
if (seen.indexOf(value) !== -1)
if (seen.indexOf(value) !== -1) {
ret = decycle(key, value);
else {
} else {
seen.push(value);

@@ -28,55 +44,41 @@ keys.push(key);

}
if (fn) ret = fn(key, ret);
if (fn) {
ret = fn(key, ret);
}
return ret;
}
}
};
};
function getPath (value, seen, keys) {
var index = seen.indexOf(value);
var path = [ keys[index] ];
for (index--; index >= 0; index--) {
if (seen[index][ path[0] ] === value) {
value = seen[index];
path.unshift(keys[index]);
}
}
return '~' + path.join('.');
}
function stringify(obj, fn, spaces, decycle) {
const stringify = (obj, fn, spaces, decycle) => {
return JSON.stringify(obj, getSerialize(fn, decycle), spaces);
}
};
stringify.getSerialize = getSerialize;module.exports = function(context) {
"use strict";
var isChanged = false;
return {
"MemberExpression": function(node) {
if (node.computed === true) {
var token = context.getTokens(node)[0];
if (node.property.type === 'Identifier') {
if (node.parent.type === 'VariableDeclarator') {
context.report(node, 'Variable Assigned to Object Injection Sink');
} else if (node.parent.type === 'CallExpression') {
// console.log(node.parent)
context.report(node, 'Function Call Object Injection Sink');
} else {
context.report(node, 'Generic Object Injection Sink');
}
}
}
stringify.getSerialize = getSerialize;
module.exports = {
meta: {
type: 'error',
docs: {
description: 'Detects "variable[key]" as a left- or right-hand assignment operand.',
category: 'Possible Security Vulnerability',
recommended: true,
url: 'https://github.com/nodesecurity/eslint-plugin-security/blob/main/docs/the-dangers-of-square-bracket-notation.md',
},
},
create: function (context) {
return {
MemberExpression: function (node) {
if (node.computed === true) {
if (node.property.type === 'Identifier') {
if (node.parent.type === 'VariableDeclarator') {
context.report(node, 'Variable Assigned to Object Injection Sink');
} else if (node.parent.type === 'CallExpression') {
context.report(node, 'Function Call Object Injection Sink');
} else {
context.report(node, 'Generic Object Injection Sink');
}
};
}
}
}
},
};
},
};

@@ -6,2 +6,4 @@ /**

'use strict';
//------------------------------------------------------------------------------

@@ -11,52 +13,48 @@ // Rule Definition

var keywords = '((' + [
'password',
'secret',
'api',
'apiKey',
'token',
'auth',
'pass',
'hash'
].join(')|(') + '))';
const keywords = `((${['password', 'secret', 'api', 'apiKey', 'token', 'auth', 'pass', 'hash'].join(')|(')}))`;
var re = new RegExp('^' + keywords + '$', 'im');
const re = new RegExp(`^${keywords}$`, 'im');
function containsKeyword (node) {
if (node.type === 'Identifier') {
if (re.test(node.name))
return true;
}
return
}
const containsKeyword = (node) => {
if (node.type === 'Identifier') {
if (re.test(node.name)) {
return true;
}
}
return;
};
module.exports = function(context) {
"use strict";
module.exports = {
meta: {
type: 'error',
docs: {
description: 'Detects insecure comparisons (`==`, `!=`, `!==` and `===`), which check input sequentially.',
category: 'Possible Security Vulnerability',
recommended: true,
url: 'https://github.com/nodesecurity/eslint-plugin-security#detect-possible-timing-attacks'
}
},
create: function (context) {
return {
"IfStatement": function(node) {
if (node.test && node.test.type === 'BinaryExpression') {
if (node.test.operator === '==' || node.test.operator === '===' || node.test.operator === '!=' || node.test.operator === '!==') {
IfStatement: function (node) {
if (node.test && node.test.type === 'BinaryExpression') {
if (node.test.operator === '==' || node.test.operator === '===' || node.test.operator === '!=' || node.test.operator === '!==') {
if (node.test.left) {
const left = containsKeyword(node.test.left);
if (left) {
return context.report(node, `Potential timing attack, left side: ${left}`);
}
}
var token = context.getTokens(node)[0];
if (node.test.left) {
var left = containsKeyword(node.test.left);
if (left) {
return context.report(node, "Potential timing attack, left side: " + left);
}
}
if (node.test.right) {
var right = containsKeyword(node.test.right);
if (right) {
return context.report(node, "Potential timing attack, right side: " + right);
}
}
}
if (node.test.right) {
const right = containsKeyword(node.test.right);
if (right) {
return context.report(node, `Potential timing attack, right side: ${right}`);
}
}
}
}
}
};
}
};

@@ -6,2 +6,4 @@ /**

'use strict';
//------------------------------------------------------------------------------

@@ -11,16 +13,21 @@ // Rule Definition

module.exports = function(context) {
"use strict";
module.exports = {
meta: {
type: 'error',
docs: {
description: 'Detects if "pseudoRandomBytes()" is in use, which might not give you the randomness you need and expect.',
category: 'Possible Security Vulnerability',
recommended: true,
url: 'https://github.com/nodesecurity/eslint-plugin-security#detect-pseudorandombytes',
},
},
create: function (context) {
return {
"MemberExpression": function (node) {
if (node.property.name === 'pseudoRandomBytes') {
var token = context.getTokens(node)[0];
return context.report(node, 'Found crypto.pseudoRandomBytes which does not produce cryptographically strong numbers');
}
MemberExpression: function (node) {
if (node.property.name === 'pseudoRandomBytes') {
return context.report(node, 'Found crypto.pseudoRandomBytes which does not produce cryptographically strong numbers');
}
},
};
},
};

@@ -1,2 +0,1 @@

var safe = require('safe-regex');
/**

@@ -7,2 +6,10 @@ * Check if the regex is evil or not using the safe-regex module

'use strict';
//-----------------------------------------------------------------------------
// Requirements
//-----------------------------------------------------------------------------
const safe = require('safe-regex');
//------------------------------------------------------------------------------

@@ -12,28 +19,34 @@ // Rule Definition

module.exports = function(context) {
"use strict";
module.exports = {
meta: {
type: 'error',
docs: {
description: 'Locates potentially unsafe regular expressions, which may take a very long time to run, blocking the event loop.',
category: 'Possible Security Vulnerability',
recommended: true,
url: 'https://github.com/nodesecurity/eslint-plugin-security/blob/main/docs/regular-expression-dos-and-node.md'
}
},
create: function (context) {
return {
"Literal": function(node) {
var token = context.getTokens(node)[0],
nodeType = token.type,
nodeValue = token.value;
Literal: function (node) {
const token = context.getTokens(node)[0];
const nodeType = token.type;
const nodeValue = token.value;
if (nodeType === "RegularExpression") {
if (!safe(nodeValue)) {
context.report(node, "Unsafe Regular Expression");
}
}
},
"NewExpression": function(node) {
if (node.callee.name == "RegExp" && node.arguments && node.arguments.length > 0 && node.arguments[0].type == "Literal") {
if (!safe(node.arguments[0].value)) {
context.report(node, "Unsafe Regular Expression (new RegExp)");
}
}
if (nodeType === 'RegularExpression') {
if (!safe(nodeValue)) {
context.report(node, 'Unsafe Regular Expression');
}
}
},
NewExpression: function (node) {
if (node.callee.name === 'RegExp' && node.arguments && node.arguments.length > 0 && node.arguments[0].type === 'Literal') {
if (!safe(node.arguments[0].value)) {
context.report(node, 'Unsafe Regular Expression (new RegExp)');
}
}
}
};
}
};

@@ -7,25 +7,25 @@ 'use strict';

const ruleName = 'detect-buffer-noassert';
const Rule = require(`../rules/${ruleName}`);
const rule = require(`../rules/${ruleName}`);
const invalid = 'a.readUInt8(0, true);';
const allMethodNames = [...rule.meta.__methodsToCheck.read, ...rule.meta.__methodsToCheck.write];
tester.run(ruleName, Rule, {
valid: [{ code: 'a.readUInt8(0);' }],
tester.run(ruleName, rule, {
valid: [...allMethodNames.map((methodName) => `a.${methodName}(0)`), ...allMethodNames.map((methodName) => `a.${methodName}(0, false)`)],
invalid: [
{
code: invalid,
errors: [{ message: 'Found Buffer.readUInt8 with noAssert flag set true' }]
}
]
});
...rule.meta.__methodsToCheck.read.map((methodName) => ({
code: `a.${methodName}(0, true)`,
errors: [{ message: `Found Buffer.${methodName} with noAssert flag set true` }],
})),
tester.run(`${ruleName} (false)`, Rule, {
valid: [{ code: 'a.readUInt8(0, false);' }],
invalid: [
...rule.meta.__methodsToCheck.write.map((methodName) => ({
code: `a.${methodName}(0, 0, true)`,
errors: [{ message: `Found Buffer.${methodName} with noAssert flag set true` }],
})),
// hard-coded test to ensure #63 is fixed
{
code: invalid,
errors: [{ message: 'Found Buffer.readUInt8 with noAssert flag set true' }]
}
]
code: 'a.readDoubleLE(0, true);',
errors: [{ message: 'Found Buffer.readDoubleLE with noAssert flag set true' }],
},
],
});

@@ -7,30 +7,20 @@ 'use strict';

const ruleName = 'detect-child-process';
const Rule = require(`../rules/${ruleName}`);
const rule = require(`../rules/${ruleName}`);
const valid = 'child_process.exec(\'ls\')';
const invalidRequire = 'require(\'child_process\')';
const invalidExec = 'var child = require(\'child_process\'); child.exec(com)';
tester.run(`${ruleName} (require("child_process"))`, Rule, {
valid: [{ code: valid }],
tester.run(ruleName, rule, {
valid: ["child_process.exec('ls')"],
invalid: [
{
code: invalidRequire,
errors: [{ message: 'Found require("child_process")' }]
}
]
});
tester.run(`${ruleName} (child_process.exec() wih non literal 1st arg.)`, Rule, {
valid: [{ code: valid }],
invalid: [
code: "require('child_process')",
errors: [{ message: 'Found require("child_process")' }],
},
{
code: invalidExec,
errors: [
{ message: 'Found require("child_process")' },
{ message: 'Found child_process.exec() with non Literal first argument' }]
}
]
code: "var child = require('child_process'); child.exec(com)",
errors: [{ message: 'Found require("child_process")' }, { message: 'Found child_process.exec() with non Literal first argument' }],
},
{
code: "var child = require('child_process'); child.exec()",
errors: [{ message: 'Found require("child_process")' }],
},
],
});

@@ -8,3 +8,2 @@ 'use strict';

tester.run(ruleName, require(`../rules/${ruleName}`), {

@@ -11,0 +10,0 @@ valid: [{ code: 'escapeMarkup = false' }],

@@ -8,3 +8,2 @@ 'use strict';

tester.run(ruleName, require(`../rules/${ruleName}`), {

@@ -11,0 +10,0 @@ valid: [{ code: 'eval(\'alert()\')' }],

@@ -9,3 +9,2 @@ 'use strict';

tester.run(ruleName, require(`../rules/${ruleName}`), {

@@ -12,0 +11,0 @@ valid: [{ code: 'var a = new Buffer(\'test\')' }],

@@ -8,3 +8,2 @@ 'use strict';

tester.run(ruleName, require(`../rules/${ruleName}`), {

@@ -11,0 +10,0 @@ valid: [{ code: 'express.methodOverride();express.csrf()' }],

@@ -10,3 +10,2 @@ 'use strict';

tester.run(ruleName, require(`../rules/${ruleName}`), {

@@ -13,0 +12,0 @@ valid: [{ code: 'var a = fs.open(\'test\')' }],

@@ -9,3 +9,2 @@ 'use strict';

tester.run(ruleName, require(`../rules/${ruleName}`), {

@@ -12,0 +11,0 @@ valid: [{ code: 'var a = new RegExp(\'ab+c\', \'i\')' }],

'use strict';
const RuleTester = require('eslint').RuleTester;
const tester = new RuleTester();
const tester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
const ruleName = 'detect-non-literal-require';
const invalid = 'var a = require(c)';
tester.run(ruleName, require(`../rules/${ruleName}`), {
valid: [{ code: 'var a = require(\'b\')' }],
valid: [{ code: 'var a = require(\'b\')' }, { code: 'var a = require(`b`)' }],
invalid: [
{
code: invalid,
code: 'var a = require(c)',
errors: [{ message: 'Found non-literal argument in require' }]
},
{
code: 'var a = require(`${c}`)',
errors: [{ message: 'Found non-literal argument in require' }]
}
]
});

@@ -15,3 +15,2 @@ 'use strict';

// TODO

@@ -39,3 +38,2 @@ // tester.run(`${ruleName} (Variable Assigned to)`, Rule, {

tester.run(`${ruleName} (Generic)`, Rule, {

@@ -42,0 +40,0 @@ valid: [{ code: valid }],

@@ -13,3 +13,2 @@ 'use strict';

// We only check with one string "password" and operator "==="

@@ -28,3 +27,2 @@ // to KISS.

tester.run(`${ruleName} (right side)`, Rule, {

@@ -31,0 +29,0 @@ valid: [{ code: valid }],

@@ -9,3 +9,2 @@ 'use strict';

tester.run(ruleName, require(`../rules/${ruleName}`), {

@@ -12,0 +11,0 @@ valid: [{ code: 'crypto.randomBytes' }],

@@ -9,5 +9,4 @@ 'use strict';

tester.run(ruleName, Rule, {
valid: [{ code: '/^\d+1337\d+$/' }],
valid: [{ code: '/^d+1337d+$/' }],
invalid: [

@@ -21,5 +20,4 @@ {

tester.run(`${ruleName} (new RegExp)`, Rule, {
valid: [{ code: 'new RegExp(\'^\d+1337\d+$\')' }],
valid: [{ code: 'new RegExp(\'^d+1337d+$\')' }],
invalid: [

@@ -26,0 +24,0 @@ {

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc