circle-ir 3.157.0 → 3.159.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.
@@ -24592,6 +24592,7 @@ var LanguageSourcesPass = class {
24592
24592
  additionalSanitizers.push(
24593
24593
  ...findJavaPathNormalizeStartsWithGuardSanitizers(code)
24594
24594
  );
24595
+ additionalSanitizers.push(...findJavaPathGetFileNameSanitizers(code));
24595
24596
  additionalSanitizers.push(...findJavaInlineCrlfStripLogSanitizers(code));
24596
24597
  additionalSanitizers.push(...findJavaArgvFormExecSanitizers(code));
24597
24598
  for (const finding of findJavaPatternFindings(code, graph.ir.meta.file)) {
@@ -26634,6 +26635,42 @@ function findJavaPathNormalizeStartsWithGuardSanitizers(code) {
26634
26635
  }
26635
26636
  return sanitizers;
26636
26637
  }
26638
+ function findJavaPathGetFileNameSanitizers(code) {
26639
+ const sanitizers = [];
26640
+ const lines = code.split("\n");
26641
+ const assignmentRe = /^\s*(?:(?:final\s+)?[A-Za-z_][\w.<>?,\s\[\]]*?\s+)?([A-Za-z_]\w*)\s*=\s*(.+?);\s*$/;
26642
+ const rhsHasGetFileNameRe = /\.\s*getFileName\s*\(\s*\)/;
26643
+ const rhsHasPathsChainRe = /\b(?:Paths\s*\.\s*get|Path\s*\.\s*of)\s*\(/;
26644
+ const candidates = [];
26645
+ for (let i2 = 0; i2 < lines.length; i2++) {
26646
+ const m = assignmentRe.exec(lines[i2]);
26647
+ if (!m) continue;
26648
+ const rhs = m[2];
26649
+ if (!rhsHasGetFileNameRe.test(rhs)) continue;
26650
+ if (!rhsHasPathsChainRe.test(rhs)) continue;
26651
+ candidates.push({ line: i2 + 1, boundVar: m[1] });
26652
+ }
26653
+ if (candidates.length === 0) return sanitizers;
26654
+ for (const c of candidates) {
26655
+ sanitizers.push({
26656
+ type: "java_path_get_filename",
26657
+ method: "getFileName",
26658
+ line: c.line,
26659
+ sanitizes: ["path_traversal", "external_taint_escape"]
26660
+ });
26661
+ const varRefRe = new RegExp(`\\b${c.boundVar}\\b`);
26662
+ for (let l = c.line; l < lines.length; l++) {
26663
+ if (!varRefRe.test(lines[l])) continue;
26664
+ sanitizers.push({
26665
+ type: "java_path_get_filename",
26666
+ method: "getFileName",
26667
+ line: l + 1,
26668
+ sanitizes: ["path_traversal", "external_taint_escape"]
26669
+ });
26670
+ }
26671
+ }
26672
+ return sanitizers;
26673
+ }
26637
26674
  function findJavaInlineCrlfStripLogSanitizers(code) {
26638
26675
  const sanitizers = [];
26639
26676
  const lines = code.split("\n");
@@ -30699,6 +30736,27 @@ var SinkFilterPass = class {
30699
30736
  return true;
30700
30737
  });
30701
30738
  }
30739
+ if (language === "java") {
30740
+ const sourceLines = ctx.code.split("\n");
30741
+ filtered = filtered.filter((sink) => {
30742
+ if (sink.type !== "xss") return true;
30743
+ const sinkLineText = sourceLines[sink.line - 1] ?? "";
30744
+ const receiverMatch = sinkLineText.match(/\b(\w+)\s*\.\s*(\w+)\s*\(/);
30745
+ const receiver = receiverMatch?.[1];
30746
+ const method = sink.method ?? receiverMatch?.[2];
30747
+ if ((method === "render" || method === "process" || method === "merge" || method === "renderTo" || method === "apply") && receiver) {
30748
+ const recvType = resolveJavaReceiverType(receiver, sink.line, sourceLines);
30749
+ if (recvType && COMPILED_TEMPLATE_TYPES.has(recvType)) return false;
30750
+ if (recvType && TEMPLATE_ENGINE_LITERAL_TARGETS.has(recvType)) {
30751
+ const args2 = extractJavaCallArgs(method, sinkLineText);
30752
+ if (args2 !== null && args2.length >= 1 && isJavaLiteralOrAnnotationAccessor(args2[0])) {
30753
+ return false;
30754
+ }
30755
+ }
30756
+ }
30757
+ return true;
30758
+ });
30759
+ }
30702
30760
  if (language === "java") {
30703
30761
  const sourceLines = ctx.code.split("\n");
30704
30762
  filtered = filtered.filter((sink) => {
@@ -37749,9 +37807,23 @@ var TEST_PATH_PATTERNS = [
37749
37807
  // JVM alt naming
37750
37808
  /\.test\.(?:java|kt)$/i
37751
37809
  ];
37810
+ var JVM_TEST_FILE_PATTERNS = [
37811
+ // JUnit/Spock/Spring convention: FooTest.java, FooTests.java,
37812
+ // FooSpec.java, FooIT.java, FooITCase.java, FooTestCase.java.
37813
+ /(?:^|\/)[A-Za-z_]\w*(?:Test|Tests|Spec|IT|ITCase|TestCase)\.(?:java|kt|scala|groovy)$/,
37814
+ // Alt naming: Foo.test.java, Foo.spec.java.
37815
+ /(?:^|\/)[A-Za-z_]\w*\.(?:test|spec)\.(?:java|kt|scala|groovy)$/i
37816
+ ];
37817
+ var JVM_SOURCE_FILE_RE = /\.(?:java|kt|scala|groovy)$/i;
37752
37818
  function isTestPath(filepath) {
37753
37819
  if (!filepath) return false;
37754
37820
  const normalized = filepath.replace(/\\/g, "/");
37821
+ if (JVM_SOURCE_FILE_RE.test(normalized)) {
37822
+ for (const pattern of JVM_TEST_FILE_PATTERNS) {
37823
+ if (pattern.test(normalized)) return true;
37824
+ }
37825
+ return false;
37826
+ }
37755
37827
  for (const pattern of TEST_PATH_PATTERNS) {
37756
37828
  if (pattern.test(normalized)) return true;
37757
37829
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "circle-ir",
3
- "version": "3.157.0",
3
+ "version": "3.159.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",