Skip to content

Commit

Permalink
feat: Add meta object documentation for all rules (#79)
Browse files Browse the repository at this point in the history
* Update .gitignore

* Closes #61
* Closes #48 

* Update README.md

Co-authored-by: Nicholas C. Zakas <[email protected]>

* Update README.md

Co-authored-by: Nicholas C. Zakas <[email protected]>

* Update README.md

Co-authored-by: Nicholas C. Zakas <[email protected]>

* docs: changed meta urls to rule docs and shortened descriptions to one, markdownfree sentence.

* docs: corrected snyk description

* docs: updated to link on main

Co-authored-by: Nicholas C. Zakas <[email protected]>
  • Loading branch information
MarkKragerup and nzakas authored Mar 30, 2022
1 parent b9a9b7f commit fb1d9ef
Show file tree
Hide file tree
Showing 16 changed files with 383 additions and 273 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules
.idea
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,27 +44,27 @@ More information: [Regular Expression DoS and Node.js](docs/regular-expression-d

#### `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.

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`."

#### `detect-child-process`

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: [Avoiding Command Injection in Node.js](docs/avoid-command-injection-node.md)

#### `detect-disable-mustache-escape`

Detects `object.escapeMarkup = false`, which can be used with some template engines to disable escaping of HTML entities. This can lead to Cross-Site Scripting (XSS) vulnerabilities.

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 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)

#### `detect-no-csrf-before-method-override`

Expand All @@ -76,7 +76,7 @@ More information: [Bypass Connect CSRF protection by abusing methodOverride Midd

Detects variable in filename argument of `fs` calls, which might allow an attacker to access anything on your system.

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

#### `detect-non-literal-regexp`

Expand All @@ -88,7 +88,7 @@ More information: [Regular Expression DoS and Node.js](docs/regular-expression-d

Detects `require(variable)`, which might allow an attacker to load and run arbitrary code, or access arbitrary files on disk.

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)

#### `detect-object-injection`

Expand All @@ -100,10 +100,14 @@ More information: [The Dangers of Square Bracket Notation](docs/the-dangers-of-s

Detects insecure comparisons (`==`, `!=`, `!==` and `===`), which check input sequentially.

More information: https://codahale.com/a-lesson-in-timing-attacks/
More information: [A lesson in timing attacks](https://codahale.com/a-lesson-in-timing-attacks/)

#### `detect-pseudoRandomBytes`

Detects if `pseudoRandomBytes()` is in use, which might not give you the randomness you need and expect.

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.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

108 changes: 58 additions & 50 deletions rules/detect-buffer-noassert.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,59 +11,67 @@

const names = [];

module.exports = function(context) {

const read = [
'readUInt8',
'readUInt16LE',
'readUInt16BE',
'readUInt32LE',
'readUInt32BE',
'readInt8',
'readInt16LE',
'readInt16BE',
'readInt32LE',
'readInt32BE',
'readFloatLE',
'readFloatBE',
'readDoubleL',
'readDoubleBE'
];
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'
}
},
create: function(context) {
const read = [
'readUInt8',
'readUInt16LE',
'readUInt16BE',
'readUInt32LE',
'readUInt32BE',
'readInt8',
'readInt16LE',
'readInt16BE',
'readInt32LE',
'readInt32BE',
'readFloatLE',
'readFloatBE',
'readDoubleL',
'readDoubleBE'
];

const write = [
'writeUInt8',
'writeUInt16LE',
'writeUInt16BE',
'writeUInt32LE',
'writeUInt32BE',
'writeInt8',
'writeInt16LE',
'writeInt16BE',
'writeInt32LE',
'writeInt32BE',
'writeFloatLE',
'writeFloatBE',
'writeDoubleLE',
'writeDoubleBE'
];
const write = [
'writeUInt8',
'writeUInt16LE',
'writeUInt16BE',
'writeUInt32LE',
'writeUInt32BE',
'writeInt8',
'writeInt16LE',
'writeInt16BE',
'writeInt32LE',
'writeInt32BE',
'writeFloatLE',
'writeFloatBE',
'writeDoubleLE',
'writeDoubleBE'
];

return {
'MemberExpression': function (node) {
let index;
if (read.indexOf(node.property.name) !== -1) {
index = 1;
}
else if (write.indexOf(node.property.name) !== -1) {
index = 2;
}
return {
'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) {
const 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) {
const token = context.getTokens(node)[0];
return context.report(node, `Found Buffer.${node.property.name} with noAssert flag set true`);

}
}
}

};

};
}
};
57 changes: 33 additions & 24 deletions rules/detect-child-process.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,42 @@

const names = [];

module.exports = function(context) {

return {
'CallExpression': function (node) {
const token = context.getTokens(node)[0];
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);
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) {
const token = context.getTokens(node)[0];
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);
}
return context.report(node, 'Found require("child_process")');
}
return context.report(node, 'Found require("child_process")');
}
}
},
'MemberExpression': function (node) {
const 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');
},
'MemberExpression': function(node) {
const 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');
}
}
}
}

};

};
}
};
34 changes: 21 additions & 13 deletions rules/detect-disable-mustache-escape.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@

'use strict';

module.exports = 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.');
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.');
}
}
}
}
}
}
};

};
}
};
26 changes: 18 additions & 8 deletions rules/detect-eval-with-expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,23 @@
// Rule Definition
//------------------------------------------------------------------------------

module.exports = 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}`);
}
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}`);
}
}
};
}
};
31 changes: 18 additions & 13 deletions rules/detect-new-buffer.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
'use strict';


module.exports = function (context) {
// Detects instances of new Buffer(argument)
// where argument is any non literal value.
return {
'NewExpression': function (node) {
if (node.callee.name === 'Buffer' &&
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');
return context.report(node, 'Found new Buffer');
}
}



}
};

};
}
};
Loading

0 comments on commit fb1d9ef

Please sign in to comment.