cognium-dev 3.152.0 → 3.154.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 +664 -252
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -10611,10 +10611,6 @@ var DEFAULT_SINKS = [
10611
10611
  { method: "FileOutputStream", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10612
10612
  { method: "FileReader", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10613
10613
  { method: "FileWriter", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10614
- { method: "getResource", class: "ClassLoader", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10615
- { method: "getResourceAsStream", class: "ClassLoader", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10616
- { method: "getResource", class: "Class", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10617
- { method: "getResourceAsStream", class: "Class", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10618
10614
  { method: "get", class: "Paths", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10619
10615
  { method: "of", class: "Path", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10620
10616
  { method: "readAllBytes", class: "Files", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
@@ -10627,9 +10623,6 @@ var DEFAULT_SINKS = [
10627
10623
  { method: "newBufferedWriter", class: "Files", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10628
10624
  { method: "copy", class: "Files", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1] },
10629
10625
  { method: "move", class: "Files", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1] },
10630
- { method: "exists", class: "Files", type: "path_traversal", cwe: "CWE-22", severity: "medium", arg_positions: [0] },
10631
- { method: "isDirectory", class: "Files", type: "path_traversal", cwe: "CWE-22", severity: "medium", arg_positions: [0] },
10632
- { method: "isRegularFile", class: "Files", type: "path_traversal", cwe: "CWE-22", severity: "medium", arg_positions: [0] },
10633
10626
  { method: "RandomAccessFile", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10634
10627
  { method: "resolveURI", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
10635
10628
  { method: "resolve", class: "SourceResolver", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
@@ -10968,6 +10961,9 @@ var DEFAULT_SINKS = [
10968
10961
  { method: "parseObject", class: "JSON", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0], safe_if_class_literal_at: 1 },
10969
10962
  { method: "parseObject", class: "JSONObject", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0], safe_if_class_literal_at: 1 },
10970
10963
  { method: "fromJson", class: "Gson", type: "deserialization", cwe: "CWE-502", severity: "medium", arg_positions: [0], safe_if_class_literal_at: 1 },
10964
+ { method: "readValue", class: "ObjectReader", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0], safe_if_class_literal_at: 1 },
10965
+ { method: "convertValue", class: "ObjectMapper", type: "deserialization", cwe: "CWE-502", severity: "medium", arg_positions: [0], safe_if_class_literal_at: 1 },
10966
+ { method: "readObject", class: "Kryo", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0], safe_if_class_literal_at: 1 },
10971
10967
  { method: "readObject", class: "XMLDecoder", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [] },
10972
10968
  { method: "ObjectInputStream", class: "constructor", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
10973
10969
  { method: "search", class: "DirContext", type: "ldap_injection", cwe: "CWE-90", severity: "high", arg_positions: [0, 1] },
@@ -12455,7 +12451,21 @@ function argIsClassLiteral(call, position) {
12455
12451
  const expr = (arg.literal ?? arg.expression ?? "").trim();
12456
12452
  if (!expr)
12457
12453
  return false;
12458
- return CLASS_LITERAL_RE.test(expr);
12454
+ if (CLASS_LITERAL_RE.test(expr))
12455
+ return true;
12456
+ return TYPE_TOKEN_RE.test(expr);
12457
+ }
12458
+ var TYPE_TOKEN_RE = /^new\s+(?:TypeReference|TypeToken)\s*<[\s\S]*>\s*\(\s*\)\s*\{\s*\}$/;
12459
+ function argIsStringLiteral(call, position) {
12460
+ const arg = call.arguments.find((a) => a.position === position);
12461
+ if (!arg)
12462
+ return false;
12463
+ if (arg.literal !== undefined && arg.literal !== null && arg.literal !== "")
12464
+ return true;
12465
+ const expr = (arg.expression ?? "").trim();
12466
+ if (!expr)
12467
+ return false;
12468
+ return expr.startsWith('"') && expr.endsWith('"') && expr.length >= 2 || expr.startsWith("'") && expr.endsWith("'") && expr.length >= 2 || expr.startsWith('"""') && expr.endsWith('"""');
12459
12469
  }
12460
12470
  var CWE_78_RECEIVER_ALLOWLIST = new Set([
12461
12471
  "Runtime",
@@ -12649,6 +12659,9 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines) {
12649
12659
  if (pattern.safe_if_class_literal_at !== undefined && argIsClassLiteral(call, pattern.safe_if_class_literal_at)) {
12650
12660
  continue;
12651
12661
  }
12662
+ if (pattern.safe_if_string_literal_at !== undefined && argIsStringLiteral(call, pattern.safe_if_string_literal_at)) {
12663
+ continue;
12664
+ }
12652
12665
  if (pattern.type === "command_injection") {
12653
12666
  if (call.is_constructor) {
12654
12667
  if (!CWE_78_RECEIVER_ALLOWLIST.has(call.method_name)) {
@@ -18460,6 +18473,470 @@ function applyLibraryApiSurfaceDowngrade(findings) {
18460
18473
  });
18461
18474
  }
18462
18475
 
18476
+ // ../circle-ir/dist/analysis/entry-point-detection.js
18477
+ var TIER_1_METHOD_ANNOTATIONS = new Set([
18478
+ "RequestMapping",
18479
+ "GetMapping",
18480
+ "PostMapping",
18481
+ "PutMapping",
18482
+ "DeleteMapping",
18483
+ "PatchMapping",
18484
+ "MessageMapping",
18485
+ "SubscribeMapping",
18486
+ "KafkaListener",
18487
+ "KafkaHandler",
18488
+ "RabbitListener",
18489
+ "RabbitHandler",
18490
+ "JmsListener",
18491
+ "StreamListener",
18492
+ "SqsListener",
18493
+ "SqsHandler",
18494
+ "EventListener",
18495
+ "Scheduled",
18496
+ "Path",
18497
+ "GET",
18498
+ "POST",
18499
+ "PUT",
18500
+ "DELETE",
18501
+ "PATCH",
18502
+ "HEAD",
18503
+ "OPTIONS",
18504
+ "DataBoundConstructor",
18505
+ "DataBoundSetter"
18506
+ ]);
18507
+ var TIER_1_CLASS_ANNOTATIONS = new Set([
18508
+ "RestController",
18509
+ "Controller",
18510
+ "Service",
18511
+ "Repository",
18512
+ "Component",
18513
+ "Path",
18514
+ "WebServlet",
18515
+ "ServerEndpoint",
18516
+ "FeignClient"
18517
+ ]);
18518
+ var TIER_1_BY_SUPERTYPE = new Map([
18519
+ ["HttpServlet", new Set(["doGet", "doPost", "doPut", "doDelete", "doHead", "doOptions", "doTrace", "service"])],
18520
+ ["GenericServlet", new Set(["service"])],
18521
+ ["Filter", new Set(["doFilter"])],
18522
+ ["HandlerInterceptor", new Set(["preHandle", "postHandle", "afterCompletion"])],
18523
+ ["AsyncHandlerInterceptor", new Set(["preHandle", "postHandle", "afterCompletion", "afterConcurrentHandlingStarted"])],
18524
+ ["CommandLineRunner", new Set(["run"])],
18525
+ ["ApplicationRunner", new Set(["run"])],
18526
+ ["SimpleChannelInboundHandler", new Set(["channelRead0", "messageReceived"])],
18527
+ ["ChannelInboundHandler", new Set(["channelRead", "channelReadComplete"])],
18528
+ ["ChannelInboundHandlerAdapter", new Set(["channelRead", "channelReadComplete"])],
18529
+ ["ChannelDuplexHandler", new Set(["channelRead", "channelReadComplete"])],
18530
+ ["NettyRequestProcessor", new Set(["process"])],
18531
+ ["Converter", new Set(["marshal", "unmarshal"])],
18532
+ ["SingleValueConverter", new Set(["fromString", "toString"])],
18533
+ ["ConverterMatcher", new Set(["marshal", "unmarshal"])],
18534
+ ["AbstractReflectionConverter", new Set(["marshal", "unmarshal", "doMarshal", "doUnmarshal"])],
18535
+ ["AbstractSingleValueConverter", new Set(["fromString", "toString"])],
18536
+ ["AbstractCollectionConverter", new Set(["marshal", "unmarshal"])]
18537
+ ]);
18538
+ var TIER_3_CLASS_SUFFIXES = [
18539
+ "Util",
18540
+ "Utils",
18541
+ "Helper",
18542
+ "Helpers"
18543
+ ];
18544
+ var TIER_3_PACKAGE_FRAGMENTS = [
18545
+ ".template.",
18546
+ ".templates.",
18547
+ ".engine.",
18548
+ ".engines."
18549
+ ];
18550
+ var TIER_3_JDK_FACADE_INTERFACES = new Set([
18551
+ "Collection",
18552
+ "List",
18553
+ "Set",
18554
+ "Map",
18555
+ "Queue",
18556
+ "Deque",
18557
+ "SortedSet",
18558
+ "SortedMap",
18559
+ "NavigableSet",
18560
+ "NavigableMap",
18561
+ "Iterator",
18562
+ "Iterable",
18563
+ "ListIterator",
18564
+ "Comparator",
18565
+ "Comparable",
18566
+ "Serializable",
18567
+ "Externalizable",
18568
+ "Cloneable"
18569
+ ]);
18570
+ function classNameLooksLikeUtility(name2) {
18571
+ if (!name2)
18572
+ return false;
18573
+ for (const suffix of TIER_3_CLASS_SUFFIXES) {
18574
+ if (name2.length > suffix.length && name2.endsWith(suffix))
18575
+ return true;
18576
+ }
18577
+ return false;
18578
+ }
18579
+ function packageLooksLikeTemplateOrEngine(pkg) {
18580
+ if (!pkg)
18581
+ return false;
18582
+ const padded = `.${pkg}.`;
18583
+ for (const frag of TIER_3_PACKAGE_FRAGMENTS) {
18584
+ if (padded.includes(frag))
18585
+ return true;
18586
+ }
18587
+ return false;
18588
+ }
18589
+ function implementsJdkFacade(t) {
18590
+ if (!t)
18591
+ return false;
18592
+ for (const impl of t.implements ?? []) {
18593
+ if (TIER_3_JDK_FACADE_INTERFACES.has(simpleTypeName(impl)))
18594
+ return true;
18595
+ }
18596
+ return false;
18597
+ }
18598
+ function classShapeIsLibraryFacade(enclosingType) {
18599
+ if (!enclosingType)
18600
+ return false;
18601
+ if (classNameLooksLikeUtility(enclosingType.name))
18602
+ return true;
18603
+ if (packageLooksLikeTemplateOrEngine(enclosingType.package))
18604
+ return true;
18605
+ if (implementsJdkFacade(enclosingType))
18606
+ return true;
18607
+ return false;
18608
+ }
18609
+ function annotationsInclude(annotations, targets) {
18610
+ if (!annotations || annotations.length === 0)
18611
+ return false;
18612
+ for (const raw of annotations) {
18613
+ const simple = raw.replace(/^@/, "").replace(/[<(].*$/, "").trim();
18614
+ if (targets.has(simple))
18615
+ return true;
18616
+ }
18617
+ return false;
18618
+ }
18619
+ function simpleTypeName(ref) {
18620
+ return ref.replace(/<.*$/, "").trim();
18621
+ }
18622
+ function looksLikeMainMethod(method) {
18623
+ if (method.name !== "main")
18624
+ return false;
18625
+ const params = method.parameters ?? [];
18626
+ if (params.length !== 1)
18627
+ return false;
18628
+ const t = (params[0].type ?? "").replace(/\s+/g, "");
18629
+ return t === "String[]" || t === "String..." || t === "java.lang.String[]";
18630
+ }
18631
+ function methodIsSupertypeLifecycleEntryPoint(method, enclosingType) {
18632
+ if (!method.name)
18633
+ return false;
18634
+ if (!enclosingType)
18635
+ return false;
18636
+ const candidates = [];
18637
+ if (enclosingType.extends)
18638
+ candidates.push(simpleTypeName(enclosingType.extends));
18639
+ for (const i2 of enclosingType.implements ?? [])
18640
+ candidates.push(simpleTypeName(i2));
18641
+ for (const supertype of candidates) {
18642
+ const lifecycleMethods = TIER_1_BY_SUPERTYPE.get(supertype);
18643
+ if (lifecycleMethods?.has(method.name))
18644
+ return true;
18645
+ }
18646
+ return false;
18647
+ }
18648
+ function classifyEntryPointTier(method, enclosingType, ctx) {
18649
+ const language = (ctx.language ?? "").toLowerCase();
18650
+ if (language !== "java")
18651
+ return "TIER_UNKNOWN";
18652
+ if (!method)
18653
+ return "TIER_UNKNOWN";
18654
+ if (classShapeIsLibraryFacade(enclosingType)) {
18655
+ return "TIER_3_LIBRARY_API";
18656
+ }
18657
+ if (annotationsInclude(method.annotations, TIER_1_METHOD_ANNOTATIONS)) {
18658
+ return "TIER_1_ENTRY_POINT";
18659
+ }
18660
+ if (enclosingType && annotationsInclude(enclosingType.annotations, TIER_1_CLASS_ANNOTATIONS)) {
18661
+ return "TIER_1_ENTRY_POINT";
18662
+ }
18663
+ if (methodIsSupertypeLifecycleEntryPoint(method, enclosingType)) {
18664
+ return "TIER_1_ENTRY_POINT";
18665
+ }
18666
+ if (looksLikeMainMethod(method)) {
18667
+ return "TIER_1_ENTRY_POINT";
18668
+ }
18669
+ return "TIER_3_LIBRARY_API";
18670
+ }
18671
+ function shouldGateInterproceduralParam(sourceType, enclosingMethod, enclosingType, ctx) {
18672
+ if (sourceType !== "interprocedural_param")
18673
+ return false;
18674
+ if (!enclosingMethod)
18675
+ return false;
18676
+ const tier = classifyEntryPointTier(enclosingMethod, enclosingType, ctx);
18677
+ return tier === "TIER_3_LIBRARY_API";
18678
+ }
18679
+
18680
+ // ../circle-ir/dist/analysis/require-entry-path.js
18681
+ var RULE_ID_REQUIRE_ENTRY_PATH = "require-entry-path";
18682
+ var MAX_VISITED_METHODS = 2000;
18683
+ function applyRequireEntryPath(fileAnalyses, options = {}) {
18684
+ const disabledSet = normalizeDisabled(options.disabledPasses);
18685
+ if (disabledSet.has(RULE_ID_REQUIRE_ENTRY_PATH))
18686
+ return;
18687
+ const graph = buildProjectMethodGraph(fileAnalyses);
18688
+ if (graph.methodsByKey.size === 0)
18689
+ return;
18690
+ const entryPointKeys = collectEntryPointKeys(graph);
18691
+ const profileResolver = makeProfileResolver(options.projectProfile);
18692
+ for (const fa of fileAnalyses) {
18693
+ const findings = fa.analysis.findings;
18694
+ if (!findings || findings.length === 0)
18695
+ continue;
18696
+ const kept = [];
18697
+ for (const finding of findings) {
18698
+ const decision = classifyFinding(finding, fa.analysis, graph, entryPointKeys, profileResolver(fa.file));
18699
+ switch (decision.action) {
18700
+ case "keep":
18701
+ kept.push(finding);
18702
+ break;
18703
+ case "annotate":
18704
+ kept.push({
18705
+ ...finding,
18706
+ entryPath: decision.entryPath,
18707
+ entryPathTier: decision.tier
18708
+ });
18709
+ break;
18710
+ case "drop":
18711
+ break;
18712
+ }
18713
+ }
18714
+ fa.analysis.findings = kept.length > 0 ? kept : undefined;
18715
+ }
18716
+ }
18717
+ function buildProjectMethodGraph(fileAnalyses) {
18718
+ const methodsByKey = new Map;
18719
+ const methodsByName = new Map;
18720
+ const callersOf = new Map;
18721
+ for (const fa of fileAnalyses) {
18722
+ const language = (fa.analysis.meta.language ?? "").toLowerCase();
18723
+ for (const type of fa.analysis.types ?? []) {
18724
+ for (const method of type.methods ?? []) {
18725
+ const key = makeMethodKey(fa.file, type.name, method.name, method.start_line);
18726
+ methodsByKey.set(key, {
18727
+ key,
18728
+ file: fa.file,
18729
+ className: type.name,
18730
+ method,
18731
+ enclosingType: type,
18732
+ language
18733
+ });
18734
+ const bucket = methodsByName.get(method.name);
18735
+ if (bucket)
18736
+ bucket.push(key);
18737
+ else
18738
+ methodsByName.set(method.name, [key]);
18739
+ }
18740
+ }
18741
+ }
18742
+ for (const fa of fileAnalyses) {
18743
+ const calls = fa.analysis.calls ?? [];
18744
+ for (const call of calls) {
18745
+ if (!call.in_method)
18746
+ continue;
18747
+ const callerKey = resolveCallerKey(fa, call.in_method, call.location.line);
18748
+ if (!callerKey)
18749
+ continue;
18750
+ const calleeKeys = resolveCalleeKeys(call, methodsByKey, methodsByName);
18751
+ if (calleeKeys.length === 0)
18752
+ continue;
18753
+ const code = call.receiver ? `${call.receiver}.${call.method_name}(...)` : `${call.method_name}(...)`;
18754
+ for (const calleeKey of calleeKeys) {
18755
+ const edge = {
18756
+ callerKey,
18757
+ calleeKey,
18758
+ callSiteLine: call.location.line,
18759
+ code
18760
+ };
18761
+ const bucket = callersOf.get(calleeKey);
18762
+ if (bucket)
18763
+ bucket.push(edge);
18764
+ else
18765
+ callersOf.set(calleeKey, [edge]);
18766
+ }
18767
+ }
18768
+ }
18769
+ return { methodsByKey, methodsByName, callersOf };
18770
+ }
18771
+ function makeMethodKey(file, className, methodName, startLine) {
18772
+ return `${file}|${className}#${methodName}@${startLine}`;
18773
+ }
18774
+ function resolveCallerKey(fa, inMethod, callLine) {
18775
+ for (const type of fa.analysis.types ?? []) {
18776
+ for (const method of type.methods ?? []) {
18777
+ if (method.name !== inMethod)
18778
+ continue;
18779
+ if (callLine >= method.start_line && callLine <= method.end_line) {
18780
+ return makeMethodKey(fa.file, type.name, method.name, method.start_line);
18781
+ }
18782
+ }
18783
+ }
18784
+ return null;
18785
+ }
18786
+ function resolveCalleeKeys(call, methodsByKey, methodsByName) {
18787
+ const candidates = methodsByName.get(call.method_name);
18788
+ if (!candidates || candidates.length === 0)
18789
+ return [];
18790
+ if (call.receiver_type) {
18791
+ const simple = call.receiver_type.replace(/<.*$/, "").trim();
18792
+ const matches = [];
18793
+ for (const key of candidates) {
18794
+ const rec = methodsByKey.get(key);
18795
+ if (rec?.className === simple)
18796
+ matches.push(key);
18797
+ }
18798
+ if (matches.length > 0)
18799
+ return matches;
18800
+ }
18801
+ return candidates;
18802
+ }
18803
+ function collectEntryPointKeys(graph) {
18804
+ const entryPoints = new Set;
18805
+ for (const rec of graph.methodsByKey.values()) {
18806
+ const tier = classifyEntryPointTier(rec.method, rec.enclosingType, {
18807
+ types: [rec.enclosingType],
18808
+ language: rec.language
18809
+ });
18810
+ if (tier === "TIER_1_ENTRY_POINT")
18811
+ entryPoints.add(rec.key);
18812
+ }
18813
+ return entryPoints;
18814
+ }
18815
+ function classifyFinding(finding, ir, graph, entryPointKeys, profile) {
18816
+ if (finding.category !== "security")
18817
+ return { action: "keep" };
18818
+ const isHighOrCritical = finding.severity === "high" || finding.severity === "critical";
18819
+ const language = (ir.meta.language ?? "").toLowerCase();
18820
+ if (language !== "java")
18821
+ return { action: "keep" };
18822
+ const containing = findContainingMethod(finding, ir, graph);
18823
+ if (!containing) {
18824
+ return { action: "keep" };
18825
+ }
18826
+ const bfs = reverseBfsToEntryPoint(containing.key, graph, entryPointKeys);
18827
+ if (bfs.status === "hit") {
18828
+ const entryPath = reconstructPath(bfs.entryKey, containing.key, bfs.parent, graph, finding);
18829
+ return {
18830
+ action: "annotate",
18831
+ entryPath,
18832
+ tier: "tier1-entry-point"
18833
+ };
18834
+ }
18835
+ if (bfs.status === "budget") {
18836
+ return { action: "keep" };
18837
+ }
18838
+ if (!isHighOrCritical)
18839
+ return { action: "keep" };
18840
+ if (!shouldDropUnderProfile(profile))
18841
+ return { action: "keep" };
18842
+ return { action: "drop" };
18843
+ }
18844
+ function findContainingMethod(finding, ir, graph) {
18845
+ const line = finding.line;
18846
+ for (const type of ir.types ?? []) {
18847
+ for (const method of type.methods ?? []) {
18848
+ if (line >= method.start_line && line <= method.end_line) {
18849
+ const key = makeMethodKey(finding.file, type.name, method.name, method.start_line);
18850
+ const rec = graph.methodsByKey.get(key);
18851
+ if (rec)
18852
+ return rec;
18853
+ }
18854
+ }
18855
+ }
18856
+ return null;
18857
+ }
18858
+ function reverseBfsToEntryPoint(startKey, graph, entryPointKeys) {
18859
+ const parent = new Map;
18860
+ const visited = new Set([startKey]);
18861
+ const queue = [startKey];
18862
+ if (entryPointKeys.has(startKey)) {
18863
+ return { status: "hit", entryKey: startKey, parent };
18864
+ }
18865
+ while (queue.length > 0) {
18866
+ if (visited.size > MAX_VISITED_METHODS) {
18867
+ return { status: "budget", entryKey: null, parent };
18868
+ }
18869
+ const current = queue.shift();
18870
+ const incoming = graph.callersOf.get(current) ?? [];
18871
+ incoming.sort((a, b) => a.callerKey.localeCompare(b.callerKey));
18872
+ for (const edge of incoming) {
18873
+ if (visited.has(edge.callerKey))
18874
+ continue;
18875
+ visited.add(edge.callerKey);
18876
+ parent.set(edge.callerKey, edge);
18877
+ if (entryPointKeys.has(edge.callerKey)) {
18878
+ return { status: "hit", entryKey: edge.callerKey, parent };
18879
+ }
18880
+ queue.push(edge.callerKey);
18881
+ }
18882
+ }
18883
+ return { status: "miss", entryKey: null, parent };
18884
+ }
18885
+ function reconstructPath(entryKey, sinkKey, parent, graph, finding) {
18886
+ const hops = [];
18887
+ let cursor = entryKey;
18888
+ const guard = new Set;
18889
+ while (cursor !== sinkKey) {
18890
+ if (guard.has(cursor))
18891
+ break;
18892
+ guard.add(cursor);
18893
+ const rec = graph.methodsByKey.get(cursor);
18894
+ const edge = parent.get(cursor);
18895
+ if (!rec || !edge)
18896
+ break;
18897
+ hops.push({
18898
+ file: rec.file,
18899
+ method: `${rec.className}.${rec.method.name}`,
18900
+ line: edge.callSiteLine,
18901
+ code: edge.code,
18902
+ variable: ""
18903
+ });
18904
+ cursor = edge.calleeKey;
18905
+ }
18906
+ const sinkRec = graph.methodsByKey.get(sinkKey);
18907
+ if (sinkRec) {
18908
+ hops.push({
18909
+ file: sinkRec.file,
18910
+ method: `${sinkRec.className}.${sinkRec.method.name}`,
18911
+ line: finding.line,
18912
+ code: finding.message,
18913
+ variable: ""
18914
+ });
18915
+ }
18916
+ return hops;
18917
+ }
18918
+ function shouldDropUnderProfile(profile) {
18919
+ if (profile === "unknown")
18920
+ return true;
18921
+ if (profile.startsWith("library/"))
18922
+ return false;
18923
+ return true;
18924
+ }
18925
+ function makeProfileResolver(input) {
18926
+ if (input === undefined)
18927
+ return () => "unknown";
18928
+ if (typeof input === "string")
18929
+ return () => input;
18930
+ return (file) => input.get(file) ?? "unknown";
18931
+ }
18932
+ function normalizeDisabled(input) {
18933
+ if (!input)
18934
+ return new Set;
18935
+ if (input instanceof Set)
18936
+ return input;
18937
+ return new Set(input);
18938
+ }
18939
+
18463
18940
  // ../circle-ir/dist/analysis/project-profile-transform.js
18464
18941
  var DOWNGRADE_ELIGIBLE_RULE_IDS = new Set([
18465
18942
  "code_injection",
@@ -30433,7 +30910,7 @@ var REFLECTION_SINK_METHODS = new Set([
30433
30910
  "loadClass",
30434
30911
  "defineClass"
30435
30912
  ]);
30436
- var TIER_1_CLASS_ANNOTATIONS = new Set([
30913
+ var TIER_1_CLASS_ANNOTATIONS2 = new Set([
30437
30914
  "RestController",
30438
30915
  "Controller",
30439
30916
  "Service",
@@ -30444,7 +30921,7 @@ var TIER_1_CLASS_ANNOTATIONS = new Set([
30444
30921
  "ServerEndpoint",
30445
30922
  "FeignClient"
30446
30923
  ]);
30447
- var TIER_1_METHOD_ANNOTATIONS = new Set([
30924
+ var TIER_1_METHOD_ANNOTATIONS2 = new Set([
30448
30925
  "RequestMapping",
30449
30926
  "GetMapping",
30450
30927
  "PostMapping",
@@ -30547,7 +31024,7 @@ class CliMainReflectionSuppressPass {
30547
31024
  let hasFrameworkSignal = false;
30548
31025
  for (const type of types) {
30549
31026
  for (const ann of type.annotations) {
30550
- if (TIER_1_CLASS_ANNOTATIONS.has(normalizeAnnotation(ann))) {
31027
+ if (TIER_1_CLASS_ANNOTATIONS2.has(normalizeAnnotation(ann))) {
30551
31028
  hasFrameworkSignal = true;
30552
31029
  break;
30553
31030
  }
@@ -30568,7 +31045,7 @@ class CliMainReflectionSuppressPass {
30568
31045
  break;
30569
31046
  for (const method of type.methods) {
30570
31047
  for (const ann of method.annotations) {
30571
- if (TIER_1_METHOD_ANNOTATIONS.has(normalizeAnnotation(ann))) {
31048
+ if (TIER_1_METHOD_ANNOTATIONS2.has(normalizeAnnotation(ann))) {
30572
31049
  hasFrameworkSignal = true;
30573
31050
  break;
30574
31051
  }
@@ -30585,52 +31062,183 @@ class CliMainReflectionSuppressPass {
30585
31062
  if (hasFrameworkSignal)
30586
31063
  break;
30587
31064
  }
30588
- const cliMainSignal = hasMain && !hasFrameworkSignal;
30589
- if (!cliMainSignal) {
30590
- return { cliMainSignal: false, droppedCount: 0 };
31065
+ const cliMainSignal = hasMain && !hasFrameworkSignal;
31066
+ if (!cliMainSignal) {
31067
+ return { cliMainSignal: false, droppedCount: 0 };
31068
+ }
31069
+ const sinks = ctx.hasResult("sink-filter") ? ctx.getResult("sink-filter").sinks : graph.ir.taint.sinks;
31070
+ let droppedCount = 0;
31071
+ const kept = sinks.filter((sink) => {
31072
+ if (sink.type !== "code_injection")
31073
+ return true;
31074
+ if (!sink.method)
31075
+ return true;
31076
+ if (!REFLECTION_SINK_METHODS.has(sink.method))
31077
+ return true;
31078
+ droppedCount++;
31079
+ return false;
31080
+ });
31081
+ if (droppedCount > 0) {
31082
+ sinks.length = 0;
31083
+ sinks.push(...kept);
31084
+ }
31085
+ return { cliMainSignal: true, droppedCount };
31086
+ }
31087
+ }
31088
+
31089
+ // ../circle-ir/dist/analysis/passes/library-profile-sink-gate-pass.js
31090
+ var DROPPED_SINK_TYPES = new Set([
31091
+ "log_injection"
31092
+ ]);
31093
+ function isLibraryShape2(profile) {
31094
+ if (!profile || profile === "unknown")
31095
+ return false;
31096
+ return profile.startsWith("library/");
31097
+ }
31098
+
31099
+ class LibraryProfileSinkGatePass {
31100
+ name = "library-profile-sink-gate";
31101
+ category = "security";
31102
+ run(ctx) {
31103
+ const { graph } = ctx;
31104
+ const profile = graph.ir.meta.projectProfile;
31105
+ if (!isLibraryShape2(profile)) {
31106
+ return {
31107
+ profile,
31108
+ applied: false,
31109
+ dropped: 0,
31110
+ droppedByType: {}
31111
+ };
31112
+ }
31113
+ const sinks = ctx.hasResult("sink-filter") ? ctx.getResult("sink-filter").sinks : graph.ir.taint.sinks;
31114
+ if (sinks.length === 0) {
31115
+ return {
31116
+ profile,
31117
+ applied: true,
31118
+ dropped: 0,
31119
+ droppedByType: {}
31120
+ };
31121
+ }
31122
+ const droppedByType = {};
31123
+ const kept = [];
31124
+ for (const sink of sinks) {
31125
+ if (DROPPED_SINK_TYPES.has(sink.type)) {
31126
+ droppedByType[sink.type] = (droppedByType[sink.type] ?? 0) + 1;
31127
+ continue;
31128
+ }
31129
+ kept.push(sink);
31130
+ }
31131
+ const dropped = sinks.length - kept.length;
31132
+ if (dropped > 0) {
31133
+ sinks.length = 0;
31134
+ sinks.push(...kept);
31135
+ }
31136
+ return {
31137
+ profile,
31138
+ applied: true,
31139
+ dropped,
31140
+ droppedByType
31141
+ };
31142
+ }
31143
+ }
31144
+ var CWE22_SPECULATIVE_SOURCE_TYPES = new Set([
31145
+ "interprocedural_param",
31146
+ "constructor_field"
31147
+ ]);
31148
+
31149
+ class LibraryProfileCwe22PathGatePass {
31150
+ name = "library-profile-cwe22-path-gate";
31151
+ category = "security";
31152
+ run(ctx) {
31153
+ const { graph } = ctx;
31154
+ const profile = graph.ir.meta.projectProfile;
31155
+ if (!isLibraryShape2(profile)) {
31156
+ return {
31157
+ profile,
31158
+ applied: false,
31159
+ dropped: 0,
31160
+ droppedBySourceType: {}
31161
+ };
31162
+ }
31163
+ const flows = graph.ir.taint.flows;
31164
+ if (!flows || flows.length === 0) {
31165
+ return {
31166
+ profile,
31167
+ applied: true,
31168
+ dropped: 0,
31169
+ droppedBySourceType: {}
31170
+ };
31171
+ }
31172
+ const droppedBySourceType = {};
31173
+ const kept = [];
31174
+ for (const flow of flows) {
31175
+ if (flow.sink_type === "path_traversal" && CWE22_SPECULATIVE_SOURCE_TYPES.has(flow.source_type)) {
31176
+ droppedBySourceType[flow.source_type] = (droppedBySourceType[flow.source_type] ?? 0) + 1;
31177
+ continue;
31178
+ }
31179
+ kept.push(flow);
30591
31180
  }
30592
- const sinks = ctx.hasResult("sink-filter") ? ctx.getResult("sink-filter").sinks : graph.ir.taint.sinks;
30593
- let droppedCount = 0;
30594
- const kept = sinks.filter((sink) => {
30595
- if (sink.type !== "code_injection")
30596
- return true;
30597
- if (!sink.method)
30598
- return true;
30599
- if (!REFLECTION_SINK_METHODS.has(sink.method))
30600
- return true;
30601
- droppedCount++;
30602
- return false;
30603
- });
30604
- if (droppedCount > 0) {
30605
- sinks.length = 0;
30606
- sinks.push(...kept);
31181
+ const dropped = flows.length - kept.length;
31182
+ if (dropped > 0) {
31183
+ flows.length = 0;
31184
+ flows.push(...kept);
30607
31185
  }
30608
- return { cliMainSignal: true, droppedCount };
31186
+ return {
31187
+ profile,
31188
+ applied: true,
31189
+ dropped,
31190
+ droppedBySourceType
31191
+ };
30609
31192
  }
30610
31193
  }
30611
31194
 
30612
- // ../circle-ir/dist/analysis/passes/library-profile-sink-gate-pass.js
30613
- var DROPPED_SINK_TYPES = new Set([
30614
- "log_injection"
31195
+ // ../circle-ir/dist/analysis/passes/library-profile-xss-gate-pass.js
31196
+ var XSS_NON_HTML_OUTPUT_CLASSES = new Set([
31197
+ "StringBuilder",
31198
+ "StringBuffer",
31199
+ "CharArrayWriter",
31200
+ "ByteArrayOutputStream",
31201
+ "PrintStream",
31202
+ "System",
31203
+ "HttpRequest",
31204
+ "HttpRequestBuilder",
31205
+ "HttpResponse",
31206
+ "HttpSession",
31207
+ "ServletRequest",
31208
+ "HttpServletRequest",
31209
+ "RedisOutputStream",
31210
+ "SafeEncoder",
31211
+ "RESP2",
31212
+ "Protocol",
31213
+ "JSONUtil",
31214
+ "JSON",
31215
+ "ObjectMapper",
31216
+ "JsonReader",
31217
+ "Logger",
31218
+ "LoggerFactory",
31219
+ "Log",
31220
+ "Slf4jLogger",
31221
+ "RequestContext",
31222
+ "Context"
30615
31223
  ]);
30616
- function isLibraryShape2(profile) {
31224
+ function isLibraryShape3(profile) {
30617
31225
  if (!profile || profile === "unknown")
30618
31226
  return false;
30619
31227
  return profile.startsWith("library/");
30620
31228
  }
30621
31229
 
30622
- class LibraryProfileSinkGatePass {
30623
- name = "library-profile-sink-gate";
31230
+ class LibraryProfileXssGatePass {
31231
+ name = "library-profile-xss-gate";
30624
31232
  category = "security";
30625
31233
  run(ctx) {
30626
31234
  const { graph } = ctx;
30627
31235
  const profile = graph.ir.meta.projectProfile;
30628
- if (!isLibraryShape2(profile)) {
31236
+ if (!isLibraryShape3(profile)) {
30629
31237
  return {
30630
31238
  profile,
30631
31239
  applied: false,
30632
31240
  dropped: 0,
30633
- droppedByType: {}
31241
+ droppedByClass: {}
30634
31242
  };
30635
31243
  }
30636
31244
  const sinks = ctx.hasResult("sink-filter") ? ctx.getResult("sink-filter").sinks : graph.ir.taint.sinks;
@@ -30639,14 +31247,14 @@ class LibraryProfileSinkGatePass {
30639
31247
  profile,
30640
31248
  applied: true,
30641
31249
  dropped: 0,
30642
- droppedByType: {}
31250
+ droppedByClass: {}
30643
31251
  };
30644
31252
  }
30645
- const droppedByType = {};
31253
+ const droppedByClass = {};
30646
31254
  const kept = [];
30647
31255
  for (const sink of sinks) {
30648
- if (DROPPED_SINK_TYPES.has(sink.type)) {
30649
- droppedByType[sink.type] = (droppedByType[sink.type] ?? 0) + 1;
31256
+ if (sink.type === "xss" && sink.class && XSS_NON_HTML_OUTPUT_CLASSES.has(sink.class)) {
31257
+ droppedByClass[sink.class] = (droppedByClass[sink.class] ?? 0) + 1;
30650
31258
  continue;
30651
31259
  }
30652
31260
  kept.push(sink);
@@ -30660,7 +31268,7 @@ class LibraryProfileSinkGatePass {
30660
31268
  profile,
30661
31269
  applied: true,
30662
31270
  dropped,
30663
- droppedByType
31271
+ droppedByClass
30664
31272
  };
30665
31273
  }
30666
31274
  }
@@ -32031,210 +32639,6 @@ function findTaintBridges2(result) {
32031
32639
  return bridges;
32032
32640
  }
32033
32641
 
32034
- // ../circle-ir/dist/analysis/entry-point-detection.js
32035
- var TIER_1_METHOD_ANNOTATIONS2 = new Set([
32036
- "RequestMapping",
32037
- "GetMapping",
32038
- "PostMapping",
32039
- "PutMapping",
32040
- "DeleteMapping",
32041
- "PatchMapping",
32042
- "MessageMapping",
32043
- "SubscribeMapping",
32044
- "KafkaListener",
32045
- "KafkaHandler",
32046
- "RabbitListener",
32047
- "RabbitHandler",
32048
- "JmsListener",
32049
- "StreamListener",
32050
- "SqsListener",
32051
- "SqsHandler",
32052
- "EventListener",
32053
- "Scheduled",
32054
- "Path",
32055
- "GET",
32056
- "POST",
32057
- "PUT",
32058
- "DELETE",
32059
- "PATCH",
32060
- "HEAD",
32061
- "OPTIONS",
32062
- "DataBoundConstructor",
32063
- "DataBoundSetter"
32064
- ]);
32065
- var TIER_1_CLASS_ANNOTATIONS2 = new Set([
32066
- "RestController",
32067
- "Controller",
32068
- "Service",
32069
- "Repository",
32070
- "Component",
32071
- "Path",
32072
- "WebServlet",
32073
- "ServerEndpoint",
32074
- "FeignClient"
32075
- ]);
32076
- var TIER_1_BY_SUPERTYPE = new Map([
32077
- ["HttpServlet", new Set(["doGet", "doPost", "doPut", "doDelete", "doHead", "doOptions", "doTrace", "service"])],
32078
- ["GenericServlet", new Set(["service"])],
32079
- ["Filter", new Set(["doFilter"])],
32080
- ["HandlerInterceptor", new Set(["preHandle", "postHandle", "afterCompletion"])],
32081
- ["AsyncHandlerInterceptor", new Set(["preHandle", "postHandle", "afterCompletion", "afterConcurrentHandlingStarted"])],
32082
- ["CommandLineRunner", new Set(["run"])],
32083
- ["ApplicationRunner", new Set(["run"])],
32084
- ["SimpleChannelInboundHandler", new Set(["channelRead0", "messageReceived"])],
32085
- ["ChannelInboundHandler", new Set(["channelRead", "channelReadComplete"])],
32086
- ["ChannelInboundHandlerAdapter", new Set(["channelRead", "channelReadComplete"])],
32087
- ["ChannelDuplexHandler", new Set(["channelRead", "channelReadComplete"])],
32088
- ["NettyRequestProcessor", new Set(["process"])],
32089
- ["Converter", new Set(["marshal", "unmarshal"])],
32090
- ["SingleValueConverter", new Set(["fromString", "toString"])],
32091
- ["ConverterMatcher", new Set(["marshal", "unmarshal"])],
32092
- ["AbstractReflectionConverter", new Set(["marshal", "unmarshal", "doMarshal", "doUnmarshal"])],
32093
- ["AbstractSingleValueConverter", new Set(["fromString", "toString"])],
32094
- ["AbstractCollectionConverter", new Set(["marshal", "unmarshal"])]
32095
- ]);
32096
- var TIER_3_CLASS_SUFFIXES = [
32097
- "Util",
32098
- "Utils",
32099
- "Helper",
32100
- "Helpers"
32101
- ];
32102
- var TIER_3_PACKAGE_FRAGMENTS = [
32103
- ".template.",
32104
- ".templates.",
32105
- ".engine.",
32106
- ".engines."
32107
- ];
32108
- var TIER_3_JDK_FACADE_INTERFACES = new Set([
32109
- "Collection",
32110
- "List",
32111
- "Set",
32112
- "Map",
32113
- "Queue",
32114
- "Deque",
32115
- "SortedSet",
32116
- "SortedMap",
32117
- "NavigableSet",
32118
- "NavigableMap",
32119
- "Iterator",
32120
- "Iterable",
32121
- "ListIterator",
32122
- "Comparator",
32123
- "Comparable",
32124
- "Serializable",
32125
- "Externalizable",
32126
- "Cloneable"
32127
- ]);
32128
- function classNameLooksLikeUtility(name2) {
32129
- if (!name2)
32130
- return false;
32131
- for (const suffix of TIER_3_CLASS_SUFFIXES) {
32132
- if (name2.length > suffix.length && name2.endsWith(suffix))
32133
- return true;
32134
- }
32135
- return false;
32136
- }
32137
- function packageLooksLikeTemplateOrEngine(pkg) {
32138
- if (!pkg)
32139
- return false;
32140
- const padded = `.${pkg}.`;
32141
- for (const frag of TIER_3_PACKAGE_FRAGMENTS) {
32142
- if (padded.includes(frag))
32143
- return true;
32144
- }
32145
- return false;
32146
- }
32147
- function implementsJdkFacade(t) {
32148
- if (!t)
32149
- return false;
32150
- for (const impl of t.implements ?? []) {
32151
- if (TIER_3_JDK_FACADE_INTERFACES.has(simpleTypeName(impl)))
32152
- return true;
32153
- }
32154
- return false;
32155
- }
32156
- function classShapeIsLibraryFacade(enclosingType) {
32157
- if (!enclosingType)
32158
- return false;
32159
- if (classNameLooksLikeUtility(enclosingType.name))
32160
- return true;
32161
- if (packageLooksLikeTemplateOrEngine(enclosingType.package))
32162
- return true;
32163
- if (implementsJdkFacade(enclosingType))
32164
- return true;
32165
- return false;
32166
- }
32167
- function annotationsInclude(annotations, targets) {
32168
- if (!annotations || annotations.length === 0)
32169
- return false;
32170
- for (const raw of annotations) {
32171
- const simple = raw.replace(/^@/, "").replace(/[<(].*$/, "").trim();
32172
- if (targets.has(simple))
32173
- return true;
32174
- }
32175
- return false;
32176
- }
32177
- function simpleTypeName(ref) {
32178
- return ref.replace(/<.*$/, "").trim();
32179
- }
32180
- function looksLikeMainMethod(method) {
32181
- if (method.name !== "main")
32182
- return false;
32183
- const params = method.parameters ?? [];
32184
- if (params.length !== 1)
32185
- return false;
32186
- const t = (params[0].type ?? "").replace(/\s+/g, "");
32187
- return t === "String[]" || t === "String..." || t === "java.lang.String[]";
32188
- }
32189
- function methodIsSupertypeLifecycleEntryPoint(method, enclosingType) {
32190
- if (!method.name)
32191
- return false;
32192
- if (!enclosingType)
32193
- return false;
32194
- const candidates = [];
32195
- if (enclosingType.extends)
32196
- candidates.push(simpleTypeName(enclosingType.extends));
32197
- for (const i2 of enclosingType.implements ?? [])
32198
- candidates.push(simpleTypeName(i2));
32199
- for (const supertype of candidates) {
32200
- const lifecycleMethods = TIER_1_BY_SUPERTYPE.get(supertype);
32201
- if (lifecycleMethods?.has(method.name))
32202
- return true;
32203
- }
32204
- return false;
32205
- }
32206
- function classifyEntryPointTier(method, enclosingType, ctx) {
32207
- const language = (ctx.language ?? "").toLowerCase();
32208
- if (language !== "java")
32209
- return "TIER_UNKNOWN";
32210
- if (!method)
32211
- return "TIER_UNKNOWN";
32212
- if (classShapeIsLibraryFacade(enclosingType)) {
32213
- return "TIER_3_LIBRARY_API";
32214
- }
32215
- if (annotationsInclude(method.annotations, TIER_1_METHOD_ANNOTATIONS2)) {
32216
- return "TIER_1_ENTRY_POINT";
32217
- }
32218
- if (enclosingType && annotationsInclude(enclosingType.annotations, TIER_1_CLASS_ANNOTATIONS2)) {
32219
- return "TIER_1_ENTRY_POINT";
32220
- }
32221
- if (methodIsSupertypeLifecycleEntryPoint(method, enclosingType)) {
32222
- return "TIER_1_ENTRY_POINT";
32223
- }
32224
- if (looksLikeMainMethod(method)) {
32225
- return "TIER_1_ENTRY_POINT";
32226
- }
32227
- return "TIER_3_LIBRARY_API";
32228
- }
32229
- function shouldGateInterproceduralParam(sourceType, enclosingMethod, enclosingType, ctx) {
32230
- if (sourceType !== "interprocedural_param")
32231
- return false;
32232
- if (!enclosingMethod)
32233
- return false;
32234
- const tier = classifyEntryPointTier(enclosingMethod, enclosingType, ctx);
32235
- return tier === "TIER_3_LIBRARY_API";
32236
- }
32237
-
32238
32642
  // ../circle-ir/dist/analysis/passes/interprocedural-pass.js
32239
32643
  class InterproceduralPass {
32240
32644
  name = "interprocedural";
@@ -41675,7 +42079,7 @@ function getNodeTypesForLanguage(language) {
41675
42079
  ]);
41676
42080
  }
41677
42081
  }
41678
- function makeProfileResolver(p) {
42082
+ function makeProfileResolver2(p) {
41679
42083
  if (p === undefined)
41680
42084
  return () => "unknown";
41681
42085
  if (typeof p === "string")
@@ -41744,7 +42148,7 @@ async function analyze(code, filePath, language, options = {}) {
41744
42148
  const nodeCache = collectAllNodes(tree.rootNode, getNodeTypesForLanguage(language));
41745
42149
  const meta = extractMeta(code, tree, filePath, language);
41746
42150
  if (options.projectProfile !== undefined) {
41747
- meta.projectProfile = makeProfileResolver(options.projectProfile)(filePath);
42151
+ meta.projectProfile = makeProfileResolver2(options.projectProfile)(filePath);
41748
42152
  }
41749
42153
  const types = extractTypes(tree, nodeCache, language);
41750
42154
  const calls = extractCalls(tree, nodeCache, language);
@@ -41783,10 +42187,14 @@ async function analyze(code, filePath, language, options = {}) {
41783
42187
  pipeline.add(new CliMainReflectionSuppressPass);
41784
42188
  if (!disabledPasses.has("library-profile-sink-gate"))
41785
42189
  pipeline.add(new LibraryProfileSinkGatePass);
42190
+ if (!disabledPasses.has("library-profile-xss-gate"))
42191
+ pipeline.add(new LibraryProfileXssGatePass);
41786
42192
  pipeline.add(new TaintPropagationPass);
41787
42193
  pipeline.add(new InterproceduralPass({
41788
42194
  enableEntryPointGate: options.enableEntryPointGate ?? true
41789
42195
  }));
42196
+ if (!disabledPasses.has("library-profile-cwe22-path-gate"))
42197
+ pipeline.add(new LibraryProfileCwe22PathGatePass);
41790
42198
  if (!disabledPasses.has("scan-secrets"))
41791
42199
  pipeline.add(new ScanSecretsPass);
41792
42200
  if (!disabledPasses.has("dead-code"))
@@ -41935,7 +42343,7 @@ async function analyze(code, filePath, language, options = {}) {
41935
42343
  emitFindingsInstrumentation(filePath, findings, taint);
41936
42344
  const verifiedFindings = applyConfidenceFilter(findings, options.includeSpeculative === true);
41937
42345
  const downgradedFindings = applyLibraryApiSurfaceDowngrade(verifiedFindings);
41938
- const profiledFindings = applyProjectProfileTransform(downgradedFindings, makeProfileResolver(options.projectProfile));
42346
+ const profiledFindings = applyProjectProfileTransform(downgradedFindings, makeProfileResolver2(options.projectProfile));
41939
42347
  const cappedFindings = applyPerFileFindingCap(filePath, profiledFindings, options.perFileFindingCap ?? DEFAULT_PER_FILE_FINDING_CAP);
41940
42348
  return {
41941
42349
  meta,
@@ -42059,6 +42467,10 @@ async function analyzeProject(files, options = {}) {
42059
42467
  fa.analysis.findings = [...fa.analysis.findings ?? [], finding];
42060
42468
  }
42061
42469
  }
42470
+ applyRequireEntryPath(fileAnalyses, {
42471
+ projectProfile: options.projectProfile,
42472
+ disabledPasses: options.disabledPasses
42473
+ });
42062
42474
  const filePaths = files.map((f) => f.filePath);
42063
42475
  const totalLoc = fileAnalyses.reduce((sum, f) => sum + (f.analysis.meta.loc ?? 0), 0);
42064
42476
  const meta = {
@@ -42713,7 +43125,7 @@ var colors = {
42713
43125
  };
42714
43126
 
42715
43127
  // src/version.ts
42716
- var version = "3.152.0";
43128
+ var version = "3.154.0";
42717
43129
 
42718
43130
  // src/formatters.ts
42719
43131
  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.152.0",
3
+ "version": "3.154.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.152.0"
69
+ "circle-ir": "^3.154.0"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/node": "^25.5.0",