circle-ir 3.73.0 → 3.74.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.
@@ -11818,11 +11818,21 @@ var DEFAULT_SANITIZERS = [
11818
11818
  // (defense-in-depth — mirrors Java getCanonicalPath in this table; the
11819
11819
  // stricter Clean+HasPrefix guard recognition is tracked separately).
11820
11820
  // EvalSymlinks is the Go equivalent of Java's Path.toRealPath.
11821
- { method: "Base", class: "filepath", removes: ["path_traversal"] },
11822
- { method: "Base", class: "path", removes: ["path_traversal"] },
11823
- { method: "Clean", class: "filepath", removes: ["path_traversal"] },
11824
- { method: "Clean", class: "path", removes: ["path_traversal"] },
11825
- { method: "EvalSymlinks", class: "filepath", removes: ["path_traversal"] },
11821
+ // Sprint 24 (#102 FP-27): broadened to cover external_taint_escape (CWE-668)
11822
+ // fallback so canonicalised paths don't trigger the synthetic sink.
11823
+ { method: "Base", class: "filepath", removes: ["path_traversal", "external_taint_escape"] },
11824
+ { method: "Base", class: "path", removes: ["path_traversal", "external_taint_escape"] },
11825
+ { method: "Clean", class: "filepath", removes: ["path_traversal", "external_taint_escape"] },
11826
+ { method: "Clean", class: "path", removes: ["path_traversal", "external_taint_escape"] },
11827
+ { method: "EvalSymlinks", class: "filepath", removes: ["path_traversal", "external_taint_escape"] },
11828
+ // Go html/template escape helpers (#102 FP-27) — registered explicitly because
11829
+ // configs/sinks/golang.json is not loaded at runtime.
11830
+ { method: "EscapeString", class: "html", removes: ["xss", "external_taint_escape", "log_injection", "open_redirect"] },
11831
+ { method: "HTMLEscapeString", class: "template", removes: ["xss", "external_taint_escape", "log_injection", "open_redirect"] },
11832
+ { method: "JSEscapeString", class: "template", removes: ["xss", "external_taint_escape", "log_injection"] },
11833
+ { method: "URLQueryEscaper", class: "template", removes: ["xss", "external_taint_escape", "open_redirect"] },
11834
+ { method: "QueryEscape", class: "url", removes: ["xss", "external_taint_escape", "open_redirect"] },
11835
+ { method: "PathEscape", class: "url", removes: ["xss", "external_taint_escape", "open_redirect"] },
11826
11836
  // Log Injection sanitizers
11827
11837
  { method: "replace", removes: ["log_injection"] },
11828
11838
  // Used to remove newlines/control chars
@@ -12342,6 +12352,42 @@ function isSafePythonSubprocessCall(call, pattern, language) {
12342
12352
  }
12343
12353
  return true;
12344
12354
  }
12355
+ function isSafeGoExecCommandCall(call, pattern, language) {
12356
+ if (language !== "go") return false;
12357
+ if (pattern.type !== "command_injection") return false;
12358
+ if (pattern.class !== "exec") return false;
12359
+ if (pattern.method !== "Command" && pattern.method !== "CommandContext") return false;
12360
+ const programArgPos = pattern.method === "CommandContext" ? 1 : 0;
12361
+ const programArg = call.arguments.find((a) => a.position === programArgPos);
12362
+ if (!programArg) return false;
12363
+ let program;
12364
+ if (programArg.literal !== null && programArg.literal !== void 0) {
12365
+ program = String(programArg.literal).split("/").pop() ?? String(programArg.literal);
12366
+ } else {
12367
+ const expr = (programArg.expression ?? "").trim();
12368
+ if (!(expr.startsWith('"') || expr.startsWith("`") || expr.startsWith("'"))) {
12369
+ return false;
12370
+ }
12371
+ const stripped = expr.slice(1, -1);
12372
+ program = stripped.split("/").pop() ?? stripped;
12373
+ }
12374
+ const SHELL_PROGRAMS = /* @__PURE__ */ new Set([
12375
+ "sh",
12376
+ "bash",
12377
+ "zsh",
12378
+ "dash",
12379
+ "ash",
12380
+ "ksh",
12381
+ "cmd",
12382
+ "cmd.exe",
12383
+ "powershell",
12384
+ "pwsh",
12385
+ "powershell.exe",
12386
+ "pwsh.exe"
12387
+ ]);
12388
+ if (SHELL_PROGRAMS.has(program)) return false;
12389
+ return true;
12390
+ }
12345
12391
  var CLASS_LITERAL_RE = /^(?:[A-Za-z_][\w]*\.)*[A-Z][\w]*(?:\[\])*\.class$/;
12346
12392
  function argIsClassLiteral(call, position) {
12347
12393
  const arg = call.arguments.find((a) => a.position === position);
@@ -12361,6 +12407,9 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines) {
12361
12407
  if (isSafePythonSubprocessCall(call, pattern, language)) {
12362
12408
  continue;
12363
12409
  }
12410
+ if (isSafeGoExecCommandCall(call, pattern, language)) {
12411
+ continue;
12412
+ }
12364
12413
  if (pattern.safe_if_class_literal_at !== void 0 && argIsClassLiteral(call, pattern.safe_if_class_literal_at)) {
12365
12414
  continue;
12366
12415
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "circle-ir",
3
- "version": "3.73.0",
3
+ "version": "3.74.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",