circle-ir 3.83.0 → 3.84.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12437,6 +12437,55 @@ function isSafeGoExecCommandCall(call, pattern, language) {
12437
12437
  if (SHELL_PROGRAMS.has(program)) return false;
12438
12438
  return true;
12439
12439
  }
12440
+ function isSafeRustCommandCall(call, pattern, language) {
12441
+ if (language !== "rust") return false;
12442
+ if (pattern.type !== "command_injection") return false;
12443
+ if (pattern.class !== void 0 && pattern.class !== "Command") return false;
12444
+ const SHELL_PROGRAMS = /* @__PURE__ */ new Set([
12445
+ "sh",
12446
+ "bash",
12447
+ "zsh",
12448
+ "dash",
12449
+ "ash",
12450
+ "ksh",
12451
+ "cmd",
12452
+ "cmd.exe",
12453
+ "powershell",
12454
+ "pwsh",
12455
+ "powershell.exe",
12456
+ "pwsh.exe"
12457
+ ]);
12458
+ const PROGRAM_RE = /\bCommand\s*::\s*new\s*\(\s*(?:r?"([^"]*)"|'([^']*)')/;
12459
+ const extractProgram = (text) => {
12460
+ const m = PROGRAM_RE.exec(text);
12461
+ if (!m) return null;
12462
+ const lit = m[1] ?? m[2] ?? "";
12463
+ return lit.split("/").pop() ?? lit;
12464
+ };
12465
+ if (pattern.method === "new") {
12466
+ const programArg = call.arguments.find((a) => a.position === 0);
12467
+ if (!programArg) return false;
12468
+ let program;
12469
+ if (programArg.literal !== null && programArg.literal !== void 0) {
12470
+ program = String(programArg.literal).split("/").pop() ?? String(programArg.literal);
12471
+ } else {
12472
+ const expr = (programArg.expression ?? "").trim();
12473
+ if (!(expr.startsWith('"') || expr.startsWith("'"))) {
12474
+ return false;
12475
+ }
12476
+ const stripped = expr.slice(1, -1);
12477
+ program = stripped.split("/").pop() ?? stripped;
12478
+ }
12479
+ return !SHELL_PROGRAMS.has(program);
12480
+ }
12481
+ if (pattern.method === "arg" || pattern.method === "args" || pattern.method === "spawn" || pattern.method === "output") {
12482
+ const receiverText = call.receiver ?? "";
12483
+ const program = extractProgram(receiverText);
12484
+ if (program === null) return false;
12485
+ return !SHELL_PROGRAMS.has(program);
12486
+ }
12487
+ return false;
12488
+ }
12440
12489
  var CLASS_LITERAL_RE = /^(?:[A-Za-z_][\w]*\.)*[A-Z][\w]*(?:\[\])*\.class$/;
12441
12490
  function argIsClassLiteral(call, position) {
12442
12491
  const arg = call.arguments.find((a) => a.position === position);
@@ -12459,6 +12508,9 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines) {
12459
12508
  if (isSafeGoExecCommandCall(call, pattern, language)) {
12460
12509
  continue;
12461
12510
  }
12511
+ if (isSafeRustCommandCall(call, pattern, language)) {
12512
+ continue;
12513
+ }
12462
12514
  if (pattern.safe_if_class_literal_at !== void 0 && argIsClassLiteral(call, pattern.safe_if_class_literal_at)) {
12463
12515
  continue;
12464
12516
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "circle-ir",
3
- "version": "3.83.0",
3
+ "version": "3.84.0",
4
4
  "description": "High-performance Static Application Security Testing (SAST) library for detecting security vulnerabilities through taint analysis",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",