cognium-dev 3.154.0 → 3.156.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.
Files changed (2) hide show
  1. package/dist/cli.js +469 -14
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -11659,6 +11659,7 @@ var DEFAULT_SANITIZERS = [
11659
11659
  { method: "parseDouble", class: "Double", removes: ["sql_injection", "command_injection", "path_traversal", "code_injection"] },
11660
11660
  { method: "parseShort", class: "Short", removes: ["sql_injection", "command_injection", "path_traversal", "code_injection"] },
11661
11661
  { method: "parseByte", class: "Byte", removes: ["sql_injection", "command_injection", "path_traversal", "code_injection"] },
11662
+ { method: "parseBoolean", class: "Boolean", removes: ["sql_injection", "command_injection", "path_traversal", "code_injection", "xss", "crlf", "log_injection", "xpath_injection", "ldap_injection", "xxe"] },
11662
11663
  { method: "fromString", class: "UUID", removes: ["sql_injection", "command_injection", "path_traversal", "code_injection"] },
11663
11664
  { method: "BigInt", removes: ["sql_injection", "nosql_injection", "command_injection", "path_traversal", "code_injection"] },
11664
11665
  { method: "Atoi", class: "strconv", removes: ["sql_injection", "command_injection", "path_traversal", "code_injection"] },
@@ -12977,7 +12978,8 @@ function matchesSinkPattern(call, pattern, typeHierarchy, language) {
12977
12978
  if (pattern.class === "constructor") {
12978
12979
  return true;
12979
12980
  }
12980
- if (call.receiver_type && call.receiver_type === pattern.class) {} else if (call.receiver_type_fqn && call.receiver_type_fqn.endsWith("." + pattern.class)) {} else if (call.receiver && !receiverMightBeClass(call.receiver, pattern.class)) {
12981
+ const subtypeArgArityOk = !pattern.arg_positions || pattern.arg_positions.length === 0 || pattern.arg_positions.every((pos) => pos < (call.arguments?.length ?? 0));
12982
+ if (call.receiver_type && call.receiver_type === pattern.class) {} else if (call.receiver_type && typeHierarchy && subtypeArgArityOk && typeHierarchy.isSubtypeOf(call.receiver_type, pattern.class)) {} else if (call.receiver_type_fqn && call.receiver_type_fqn.endsWith("." + pattern.class)) {} else if (call.receiver_type_fqn && typeHierarchy && subtypeArgArityOk && typeHierarchy.isSubtypeOf(call.receiver_type_fqn, pattern.class)) {} else if (call.receiver && !receiverMightBeClass(call.receiver, pattern.class)) {
12981
12983
  if (typeHierarchy && typeHierarchy.couldBeType(call.receiver, pattern.class)) {
12982
12984
  return true;
12983
12985
  }
@@ -13770,6 +13772,18 @@ class CodeGraph {
13770
13772
  }
13771
13773
  return this._chainsByFromDef;
13772
13774
  }
13775
+ _chainsByToDef = null;
13776
+ get chainsByToDef() {
13777
+ if (!this._chainsByToDef) {
13778
+ this._chainsByToDef = new Map;
13779
+ for (const chain of this.ir.dfg.chains ?? []) {
13780
+ const arr = this._chainsByToDef.get(chain.to_def) ?? [];
13781
+ arr.push(chain);
13782
+ this._chainsByToDef.set(chain.to_def, arr);
13783
+ }
13784
+ }
13785
+ return this._chainsByToDef;
13786
+ }
13773
13787
  _callsByLine = null;
13774
13788
  get callsByLine() {
13775
13789
  if (!this._callsByLine) {
@@ -14303,8 +14317,150 @@ function createWithJdkTypes() {
14303
14317
  for (const type of [...jdbcTypes, ...ioTypes, ...servletTypes]) {
14304
14318
  resolver.addType(type, "jdk", type.package);
14305
14319
  }
14320
+ registerCommonLibraries(resolver);
14306
14321
  return resolver;
14307
14322
  }
14323
+ function registerCommonLibraries(resolver) {
14324
+ const apacheHttpClient4x = [
14325
+ {
14326
+ name: "HttpClient",
14327
+ kind: "interface",
14328
+ package: "org.apache.http.client",
14329
+ extends: null,
14330
+ implements: [],
14331
+ annotations: [],
14332
+ methods: [],
14333
+ fields: [],
14334
+ start_line: 0,
14335
+ end_line: 0
14336
+ },
14337
+ {
14338
+ name: "AbstractHttpClient",
14339
+ kind: "class",
14340
+ package: "org.apache.http.impl.client",
14341
+ extends: null,
14342
+ implements: ["org.apache.http.client.HttpClient"],
14343
+ annotations: [],
14344
+ methods: [],
14345
+ fields: [],
14346
+ start_line: 0,
14347
+ end_line: 0
14348
+ },
14349
+ {
14350
+ name: "CloseableHttpClient",
14351
+ kind: "class",
14352
+ package: "org.apache.http.impl.client",
14353
+ extends: null,
14354
+ implements: ["org.apache.http.client.HttpClient"],
14355
+ annotations: [],
14356
+ methods: [],
14357
+ fields: [],
14358
+ start_line: 0,
14359
+ end_line: 0
14360
+ },
14361
+ {
14362
+ name: "InternalHttpClient",
14363
+ kind: "class",
14364
+ package: "org.apache.http.impl.client",
14365
+ extends: "org.apache.http.impl.client.CloseableHttpClient",
14366
+ implements: [],
14367
+ annotations: [],
14368
+ methods: [],
14369
+ fields: [],
14370
+ start_line: 0,
14371
+ end_line: 0
14372
+ },
14373
+ {
14374
+ name: "MinimalHttpClient",
14375
+ kind: "class",
14376
+ package: "org.apache.http.impl.client",
14377
+ extends: "org.apache.http.impl.client.CloseableHttpClient",
14378
+ implements: [],
14379
+ annotations: [],
14380
+ methods: [],
14381
+ fields: [],
14382
+ start_line: 0,
14383
+ end_line: 0
14384
+ },
14385
+ {
14386
+ name: "DefaultHttpClient",
14387
+ kind: "class",
14388
+ package: "org.apache.http.impl.client",
14389
+ extends: "org.apache.http.impl.client.AbstractHttpClient",
14390
+ implements: [],
14391
+ annotations: [],
14392
+ methods: [],
14393
+ fields: [],
14394
+ start_line: 0,
14395
+ end_line: 0
14396
+ },
14397
+ {
14398
+ name: "SystemDefaultHttpClient",
14399
+ kind: "class",
14400
+ package: "org.apache.http.impl.client",
14401
+ extends: "org.apache.http.impl.client.DefaultHttpClient",
14402
+ implements: [],
14403
+ annotations: [],
14404
+ methods: [],
14405
+ fields: [],
14406
+ start_line: 0,
14407
+ end_line: 0
14408
+ }
14409
+ ];
14410
+ const apacheHttpClient5x = [
14411
+ {
14412
+ name: "HttpClient",
14413
+ kind: "interface",
14414
+ package: "org.apache.hc.client5.http.classic",
14415
+ extends: null,
14416
+ implements: [],
14417
+ annotations: [],
14418
+ methods: [],
14419
+ fields: [],
14420
+ start_line: 0,
14421
+ end_line: 0
14422
+ },
14423
+ {
14424
+ name: "CloseableHttpClient",
14425
+ kind: "class",
14426
+ package: "org.apache.hc.client5.http.impl.classic",
14427
+ extends: null,
14428
+ implements: ["org.apache.hc.client5.http.classic.HttpClient"],
14429
+ annotations: [],
14430
+ methods: [],
14431
+ fields: [],
14432
+ start_line: 0,
14433
+ end_line: 0
14434
+ },
14435
+ {
14436
+ name: "InternalHttpClient",
14437
+ kind: "class",
14438
+ package: "org.apache.hc.client5.http.impl.classic",
14439
+ extends: "org.apache.hc.client5.http.impl.classic.CloseableHttpClient",
14440
+ implements: [],
14441
+ annotations: [],
14442
+ methods: [],
14443
+ fields: [],
14444
+ start_line: 0,
14445
+ end_line: 0
14446
+ },
14447
+ {
14448
+ name: "MinimalHttpClient",
14449
+ kind: "class",
14450
+ package: "org.apache.hc.client5.http.impl.classic",
14451
+ extends: "org.apache.hc.client5.http.impl.classic.CloseableHttpClient",
14452
+ implements: [],
14453
+ annotations: [],
14454
+ methods: [],
14455
+ fields: [],
14456
+ start_line: 0,
14457
+ end_line: 0
14458
+ }
14459
+ ];
14460
+ for (const type of [...apacheHttpClient4x, ...apacheHttpClient5x]) {
14461
+ resolver.addType(type, "common-libraries", type.package);
14462
+ }
14463
+ }
14308
14464
  // ../circle-ir/dist/resolution/symbol-table.js
14309
14465
  class SymbolTable {
14310
14466
  exports = new Map;
@@ -15640,6 +15796,45 @@ class AnalysisPipeline {
15640
15796
  return { results, findings };
15641
15797
  }
15642
15798
  }
15799
+ // ../circle-ir/dist/analysis/dfg-walk.js
15800
+ function walkBackwardDefs(startDefId, chainsByToDef, defById, options = {}) {
15801
+ const maxHops = options.maxHops ?? 32;
15802
+ const visited = new Set;
15803
+ const lines = new Set;
15804
+ let hopCapReached = false;
15805
+ const startDef = defById.get(startDefId);
15806
+ if (!startDef) {
15807
+ return { visited, lines, hopCapReached: false };
15808
+ }
15809
+ visited.add(startDefId);
15810
+ lines.add(startDef.line);
15811
+ const queue = [startDefId];
15812
+ let hops = 0;
15813
+ while (queue.length > 0) {
15814
+ if (hops >= maxHops) {
15815
+ hopCapReached = true;
15816
+ break;
15817
+ }
15818
+ hops++;
15819
+ const currentId = queue.shift();
15820
+ const incoming = chainsByToDef.get(currentId);
15821
+ if (!incoming)
15822
+ continue;
15823
+ for (const chain of incoming) {
15824
+ const fromId = chain.from_def;
15825
+ if (visited.has(fromId))
15826
+ continue;
15827
+ visited.add(fromId);
15828
+ const fromDef = defById.get(fromId);
15829
+ if (fromDef) {
15830
+ lines.add(fromDef.line);
15831
+ }
15832
+ queue.push(fromId);
15833
+ }
15834
+ }
15835
+ return { visited, lines, hopCapReached };
15836
+ }
15837
+
15643
15838
  // ../circle-ir/dist/analysis/taint-propagation.js
15644
15839
  function buildSanitizersByLine(sanitizers) {
15645
15840
  const out2 = new Map;
@@ -15721,7 +15916,11 @@ function propagateTaint(graphOrDfg, callsOrSources, sourcesOrSinks, sinksOrSanit
15721
15916
  if (allTaintedDefIds.has(use.def_id)) {
15722
15917
  const taintInfo = taintByDefId.get(use.def_id);
15723
15918
  if (taintInfo) {
15724
- const isSanitized = checkSanitized(taintInfo.line, sink.line, sink.type, sanitizersByLine);
15919
+ const isSanitized = checkSanitized(taintInfo.line, sink.line, sink.type, sanitizersByLine, {
15920
+ startDefId: use.def_id,
15921
+ chainsByToDef: graph.chainsByToDef,
15922
+ defById
15923
+ });
15725
15924
  if (!isSanitized.sanitized) {
15726
15925
  const source = sources.find((s) => s.line === taintInfo.sourceLine);
15727
15926
  if (source) {
@@ -15851,20 +16050,36 @@ var KNOWN_SINK_TYPES = new Set([
15851
16050
  "crlf",
15852
16051
  "mass_assignment"
15853
16052
  ]);
15854
- function checkSanitized(_fromLine, toLine, sinkType, sanitizersByLine) {
15855
- const sanitizersAtTarget = sanitizersByLine.get(toLine);
15856
- if (!sanitizersAtTarget || sanitizersAtTarget.length === 0) {
15857
- return { sanitized: false };
15858
- }
16053
+ function checkSanitized(_fromLine, toLine, sinkType, sanitizersByLine, ctx) {
15859
16054
  const isKnownSinkType = KNOWN_SINK_TYPES.has(sinkType);
15860
- for (const san of sanitizersAtTarget) {
15861
- if (isKnownSinkType) {
15862
- if (san.sanitizes.includes(sinkType)) {
16055
+ const sanitizersAtTarget = sanitizersByLine.get(toLine);
16056
+ if (sanitizersAtTarget && sanitizersAtTarget.length > 0) {
16057
+ for (const san of sanitizersAtTarget) {
16058
+ if (isKnownSinkType) {
16059
+ if (san.sanitizes.includes(sinkType)) {
16060
+ return { sanitized: true, sanitizer: san };
16061
+ }
16062
+ } else if (san.sanitizes.length > 0) {
15863
16063
  return { sanitized: true, sanitizer: san };
15864
16064
  }
15865
- } else {
15866
- if (san.sanitizes.length > 0) {
15867
- return { sanitized: true, sanitizer: san };
16065
+ }
16066
+ }
16067
+ if (ctx) {
16068
+ const walk = walkBackwardDefs(ctx.startDefId, ctx.chainsByToDef, ctx.defById, { maxHops: ctx.maxHops ?? 32 });
16069
+ for (const line of walk.lines) {
16070
+ if (line === toLine)
16071
+ continue;
16072
+ const sansAtLine = sanitizersByLine.get(line);
16073
+ if (!sansAtLine || sansAtLine.length === 0)
16074
+ continue;
16075
+ for (const san of sansAtLine) {
16076
+ if (isKnownSinkType) {
16077
+ if (san.sanitizes.includes(sinkType)) {
16078
+ return { sanitized: true, sanitizer: san };
16079
+ }
16080
+ } else if (san.sanitizes.length > 0) {
16081
+ return { sanitized: true, sanitizer: san };
16082
+ }
15868
16083
  }
15869
16084
  }
15870
16085
  }
@@ -24132,6 +24347,20 @@ function findJavaScriptDOMSinks(sourceCode, language) {
24132
24347
  method = "cssText";
24133
24348
  else if (line.includes("style.textContent"))
24134
24349
  method = "textContent";
24350
+ if (method === "document.write" || method === "document.writeln") {
24351
+ const argMatch = line.match(/document\.write(?:ln)?\s*\(\s*([^)]*)\)/);
24352
+ if (argMatch) {
24353
+ const arg = argMatch[1].trim();
24354
+ if (!arg.includes("+")) {
24355
+ const doubleQ = /^"(?:[^"\\]|\\.)*"$/;
24356
+ const singleQ = /^'(?:[^'\\]|\\.)*'$/;
24357
+ const backtick = /^`(?:[^`\\$]|\\.|\$(?!\{))*`$/;
24358
+ if (doubleQ.test(arg) || singleQ.test(arg) || backtick.test(arg)) {
24359
+ break;
24360
+ }
24361
+ }
24362
+ }
24363
+ }
24135
24364
  const alreadyExists = sinks.some((s) => s.line === lineNumber && s.cwe === cwe);
24136
24365
  if (!alreadyExists) {
24137
24366
  sinks.push({ type, cwe, severity, line: lineNumber, location: line.trim().substring(0, 80), method });
@@ -29405,6 +29634,202 @@ class LibraryProfileSourceGatePass {
29405
29634
  }
29406
29635
  }
29407
29636
 
29637
+ // ../circle-ir/dist/analysis/passes/mybatis-annotation-sql-sink-pass.js
29638
+ var MYBATIS_SQL_ANNOTATIONS = new Set([
29639
+ "Select",
29640
+ "Update",
29641
+ "Insert",
29642
+ "Delete",
29643
+ "SelectProvider",
29644
+ "UpdateProvider",
29645
+ "InsertProvider",
29646
+ "DeleteProvider"
29647
+ ]);
29648
+ var DOLLAR_BRACE_RE = /\$\{([A-Za-z_][A-Za-z0-9_]*)(?:\.[A-Za-z0-9_.]+)?\}/g;
29649
+ function parsePositionalRef(name2) {
29650
+ const paramMatch = /^param(\d+)$/.exec(name2);
29651
+ if (paramMatch) {
29652
+ const oneBased = Number.parseInt(paramMatch[1], 10);
29653
+ if (Number.isFinite(oneBased) && oneBased >= 1)
29654
+ return oneBased - 1;
29655
+ }
29656
+ const zeroMatch = /^(\d+)$/.exec(name2);
29657
+ if (zeroMatch) {
29658
+ const zeroBased = Number.parseInt(zeroMatch[1], 10);
29659
+ if (Number.isFinite(zeroBased) && zeroBased >= 0)
29660
+ return zeroBased;
29661
+ }
29662
+ return null;
29663
+ }
29664
+ function extractAnnotationBody(annotation) {
29665
+ const openIdx = annotation.indexOf("(");
29666
+ if (openIdx < 0)
29667
+ return null;
29668
+ const closeIdx = annotation.lastIndexOf(")");
29669
+ if (closeIdx <= openIdx)
29670
+ return null;
29671
+ return annotation.substring(openIdx + 1, closeIdx);
29672
+ }
29673
+ function annotationName(annotation) {
29674
+ const openIdx = annotation.indexOf("(");
29675
+ return openIdx < 0 ? annotation : annotation.substring(0, openIdx);
29676
+ }
29677
+ function extractParamName(annotation) {
29678
+ if (annotationName(annotation) !== "Param")
29679
+ return null;
29680
+ const body2 = extractAnnotationBody(annotation);
29681
+ if (body2 === null)
29682
+ return null;
29683
+ const strMatch = /^\s*["']([^"']*)["']/.exec(body2);
29684
+ return strMatch ? strMatch[1] : null;
29685
+ }
29686
+ function extractDollarBraceRefs(annotationBody) {
29687
+ const seen = new Set;
29688
+ const out2 = [];
29689
+ DOLLAR_BRACE_RE.lastIndex = 0;
29690
+ let m;
29691
+ while ((m = DOLLAR_BRACE_RE.exec(annotationBody)) !== null) {
29692
+ const name2 = m[1];
29693
+ if (!seen.has(name2)) {
29694
+ seen.add(name2);
29695
+ out2.push(name2);
29696
+ }
29697
+ }
29698
+ return out2;
29699
+ }
29700
+ function fileImportsMyBatis(imports) {
29701
+ for (const imp of imports) {
29702
+ const pkg = imp.from_package;
29703
+ if (!pkg)
29704
+ continue;
29705
+ if (pkg === "org.apache.ibatis.annotations" || pkg.startsWith("org.apache.ibatis.annotations.") || pkg === "org.apache.ibatis" || pkg.startsWith("org.apache.ibatis.")) {
29706
+ return true;
29707
+ }
29708
+ }
29709
+ return false;
29710
+ }
29711
+ function correlateDollarBraceToArgPositions(method, refs) {
29712
+ const paramNameToIndex = new Map;
29713
+ method.parameters.forEach((param, idx) => {
29714
+ for (const ann of param.annotations) {
29715
+ const paramName = extractParamName(ann);
29716
+ if (paramName !== null) {
29717
+ paramNameToIndex.set(paramName, idx);
29718
+ }
29719
+ }
29720
+ });
29721
+ const positions = new Set;
29722
+ for (const ref of refs) {
29723
+ const namedIdx = paramNameToIndex.get(ref);
29724
+ if (namedIdx !== undefined) {
29725
+ positions.add(namedIdx);
29726
+ continue;
29727
+ }
29728
+ const positionalIdx = parsePositionalRef(ref);
29729
+ if (positionalIdx !== null && positionalIdx < method.parameters.length) {
29730
+ positions.add(positionalIdx);
29731
+ }
29732
+ }
29733
+ return Array.from(positions).sort((a, b) => a - b);
29734
+ }
29735
+ function isMapperMethodCall(call, interfaceSimpleName, interfaceFqn, methodName) {
29736
+ const target = call.resolution?.target;
29737
+ if (target) {
29738
+ const suffix = `${interfaceSimpleName}.${methodName}`;
29739
+ const suffixFqn = `${interfaceFqn}.${methodName}`;
29740
+ if (target === suffix || target === suffixFqn || target.endsWith("." + suffix) || target.endsWith("." + suffixFqn)) {
29741
+ return true;
29742
+ }
29743
+ }
29744
+ if (call.method_name !== methodName)
29745
+ return false;
29746
+ if (call.receiver_type === interfaceSimpleName)
29747
+ return true;
29748
+ if (call.receiver_type_fqn === interfaceFqn)
29749
+ return true;
29750
+ return false;
29751
+ }
29752
+
29753
+ class MyBatisAnnotationSqlSinkPass {
29754
+ name = "mybatis-annotation-sql-sink";
29755
+ category = "security";
29756
+ run(ctx) {
29757
+ if (ctx.language !== "java") {
29758
+ return { annotatedMethodCount: 0, addedSinkCount: 0 };
29759
+ }
29760
+ const { types, imports, calls } = ctx.graph.ir;
29761
+ if (!fileImportsMyBatis(imports)) {
29762
+ return { annotatedMethodCount: 0, addedSinkCount: 0 };
29763
+ }
29764
+ const mapperMethods = [];
29765
+ for (const type of types) {
29766
+ if (type.kind !== "interface")
29767
+ continue;
29768
+ for (const method of type.methods) {
29769
+ let matchedRefs = [];
29770
+ for (const ann of method.annotations) {
29771
+ if (!MYBATIS_SQL_ANNOTATIONS.has(annotationName(ann)))
29772
+ continue;
29773
+ const body2 = extractAnnotationBody(ann);
29774
+ if (body2 === null)
29775
+ continue;
29776
+ const refs = extractDollarBraceRefs(body2);
29777
+ if (refs.length > 0) {
29778
+ matchedRefs = [...matchedRefs, ...refs];
29779
+ }
29780
+ }
29781
+ if (matchedRefs.length === 0)
29782
+ continue;
29783
+ const positions = correlateDollarBraceToArgPositions(method, matchedRefs);
29784
+ if (positions.length === 0)
29785
+ continue;
29786
+ const interfaceFqn = type.package ? `${type.package}.${type.name}` : type.name;
29787
+ mapperMethods.push({
29788
+ interfaceSimpleName: type.name,
29789
+ interfaceFqn,
29790
+ methodName: method.name,
29791
+ taintedArgPositions: positions
29792
+ });
29793
+ }
29794
+ }
29795
+ if (mapperMethods.length === 0) {
29796
+ return {
29797
+ annotatedMethodCount: 0,
29798
+ addedSinkCount: 0
29799
+ };
29800
+ }
29801
+ const sinks = ctx.hasResult("taint-matcher") ? ctx.getResult("taint-matcher").sinks : ctx.graph.ir.taint.sinks;
29802
+ let addedSinkCount = 0;
29803
+ for (const call of calls) {
29804
+ for (const rec of mapperMethods) {
29805
+ if (!isMapperMethodCall(call, rec.interfaceSimpleName, rec.interfaceFqn, rec.methodName)) {
29806
+ continue;
29807
+ }
29808
+ const line = call.location.line;
29809
+ if (sinks.some((s) => s.line === line && s.type === "sql_injection" && s.method === rec.methodName)) {
29810
+ continue;
29811
+ }
29812
+ const receiverLoc = call.receiver ? `${call.receiver}.${rec.methodName}()` : `${rec.methodName}()`;
29813
+ sinks.push({
29814
+ type: "sql_injection",
29815
+ cwe: "CWE-89",
29816
+ location: call.in_method ? `${receiverLoc} in ${call.in_method}` : receiverLoc,
29817
+ line,
29818
+ confidence: 0.95,
29819
+ method: rec.methodName,
29820
+ argPositions: rec.taintedArgPositions,
29821
+ class: rec.interfaceSimpleName
29822
+ });
29823
+ addedSinkCount++;
29824
+ }
29825
+ }
29826
+ return {
29827
+ annotatedMethodCount: mapperMethods.length,
29828
+ addedSinkCount
29829
+ };
29830
+ }
29831
+ }
29832
+
29408
29833
  // ../circle-ir/dist/analysis/passes/sink-filter-pass.js
29409
29834
  var JS_XSS_SANITIZERS = [
29410
29835
  /\bDOMPurify\.sanitize\s*\(/,
@@ -38207,6 +38632,31 @@ class WeakHashPass {
38207
38632
  }
38208
38633
  }
38209
38634
 
38635
+ // ../circle-ir/dist/analysis/path-classification.js
38636
+ var TEST_PATH_PATTERNS = [
38637
+ /(^|\/)test\//i,
38638
+ /(^|\/)tests\//i,
38639
+ /(^|\/)testing\//i,
38640
+ /(^|\/)__tests__\//i,
38641
+ /(^|\/)spec\//i,
38642
+ /_test\.go$/i,
38643
+ /(^|\/)test_[^/]+\.py$/i,
38644
+ /_test\.py$/i,
38645
+ /\.test\.(?:tsx?|jsx?|mjs|cjs)$/i,
38646
+ /\.spec\.(?:tsx?|jsx?|mjs|cjs)$/i,
38647
+ /\.test\.(?:java|kt)$/i
38648
+ ];
38649
+ function isTestPath(filepath) {
38650
+ if (!filepath)
38651
+ return false;
38652
+ const normalized = filepath.replace(/\\/g, "/");
38653
+ for (const pattern of TEST_PATH_PATTERNS) {
38654
+ if (pattern.test(normalized))
38655
+ return true;
38656
+ }
38657
+ return false;
38658
+ }
38659
+
38210
38660
  // ../circle-ir/dist/analysis/passes/weak-crypto-pass.js
38211
38661
  var WEAK_CIPHER_BASES = new Set([
38212
38662
  "des",
@@ -38422,6 +38872,9 @@ class WeakCryptoPass {
38422
38872
  if (isProtocolMandatedCryptoFile(file, code)) {
38423
38873
  return { findings: [] };
38424
38874
  }
38875
+ if (isTestPath(file)) {
38876
+ return { findings: [] };
38877
+ }
38425
38878
  const findings = [];
38426
38879
  const constProp = ctx.hasResult("constant-propagation") ? ctx.getResult("constant-propagation") : null;
38427
38880
  const literalBindings = scanLiteralBindings(code, language);
@@ -42180,6 +42633,8 @@ async function analyze(code, filePath, language, options = {}) {
42180
42633
  pipeline.add(new SourceSemanticsPass);
42181
42634
  if (!disabledPasses.has("library-profile-source-gate"))
42182
42635
  pipeline.add(new LibraryProfileSourceGatePass);
42636
+ if (!disabledPasses.has("mybatis-annotation-sql-sink"))
42637
+ pipeline.add(new MyBatisAnnotationSqlSinkPass);
42183
42638
  pipeline.add(new SinkFilterPass);
42184
42639
  if (!disabledPasses.has("sink-semantics"))
42185
42640
  pipeline.add(new SinkSemanticsPass);
@@ -43125,7 +43580,7 @@ var colors = {
43125
43580
  };
43126
43581
 
43127
43582
  // src/version.ts
43128
- var version = "3.154.0";
43583
+ var version = "3.156.0";
43129
43584
 
43130
43585
  // src/formatters.ts
43131
43586
  var LIBRARY_API_SURFACE_TAG2 = "library-api-surface:caller-responsibility";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cognium-dev",
3
- "version": "3.154.0",
3
+ "version": "3.156.0",
4
4
  "description": "Static Application Security Testing CLI for detecting security vulnerabilities via taint tracking",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -66,7 +66,7 @@
66
66
  },
67
67
  "dependencies": {
68
68
  "@cognium/project-profile-detect": "^1.1.0",
69
- "circle-ir": "^3.154.0"
69
+ "circle-ir": "^3.156.0"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/node": "^25.5.0",