diff --git a/eslint-factory/src/rules/no-child-process-interpolated-command.test.ts b/eslint-factory/src/rules/no-child-process-interpolated-command.test.ts index b8eff0f5445..74d9f682a7d 100644 --- a/eslint-factory/src/rules/no-child-process-interpolated-command.test.ts +++ b/eslint-factory/src/rules/no-child-process-interpolated-command.test.ts @@ -23,6 +23,8 @@ describe("no-child-process-interpolated-command", () => { { code: `const { execSync } = require("child_process"); let cmd = \`git checkout \${branch}\`; cmd = "git status"; execSync(cmd);` }, { code: `const { execSync } = require("child_process"); (function(cmd) { execSync(cmd); })("git status");` }, { code: `exec.exec(\`git checkout \${branch}\`, []);` }, + { code: `require("child_process").execSync("git status");` }, + { code: `require("node:child_process").execSync(\`git status\`);` }, { code: `import { exec } from "node:child_process"; exec("git status");`, languageOptions: { sourceType: "module" }, @@ -89,6 +91,18 @@ describe("no-child-process-interpolated-command", () => { { messageId: "interpolatedCommand", data: { kind: "dynamic string concatenation", method: "exec" } }, ], }, + { + code: `require("child_process").execSync(\`rm -rf \${userInput}\`);`, + errors: [{ messageId: "interpolatedCommand", data: { kind: "interpolated template literal", method: "execSync" } }], + }, + { + code: `require("node:child_process").execSync("rm -rf " + userInput);`, + errors: [{ messageId: "interpolatedCommand", data: { kind: "dynamic string concatenation", method: "execSync" } }], + }, + { + code: `require("child_process").spawn(\`git checkout \${branch}\`, { shell: true });`, + errors: [{ messageId: "interpolatedCommand", data: { kind: "interpolated template literal", method: "spawn" } }], + }, ], }); }); diff --git a/eslint-factory/src/rules/no-child-process-interpolated-command.ts b/eslint-factory/src/rules/no-child-process-interpolated-command.ts index 8219b01b741..68106cc1cd8 100644 --- a/eslint-factory/src/rules/no-child-process-interpolated-command.ts +++ b/eslint-factory/src/rules/no-child-process-interpolated-command.ts @@ -133,7 +133,14 @@ function resolveChildProcessMethod(node: TSESTree.CallExpression, sourceCode: TS } if (callee.type !== AST_NODE_TYPES.MemberExpression || callee.computed) return null; - if (callee.object.type !== AST_NODE_TYPES.Identifier || callee.property.type !== AST_NODE_TYPES.Identifier) return null; + if (callee.property.type !== AST_NODE_TYPES.Identifier) return null; + + if (callee.object.type === AST_NODE_TYPES.CallExpression && isRequireChildProcess(callee.object)) { + const method = callee.property.name; + return method === "exec" || method === "execSync" || method === "spawn" || method === "spawnSync" || method === "execFile" || method === "execFileSync" ? method : null; + } + + if (callee.object.type !== AST_NODE_TYPES.Identifier) return null; if (!isChildProcessObjectBinding(callee.object.name, callee.object, sourceCode)) return null; const method = callee.property.name;