cognium-dev 4.9.24 → 4.9.25

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 +85 -23
  2. package/package.json +3 -5
package/dist/cli.js CHANGED
@@ -50156,19 +50156,30 @@ var YELLOW = "\x1B[93m";
50156
50156
  var BLUE = "\x1B[94m";
50157
50157
  var CYAN = "\x1B[96m";
50158
50158
  var MAGENTA = "\x1B[95m";
50159
+ function colorEnabled() {
50160
+ const noColor = process.env.NO_COLOR;
50161
+ if (noColor !== undefined && noColor !== "")
50162
+ return false;
50163
+ if (process.env.TERM === "dumb")
50164
+ return false;
50165
+ return true;
50166
+ }
50167
+ function paint(code, text) {
50168
+ return colorEnabled() ? `${code}${text}${RESET}` : text;
50169
+ }
50159
50170
  var colors = {
50160
- red: (text) => `${RED}${text}${RESET}`,
50161
- green: (text) => `${GREEN}${text}${RESET}`,
50162
- yellow: (text) => `${YELLOW}${text}${RESET}`,
50163
- blue: (text) => `${BLUE}${text}${RESET}`,
50164
- cyan: (text) => `${CYAN}${text}${RESET}`,
50165
- magenta: (text) => `${MAGENTA}${text}${RESET}`,
50166
- bold: (text) => `${BOLD}${text}${RESET}`,
50171
+ red: (text) => paint(RED, text),
50172
+ green: (text) => paint(GREEN, text),
50173
+ yellow: (text) => paint(YELLOW, text),
50174
+ blue: (text) => paint(BLUE, text),
50175
+ cyan: (text) => paint(CYAN, text),
50176
+ magenta: (text) => paint(MAGENTA, text),
50177
+ bold: (text) => paint(BOLD, text),
50167
50178
  dim: (text) => text
50168
50179
  };
50169
50180
 
50170
50181
  // src/version.ts
50171
- var version = "4.9.24";
50182
+ var version = "4.9.25";
50172
50183
 
50173
50184
  // src/formatters.ts
50174
50185
  var LIBRARY_API_SURFACE_TAG2 = "library-api-surface:caller-responsibility";
@@ -50713,8 +50724,8 @@ function generateSarifResults(results, crossFileData) {
50713
50724
 
50714
50725
  // src/build-info.ts
50715
50726
  var buildInfo = {
50716
- gitSha: "527cda0",
50717
- builtAt: "2026-09-23T02:30:52.145Z"
50727
+ gitSha: "2467260",
50728
+ builtAt: "2026-09-24T06:46:18.058Z"
50718
50729
  };
50719
50730
 
50720
50731
  // src/utils/args.ts
@@ -50773,7 +50784,7 @@ COMMANDS:
50773
50784
  version Display version information
50774
50785
 
50775
50786
  SCAN OPTIONS:
50776
- -l, --language <lang> Scan only files for language (bash|go|html|java|javascript|typescript|python|rust)
50787
+ -l, --language <lang> Scan only files for language (bash|csharp|go|html|java|javascript|typescript|python|rust)
50777
50788
  -f, --format <format> Output format (text|json|sarif) [default: text]
50778
50789
  --threads <n> Parallel analysis threads [default: 4]
50779
50790
  --severity <level> Filter by severity:
@@ -50806,7 +50817,7 @@ SCAN OPTIONS:
50806
50817
  surfaced in output (text warning / JSON / SARIF field).
50807
50818
 
50808
50819
  METRICS OPTIONS:
50809
- -l, --language <lang> Analyze only files for language (bash|go|html|java|javascript|typescript|python|rust)
50820
+ -l, --language <lang> Analyze only files for language (bash|csharp|go|html|java|javascript|typescript|python|rust)
50810
50821
  -f, --format <format> Output format (text|json) [default: text]
50811
50822
  --category <cats> Filter by metric category (comma-separated):
50812
50823
  - Valid categories: complexity, size, coupling,
@@ -50915,19 +50926,19 @@ class Spinner {
50915
50926
  succeed(text) {
50916
50927
  this.stop();
50917
50928
  const message = text || this._text;
50918
- console.error(`\x1B[32m${CHECKMARK}\x1B[0m ${message}`);
50929
+ console.error(`${colors.green(CHECKMARK)} ${message}`);
50919
50930
  return this;
50920
50931
  }
50921
50932
  fail(text) {
50922
50933
  this.stop();
50923
50934
  const message = text || this._text;
50924
- console.error(`\x1B[31m${CROSS}\x1B[0m ${message}`);
50935
+ console.error(`${colors.red(CROSS)} ${message}`);
50925
50936
  return this;
50926
50937
  }
50927
50938
  warn(text) {
50928
50939
  this.stop();
50929
50940
  const message = text || this._text;
50930
- console.error(`\x1B[33m${WARNING}\x1B[0m ${message}`);
50941
+ console.error(`${colors.yellow(WARNING)} ${message}`);
50931
50942
  return this;
50932
50943
  }
50933
50944
  set text(value) {
@@ -50954,8 +50965,7 @@ function loadConfig(profilePath) {
50954
50965
  const content = readFileSync(configPath, "utf-8");
50955
50966
  return JSON.parse(content);
50956
50967
  } catch (err2) {
50957
- console.error(colors.yellow(`Warning: Failed to parse ${configPath}: ${err2}`));
50958
- return null;
50968
+ throw new Error(`Failed to parse ${configPath}: ${err2 instanceof Error ? err2.message : String(err2)}. ` + "Fix the JSON or remove the file.");
50959
50969
  }
50960
50970
  }
50961
50971
  function convertConfigToPassOptions(config) {
@@ -51021,6 +51031,27 @@ function applySuppressionsToResults(results, suppressions, basePath) {
51021
51031
  return { ...result, vulnerabilities: filteredVulns };
51022
51032
  });
51023
51033
  }
51034
+ function applySuppressionsToTaintPaths(paths, suppressions, basePath) {
51035
+ if (suppressions.length === 0)
51036
+ return paths;
51037
+ return paths.filter((path) => {
51038
+ for (const supp of suppressions) {
51039
+ const sinkType = path.sink.type;
51040
+ if (supp.pass !== sinkType && supp.pass !== `cross-file-${sinkType}`)
51041
+ continue;
51042
+ if (supp.file) {
51043
+ const suppFile = supp.file.replace(/^\.\//, "");
51044
+ const relativeFile = relative4(basePath, path.sink.file) || path.sink.file;
51045
+ if (suppFile !== relativeFile && suppFile !== path.sink.file)
51046
+ continue;
51047
+ }
51048
+ if (supp.line !== undefined && supp.line !== path.sink.line)
51049
+ continue;
51050
+ return false;
51051
+ }
51052
+ return true;
51053
+ });
51054
+ }
51024
51055
  var TEST_PATTERNS = [
51025
51056
  /[\/\\]test[\/\\]/i,
51026
51057
  /[\/\\]tests[\/\\]/i,
@@ -51078,9 +51109,30 @@ function detectLanguage7(filePath) {
51078
51109
  const ext = extname(filePath).toLowerCase();
51079
51110
  return LANG_MAP[ext] || null;
51080
51111
  }
51112
+ var SUPPORTED_SCAN_LANGUAGES = [
51113
+ ...new Set(Object.values(LANG_MAP))
51114
+ ].sort();
51081
51115
  function normalizeLanguage(language) {
51082
51116
  return language.trim().toLowerCase();
51083
51117
  }
51118
+ function resolveScanLanguage(raw) {
51119
+ if (raw === undefined || raw === "")
51120
+ return;
51121
+ const normalized = normalizeLanguage(String(raw));
51122
+ if (!SUPPORTED_SCAN_LANGUAGES.includes(normalized)) {
51123
+ throw new Error(`Invalid language: ${normalized}
51124
+ Valid options: ${SUPPORTED_SCAN_LANGUAGES.join(", ")}`);
51125
+ }
51126
+ return normalized;
51127
+ }
51128
+ function languageFromCliOptions(options) {
51129
+ try {
51130
+ return resolveScanLanguage(options.language || options.l);
51131
+ } catch (err2) {
51132
+ console.error(colors.red(`Error: ${err2.message}`));
51133
+ process.exit(1);
51134
+ }
51135
+ }
51084
51136
  function fileMatchesLanguage(filePath, language) {
51085
51137
  const detected = detectLanguage7(filePath);
51086
51138
  if (!detected)
@@ -51091,9 +51143,13 @@ function fileMatchesLanguage(filePath, language) {
51091
51143
  }
51092
51144
  function matchesGlob(filePath, pattern) {
51093
51145
  const normalizedPath = filePath.replace(/\\/g, "/");
51094
- const normalizedPattern = pattern.replace(/\\/g, "/");
51146
+ let normalizedPattern = pattern.replace(/\\/g, "/");
51147
+ normalizedPattern = normalizedPattern.replace(/\*{3,}/g, "**").replace(/(?:\*\*\/)+/g, "**/").replace(/(?:\/\*\*)+/g, "/**");
51148
+ const globstarCount = (normalizedPattern.match(/\*\*/g) ?? []).length;
51149
+ if (globstarCount > 4)
51150
+ return false;
51095
51151
  let regex = normalizedPattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\?/g, ".");
51096
- regex = regex.replace(/\{\{GLOBSTAR\}\}\//g, "(?:.+/)?").replace(/\/\{\{GLOBSTAR\}\}/g, "(?:/.*)?").replace(/\{\{GLOBSTAR\}\}/g, ".*");
51152
+ regex = regex.replace(/\{\{GLOBSTAR\}\}\//g, "(?:[^/]+/)*").replace(/\/\{\{GLOBSTAR\}\}/g, "(?:/[^/]+)*").replace(/\{\{GLOBSTAR\}\}/g, "[^]*");
51097
51153
  return new RegExp("^" + regex + "$").test(normalizedPath);
51098
51154
  }
51099
51155
  function matchesAnyPattern(filePath, patterns) {
@@ -51484,9 +51540,12 @@ async function runScan(targetPath, options) {
51484
51540
  if (spin)
51485
51541
  spin.succeed(`Scanned ${files.length} file(s)`);
51486
51542
  if (suppressions.length > 0) {
51487
- const beforeCount = results.reduce((sum, r) => sum + r.vulnerabilities.length, 0);
51543
+ const beforeCount = results.reduce((sum, r) => sum + r.vulnerabilities.length, 0) + (crossFileData?.taintPaths.length ?? 0);
51488
51544
  results = applySuppressionsToResults(results, suppressions, process.cwd());
51489
- const afterCount = results.reduce((sum, r) => sum + r.vulnerabilities.length, 0);
51545
+ if (crossFileData) {
51546
+ crossFileData.taintPaths = applySuppressionsToTaintPaths(crossFileData.taintPaths, suppressions, process.cwd());
51547
+ }
51548
+ const afterCount = results.reduce((sum, r) => sum + r.vulnerabilities.length, 0) + (crossFileData?.taintPaths.length ?? 0);
51490
51549
  if (!options.quiet && beforeCount !== afterCount) {
51491
51550
  console.error(colors.dim(`Suppressed ${beforeCount - afterCount} finding(s) via config`));
51492
51551
  }
@@ -52035,7 +52094,7 @@ Usage: cognium-dev metrics <path> [options]`);
52035
52094
  category: options.category,
52036
52095
  output: options.output || options.o,
52037
52096
  quiet: options.quiet === true || options.q === true,
52038
- language: options.language || options.l ? normalizeLanguage(options.language || options.l) : undefined,
52097
+ language: languageFromCliOptions(options),
52039
52098
  excludeTests: options["exclude-tests"] === true,
52040
52099
  profile: options.profile || options.p
52041
52100
  };
@@ -52073,7 +52132,7 @@ Usage: cognium-dev scan <path> [options]`);
52073
52132
  }
52074
52133
  const targetPath = args2[0];
52075
52134
  const scanOptions = {
52076
- language: options.language || options.l ? normalizeLanguage(options.language || options.l) : undefined,
52135
+ language: languageFromCliOptions(options),
52077
52136
  format: options.format || options.f || "text",
52078
52137
  threads: parseInt(options.threads || "4", 10),
52079
52138
  severity: options.severity,
@@ -52107,12 +52166,15 @@ main().catch((error) => {
52107
52166
  process.exit(2);
52108
52167
  });
52109
52168
  export {
52169
+ resolveScanLanguage,
52110
52170
  matchesGlob,
52111
52171
  loadConfig,
52112
52172
  isTestFile2 as isTestFile,
52113
52173
  detectLanguage7 as detectLanguage,
52114
52174
  dedupeVulnerabilities,
52115
52175
  convertConfigToPassOptions,
52176
+ applySuppressionsToTaintPaths,
52116
52177
  applySuppressionsToResults,
52178
+ SUPPORTED_SCAN_LANGUAGES,
52117
52179
  PASS_REGISTRY
52118
52180
  };
package/package.json CHANGED
@@ -1,9 +1,7 @@
1
1
  {
2
2
  "name": "cognium-dev",
3
- "version": "4.9.24",
3
+ "version": "4.9.25",
4
4
  "description": "Static Application Security Testing CLI for detecting security vulnerabilities via taint tracking",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
5
  "bin": {
8
6
  "cognium-dev": "dist/cli.js"
9
7
  },
@@ -14,7 +12,7 @@
14
12
  "test": "bun test",
15
13
  "clean": "rm -rf dist cognium-dev cognium-dev-* *.bun-build wasm",
16
14
  "typecheck": "tsc --noEmit",
17
- "version": "node -e \"const v = require('./package.json').version; require('fs').writeFileSync('src/version.ts', '/**\\n * Version information\\n *\\n * Kept in sync with package.json via the \\`version\\` npm lifecycle script.\\n * Do not edit manually — use \\`npm version patch|minor|major\\` instead.\\n */\\nexport const version = \\x27' + v + '\\x27;\\n')\" && git add src/version.ts",
15
+ "version": "node -e \"const v = require('./package.json').version; require('fs').writeFileSync('src/version.ts', '/**\\n * Version information\\n *\\n * Kept in sync with package.json via the \\`version\\` npm lifecycle script.\\n * Do not edit manually \u2014 use \\`npm version patch|minor|major\\` instead.\\n */\\nexport const version = \\x27' + v + '\\x27;\\n')\" && git add src/version.ts",
18
16
  "dogfood": "bun run src/cli.ts scan src/ -q",
19
17
  "prepublishOnly": "bun run build",
20
18
  "test:coverage": "bun test --coverage"
@@ -67,7 +65,7 @@
67
65
  },
68
66
  "dependencies": {
69
67
  "@cognium/project-profile-detect": "1.1.1",
70
- "circle-ir": "4.9.24"
68
+ "circle-ir": "4.9.25"
71
69
  },
72
70
  "devDependencies": {
73
71
  "@types/node": "^26.6.1",