eslint-plugin-security
Advanced tools
Comparing version 1.7.0 to 1.7.1
# Changelog | ||
### [1.7.1](https://www.github.com/eslint-community/eslint-plugin-security/compare/v1.7.0...v1.7.1) (2023-02-02) | ||
### Bug Fixes | ||
* false positives for static expressions in detect-non-literal-fs-filename, detect-child-process, detect-non-literal-regexp, and detect-non-literal-require ([#109](https://www.github.com/eslint-community/eslint-plugin-security/issues/109)) ([56102b5](https://www.github.com/eslint-community/eslint-plugin-security/commit/56102b50aed4bd632dd668770eb37de58788110b)) | ||
## [1.7.0](https://www.github.com/eslint-community/eslint-plugin-security/compare/v1.6.0...v1.7.0) (2023-01-26) | ||
@@ -4,0 +11,0 @@ |
{ | ||
"name": "eslint-plugin-security", | ||
"version": "1.7.0", | ||
"version": "1.7.1", | ||
"description": "Security rules for eslint", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -9,2 +9,3 @@ /** | ||
const { getImportAccessPath } = require('../utils/import-utils'); | ||
const { isStaticExpression } = require('../utils/is-static-expression'); | ||
const childProcessPackageNames = ['child_process', 'node:child_process']; | ||
@@ -45,3 +46,9 @@ | ||
// Reports non-literal `exec()` calls. | ||
if (!node.arguments.length || node.arguments[0].type === 'Literal') { | ||
if ( | ||
!node.arguments.length || | ||
isStaticExpression({ | ||
node: node.arguments[0], | ||
scope: context.getScope(), | ||
}) | ||
) { | ||
return; | ||
@@ -48,0 +55,0 @@ } |
@@ -13,19 +13,5 @@ /** | ||
const { getImportAccessPath } = require('../utils/import-utils'); | ||
const { isStaticExpression } = require('../utils/is-static-expression'); | ||
//------------------------------------------------------------------------------ | ||
// Utils | ||
//------------------------------------------------------------------------------ | ||
function getIndices(node, argMeta) { | ||
return (argMeta || []).filter((argIndex) => node.arguments[argIndex].type !== 'Literal'); | ||
} | ||
function generateReport({ context, node, packageName, methodName, indices }) { | ||
if (!indices || indices.length === 0) { | ||
return; | ||
} | ||
context.report({ node, message: `Found ${methodName} from package "${packageName}" with non literal argument at index ${indices.join(',')}` }); | ||
} | ||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
@@ -91,11 +77,19 @@ //------------------------------------------------------------------------------ | ||
const indices = getIndices(node, fsMetaData[fnName]); | ||
generateReport({ | ||
context, | ||
node, | ||
packageName, | ||
methodName: fnName, | ||
indices, | ||
}); | ||
const indices = []; | ||
for (const index of fsMetaData[fnName] || []) { | ||
if (index >= node.arguments.length) { | ||
continue; | ||
} | ||
const argument = node.arguments[index]; | ||
if (isStaticExpression({ node: argument, scope: context.getScope() })) { | ||
continue; | ||
} | ||
indices.push(index); | ||
} | ||
if (indices.length) { | ||
context.report({ | ||
node, | ||
message: `Found ${fnName} from package "${packageName}" with non literal argument at index ${indices.join(',')}`, | ||
}); | ||
} | ||
}, | ||
@@ -102,0 +96,0 @@ }; |
@@ -8,2 +8,4 @@ /** | ||
const { isStaticExpression } = require('../utils/is-static-expression'); | ||
//------------------------------------------------------------------------------ | ||
@@ -28,3 +30,10 @@ // Rule Definition | ||
const args = node.arguments; | ||
if (args && args.length > 0 && args[0].type !== 'Literal') { | ||
if ( | ||
args && | ||
args.length > 0 && | ||
!isStaticExpression({ | ||
node: args[0], | ||
scope: context.getScope(), | ||
}) | ||
) { | ||
return context.report({ node: node, message: 'Found non-literal argument to RegExp Constructor' }); | ||
@@ -31,0 +40,0 @@ } |
@@ -8,2 +8,4 @@ /** | ||
const { isStaticExpression } = require('../utils/is-static-expression'); | ||
//------------------------------------------------------------------------------ | ||
@@ -29,4 +31,8 @@ // Rule Definition | ||
if ( | ||
(args && args.length > 0 && args[0].type === 'TemplateLiteral' && args[0].expressions.length > 0) || | ||
(args[0].type !== 'TemplateLiteral' && args[0].type !== 'Literal') | ||
args && | ||
args.length > 0 && | ||
!isStaticExpression({ | ||
node: args[0], | ||
scope: context.getScope(), | ||
}) | ||
) { | ||
@@ -33,0 +39,0 @@ return context.report({ node: node, message: 'Found non-literal argument in require' }); |
@@ -53,2 +53,10 @@ 'use strict'; | ||
}`, | ||
` | ||
var child_process = require('child_process'); | ||
var FOO = 'ls'; | ||
child_process.exec(FOO);`, | ||
` | ||
import child_process from 'child_process'; | ||
const FOO = 'ls'; | ||
child_process.exec(FOO);`, | ||
], | ||
@@ -55,0 +63,0 @@ invalid: [ |
@@ -6,3 +6,3 @@ 'use strict'; | ||
parserOptions: { | ||
ecmaVersion: 6, | ||
ecmaVersion: 13, | ||
sourceType: 'module', | ||
@@ -28,2 +28,47 @@ }, | ||
}, | ||
{ | ||
code: ` | ||
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);`, | ||
globals: { | ||
__dirname: 'readonly', | ||
}, | ||
}, | ||
{ | ||
code: ` | ||
import fs from 'fs'; | ||
import path from 'path'; | ||
const dirname = path.dirname(__filename) | ||
const key = fs.readFileSync(path.resolve(dirname, './index.html'));`, | ||
globals: { | ||
__filename: 'readonly', | ||
}, | ||
}, | ||
{ | ||
code: ` | ||
import fs from 'fs'; | ||
const key = fs.readFileSync(\`\${process.cwd()}/path/to/foo.json\`);`, | ||
globals: { | ||
process: 'readonly', | ||
}, | ||
}, | ||
` | ||
import fs from 'fs'; | ||
import path from 'path'; | ||
import url from 'url'; | ||
const dirname = path.dirname(url.fileURLToPath(import.meta.url)); | ||
const html = fs.readFileSync(path.resolve(dirname, './index.html'), 'utf-8');`, | ||
{ | ||
code: ` | ||
import fs from 'fs'; | ||
const pkg = fs.readFileSync(require.resolve('eslint/package.json'), 'utf-8');`, | ||
globals: { | ||
require: 'readonly', | ||
}, | ||
}, | ||
], | ||
@@ -146,3 +191,13 @@ invalid: [ | ||
}, | ||
{ | ||
code: ` | ||
import fs from 'fs'; | ||
import path from 'path'; | ||
const key = fs.readFileSync(path.resolve(__dirname, foo));`, | ||
globals: { | ||
__filename: 'readonly', | ||
}, | ||
errors: [{ message: 'Found readFileSync from package "fs" with non literal argument at index 0' }], | ||
}, | ||
], | ||
}); |
@@ -10,3 +10,10 @@ 'use strict'; | ||
tester.run(ruleName, require(`../rules/${ruleName}`), { | ||
valid: [{ code: "var a = new RegExp('ab+c', 'i')" }], | ||
valid: [ | ||
{ code: "var a = new RegExp('ab+c', 'i')" }, | ||
{ | ||
code: ` | ||
var source = 'ab+c' | ||
var a = new RegExp(source, 'i')`, | ||
}, | ||
], | ||
invalid: [ | ||
@@ -13,0 +20,0 @@ { |
@@ -10,3 +10,17 @@ 'use strict'; | ||
tester.run(ruleName, require(`../rules/${ruleName}`), { | ||
valid: [{ code: "var a = require('b')" }, { code: 'var a = require(`b`)' }], | ||
valid: [ | ||
{ code: "var a = require('b')" }, | ||
{ code: 'var a = require(`b`)' }, | ||
{ | ||
code: ` | ||
const d = 'debounce' | ||
var a = require(\`lodash/\${d}\`)`, | ||
}, | ||
{ | ||
code: "const utils = require(__dirname + '/utils');", | ||
globals: { | ||
__dirname: 'readonly', | ||
}, | ||
}, | ||
], | ||
invalid: [ | ||
@@ -13,0 +27,0 @@ { |
@@ -0,1 +1,3 @@ | ||
const { findVariable } = require('./find-variable'); | ||
module.exports.getImportAccessPath = getImportAccessPath; | ||
@@ -185,13 +187,1 @@ | ||
} | ||
/** @returns {import("eslint").Scope.Variable | null} */ | ||
function findVariable(scope, name) { | ||
while (scope != null) { | ||
const variable = scope.set.get(name); | ||
if (variable != null) { | ||
return variable; | ||
} | ||
scope = scope.upper; | ||
} | ||
return null; | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
133989
69
2286