cognium-dev 3.150.0 → 3.152.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 +154 -1
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -28873,6 +28873,61 @@ class SourceSemanticsPass {
28873
28873
  }
28874
28874
  }
28875
28875
 
28876
+ // ../circle-ir/dist/analysis/passes/library-profile-source-gate-pass.js
28877
+ var SPECULATIVE_SOURCE_TYPES = new Set([
28878
+ "interprocedural_param",
28879
+ "constructor_field"
28880
+ ]);
28881
+ function isLibraryShape(profile) {
28882
+ if (!profile || profile === "unknown")
28883
+ return false;
28884
+ return profile.startsWith("library/");
28885
+ }
28886
+
28887
+ class LibraryProfileSourceGatePass {
28888
+ name = "library-profile-source-gate";
28889
+ category = "security";
28890
+ run(ctx) {
28891
+ const { graph } = ctx;
28892
+ const profile = graph.ir.meta.projectProfile;
28893
+ if (!isLibraryShape(profile)) {
28894
+ return {
28895
+ profile,
28896
+ applied: false,
28897
+ dropped: 0,
28898
+ droppedByType: {}
28899
+ };
28900
+ }
28901
+ const sources = graph.ir.taint.sources;
28902
+ if (sources.length === 0) {
28903
+ return {
28904
+ profile,
28905
+ applied: true,
28906
+ dropped: 0,
28907
+ droppedByType: {}
28908
+ };
28909
+ }
28910
+ const droppedByType = {};
28911
+ const kept = [];
28912
+ for (const src of sources) {
28913
+ if (SPECULATIVE_SOURCE_TYPES.has(src.type)) {
28914
+ droppedByType[src.type] = (droppedByType[src.type] ?? 0) + 1;
28915
+ continue;
28916
+ }
28917
+ kept.push(src);
28918
+ }
28919
+ const dropped = sources.length - kept.length;
28920
+ sources.length = 0;
28921
+ sources.push(...kept);
28922
+ return {
28923
+ profile,
28924
+ applied: true,
28925
+ dropped,
28926
+ droppedByType
28927
+ };
28928
+ }
28929
+ }
28930
+
28876
28931
  // ../circle-ir/dist/analysis/passes/sink-filter-pass.js
28877
28932
  var JS_XSS_SANITIZERS = [
28878
28933
  /\bDOMPurify\.sanitize\s*\(/,
@@ -30554,6 +30609,62 @@ class CliMainReflectionSuppressPass {
30554
30609
  }
30555
30610
  }
30556
30611
 
30612
+ // ../circle-ir/dist/analysis/passes/library-profile-sink-gate-pass.js
30613
+ var DROPPED_SINK_TYPES = new Set([
30614
+ "log_injection"
30615
+ ]);
30616
+ function isLibraryShape2(profile) {
30617
+ if (!profile || profile === "unknown")
30618
+ return false;
30619
+ return profile.startsWith("library/");
30620
+ }
30621
+
30622
+ class LibraryProfileSinkGatePass {
30623
+ name = "library-profile-sink-gate";
30624
+ category = "security";
30625
+ run(ctx) {
30626
+ const { graph } = ctx;
30627
+ const profile = graph.ir.meta.projectProfile;
30628
+ if (!isLibraryShape2(profile)) {
30629
+ return {
30630
+ profile,
30631
+ applied: false,
30632
+ dropped: 0,
30633
+ droppedByType: {}
30634
+ };
30635
+ }
30636
+ const sinks = ctx.hasResult("sink-filter") ? ctx.getResult("sink-filter").sinks : graph.ir.taint.sinks;
30637
+ if (sinks.length === 0) {
30638
+ return {
30639
+ profile,
30640
+ applied: true,
30641
+ dropped: 0,
30642
+ droppedByType: {}
30643
+ };
30644
+ }
30645
+ const droppedByType = {};
30646
+ const kept = [];
30647
+ for (const sink of sinks) {
30648
+ if (DROPPED_SINK_TYPES.has(sink.type)) {
30649
+ droppedByType[sink.type] = (droppedByType[sink.type] ?? 0) + 1;
30650
+ continue;
30651
+ }
30652
+ kept.push(sink);
30653
+ }
30654
+ const dropped = sinks.length - kept.length;
30655
+ if (dropped > 0) {
30656
+ sinks.length = 0;
30657
+ sinks.push(...kept);
30658
+ }
30659
+ return {
30660
+ profile,
30661
+ applied: true,
30662
+ dropped,
30663
+ droppedByType
30664
+ };
30665
+ }
30666
+ }
30667
+
30557
30668
  // ../circle-ir/dist/analysis/passes/taint-propagation-pass.js
30558
30669
  class TaintPropagationPass {
30559
30670
  name = "taint-propagation";
@@ -41571,6 +41682,38 @@ function makeProfileResolver(p) {
41571
41682
  return () => p;
41572
41683
  return (file) => p.get(file) ?? "unknown";
41573
41684
  }
41685
+ function computeProjectProfileSummary(fileAnalyses) {
41686
+ const byShape = {
41687
+ library: 0,
41688
+ application: 0,
41689
+ cli: 0,
41690
+ server: 0,
41691
+ plugin: 0,
41692
+ unknown: 0
41693
+ };
41694
+ const byEnv = {
41695
+ production: 0,
41696
+ dev: 0,
41697
+ sample: 0,
41698
+ benchmark: 0,
41699
+ test: 0,
41700
+ unknown: 0
41701
+ };
41702
+ for (const { analysis } of fileAnalyses) {
41703
+ const profile = analysis.meta.projectProfile ?? "unknown";
41704
+ if (profile === "unknown") {
41705
+ byShape.unknown += 1;
41706
+ byEnv.unknown += 1;
41707
+ continue;
41708
+ }
41709
+ const slash = profile.indexOf("/");
41710
+ const shape = profile.slice(0, slash);
41711
+ const env = profile.slice(slash + 1);
41712
+ byShape[shape] += 1;
41713
+ byEnv[env] += 1;
41714
+ }
41715
+ return { byShape, byEnv, totalFiles: fileAnalyses.length };
41716
+ }
41574
41717
  async function analyze(code, filePath, language, options = {}) {
41575
41718
  if (!initialized) {
41576
41719
  await initAnalyzer(options);
@@ -41600,6 +41743,9 @@ async function analyze(code, filePath, language, options = {}) {
41600
41743
  }
41601
41744
  const nodeCache = collectAllNodes(tree.rootNode, getNodeTypesForLanguage(language));
41602
41745
  const meta = extractMeta(code, tree, filePath, language);
41746
+ if (options.projectProfile !== undefined) {
41747
+ meta.projectProfile = makeProfileResolver(options.projectProfile)(filePath);
41748
+ }
41603
41749
  const types = extractTypes(tree, nodeCache, language);
41604
41750
  const calls = extractCalls(tree, nodeCache, language);
41605
41751
  const imports = extractImports(tree, language);
@@ -41628,11 +41774,15 @@ async function analyze(code, filePath, language, options = {}) {
41628
41774
  pipeline.add(new LanguageSourcesPass);
41629
41775
  if (!disabledPasses.has("source-semantics"))
41630
41776
  pipeline.add(new SourceSemanticsPass);
41777
+ if (!disabledPasses.has("library-profile-source-gate"))
41778
+ pipeline.add(new LibraryProfileSourceGatePass);
41631
41779
  pipeline.add(new SinkFilterPass);
41632
41780
  if (!disabledPasses.has("sink-semantics"))
41633
41781
  pipeline.add(new SinkSemanticsPass);
41634
41782
  if (!disabledPasses.has("cli-main-reflection-suppress"))
41635
41783
  pipeline.add(new CliMainReflectionSuppressPass);
41784
+ if (!disabledPasses.has("library-profile-sink-gate"))
41785
+ pipeline.add(new LibraryProfileSinkGatePass);
41636
41786
  pipeline.add(new TaintPropagationPass);
41637
41787
  pipeline.add(new InterproceduralPass({
41638
41788
  enableEntryPointGate: options.enableEntryPointGate ?? true
@@ -41919,6 +42069,9 @@ async function analyzeProject(files, options = {}) {
41919
42069
  total_loc: totalLoc,
41920
42070
  analyzed_at: new Date().toISOString()
41921
42071
  };
42072
+ if (options.projectProfile !== undefined) {
42073
+ meta.projectProfileSummary = computeProjectProfileSummary(fileAnalyses);
42074
+ }
41922
42075
  const projectAnalysis = {
41923
42076
  meta,
41924
42077
  files: fileAnalyses,
@@ -42560,7 +42713,7 @@ var colors = {
42560
42713
  };
42561
42714
 
42562
42715
  // src/version.ts
42563
- var version = "3.150.0";
42716
+ var version = "3.152.0";
42564
42717
 
42565
42718
  // src/formatters.ts
42566
42719
  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.150.0",
3
+ "version": "3.152.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.150.0"
69
+ "circle-ir": "^3.152.0"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/node": "^25.5.0",