fix: allow safe Node self-reexec scans

This commit is contained in:
Gustavo Madeira Santana
2026-04-22 20:53:47 -04:00
parent 0520aeb244
commit d17687e4e8
2 changed files with 23 additions and 0 deletions

View File

@@ -241,6 +241,17 @@ const options: ExecOptions = { timeout: 5000 };
expect(findings.some((f) => f.ruleId === "dangerous-exec")).toBe(false);
});
it("does not flag argv-only self-reexec as shell command execution", () => {
const source = `
import { spawn } from "node:child_process";
const child = spawn(process.execPath, [distEntryPath, ...args], {
stdio: ["pipe", "pipe", "pipe"],
});
`;
const findings = scanSource(source, "plugin.ts");
expect(findings.some((f) => f.ruleId === "dangerous-exec")).toBe(false);
});
it("returns empty array for clean plugin code", () => {
const source = `
export function greet(name: string): string {

View File

@@ -216,6 +216,15 @@ function truncateEvidence(evidence: string, maxLen = 120): string {
return `${evidence.slice(0, maxLen)}`;
}
function isAllowedDangerousExecEvidence(rule: LineRule, line: string): boolean {
if (rule.ruleId !== "dangerous-exec") {
return false;
}
// Spawning the current Node executable with an argv array is not shell
// execution. Keep direct shell/process launches blocked below.
return /\bspawn\s*\(\s*process\.execPath\s*,/.test(line);
}
export function scanSource(source: string, filePath: string): SkillScanFinding[] {
const findings: SkillScanFinding[] = [];
const lines = source.split("\n");
@@ -238,6 +247,9 @@ export function scanSource(source: string, filePath: string): SkillScanFinding[]
if (!match) {
continue;
}
if (isAllowedDangerousExecEvidence(rule, line)) {
continue;
}
// Special handling for suspicious-network: check port
if (rule.ruleId === "suspicious-network") {