cognium-dev 4.9.10 → 4.9.11

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 +158 -158
  2. package/package.json +4 -4
package/dist/cli.js CHANGED
@@ -5,7 +5,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
5
5
  // src/cli.ts
6
6
  import { readFileSync, existsSync, writeFileSync } from "fs";
7
7
  import { stat as stat2, readdir as readdir2 } from "fs/promises";
8
- import { join as join2, dirname as dirname3, extname, resolve as resolve2, relative as relative4, basename } from "path";
8
+ import { join as join2, dirname as dirname2, extname, resolve, relative as relative3, basename } from "path";
9
9
  import { createRequire as createRequire2 } from "module";
10
10
 
11
11
  // ../../node_modules/web-tree-sitter/web-tree-sitter.js
@@ -5338,6 +5338,27 @@ var CSHARP_COMMAND_EXECUTE_METHODS = new Set([
5338
5338
  "ExecuteReaderAsync",
5339
5339
  "ExecuteNonQueryAsync"
5340
5340
  ]);
5341
+ var CSHARP_RECEIVER_URL_METHODS = new Set([
5342
+ "GetAsync",
5343
+ "PostAsync",
5344
+ "PutAsync",
5345
+ "PatchAsync",
5346
+ "DeleteAsync",
5347
+ "HeadAsync",
5348
+ "GetStringAsync",
5349
+ "GetByteArrayAsync",
5350
+ "GetStreamAsync",
5351
+ "GetJsonAsync"
5352
+ ]);
5353
+ var CSHARP_HEADER_RECEIVER_RE = /(^|\.)Headers$/;
5354
+ function csharpBareName(node) {
5355
+ if (node.type === "generic_name") {
5356
+ const id = node.childForFieldName("name") ?? node.namedChild(0);
5357
+ if (id)
5358
+ return getNodeText(id);
5359
+ }
5360
+ return getNodeText(node);
5361
+ }
5341
5362
  function extractCSharpCalls(tree, cache) {
5342
5363
  const calls = [];
5343
5364
  const typeMap = buildCSharpReceiverTypeMap(tree, cache);
@@ -5349,16 +5370,22 @@ function extractCSharpCalls(tree, cache) {
5349
5370
  if (fn?.type === "member_access_expression") {
5350
5371
  const nameNode = fn.childForFieldName("name");
5351
5372
  const exprNode = fn.childForFieldName("expression");
5352
- methodName = nameNode ? getNodeText(nameNode) : "unknown";
5373
+ methodName = nameNode ? csharpBareName(nameNode) : "unknown";
5353
5374
  receiver = exprNode ? getNodeText(exprNode) : null;
5354
5375
  } else if (fn) {
5355
- methodName = getNodeText(fn);
5376
+ methodName = csharpBareName(fn);
5356
5377
  }
5357
5378
  const argsNode = inv.childForFieldName("arguments");
5358
5379
  let args2 = argsNode ? extractCSharpArguments(argsNode) : [];
5359
5380
  if (receiver && CSHARP_COMMAND_EXECUTE_METHODS.has(methodName)) {
5360
5381
  args2 = [{ position: 0, expression: receiver, variable: receiver, literal: null, value: null }, ...args2];
5361
5382
  }
5383
+ if (methodName === "Add" && receiver && CSHARP_HEADER_RECEIVER_RE.test(receiver)) {
5384
+ methodName = "AddHeader";
5385
+ }
5386
+ if (receiver && args2.length === 0 && CSHARP_RECEIVER_URL_METHODS.has(methodName)) {
5387
+ args2 = [{ position: 0, expression: receiver, variable: receiver, literal: null, value: null }];
5388
+ }
5362
5389
  calls.push({
5363
5390
  method_name: methodName,
5364
5391
  receiver,
@@ -5374,7 +5401,7 @@ function extractCSharpCalls(tree, cache) {
5374
5401
  const typeNode = creation.childForFieldName("type");
5375
5402
  const argsNode = creation.childForFieldName("arguments");
5376
5403
  calls.push({
5377
- method_name: typeNode ? getNodeText(typeNode) : "unknown",
5404
+ method_name: typeNode ? csharpBareName(typeNode) : "unknown",
5378
5405
  receiver: null,
5379
5406
  receiver_type: null,
5380
5407
  receiver_type_fqn: null,
@@ -5387,6 +5414,41 @@ function extractCSharpCalls(tree, cache) {
5387
5414
  const assignments = getNodesFromCache(tree.rootNode, "assignment_expression", cache);
5388
5415
  for (const asn of assignments) {
5389
5416
  const left = asn.childForFieldName("left");
5417
+ if (left?.type === "element_access_expression") {
5418
+ const target = left.childForFieldName("expression");
5419
+ const right2 = asn.childForFieldName("right");
5420
+ if (!target || !right2)
5421
+ continue;
5422
+ if (!CSHARP_HEADER_RECEIVER_RE.test(getNodeText(target)))
5423
+ continue;
5424
+ const subscript = left.childForFieldName("subscript") ?? left.namedChild(1);
5425
+ const rhsText2 = getNodeText(right2);
5426
+ calls.push({
5427
+ method_name: "AddHeader",
5428
+ receiver: getNodeText(target),
5429
+ receiver_type: null,
5430
+ receiver_type_fqn: null,
5431
+ arguments: [
5432
+ {
5433
+ position: 0,
5434
+ expression: subscript ? getNodeText(subscript) : "",
5435
+ variable: null,
5436
+ literal: subscript ? getNodeText(subscript) : null,
5437
+ value: null
5438
+ },
5439
+ {
5440
+ position: 1,
5441
+ expression: rhsText2,
5442
+ variable: right2.type === "identifier" ? rhsText2 : null,
5443
+ literal: right2.type === "string_literal" ? rhsText2 : null,
5444
+ value: null
5445
+ }
5446
+ ],
5447
+ location: { line: asn.startPosition.row + 1, column: asn.startPosition.column },
5448
+ in_method: findEnclosingMethod(asn)
5449
+ });
5450
+ continue;
5451
+ }
5390
5452
  if (left?.type !== "member_access_expression")
5391
5453
  continue;
5392
5454
  const nameNode = left.childForFieldName("name");
@@ -12474,6 +12536,17 @@ var DEFAULT_SINKS = [
12474
12536
  { method: "ExecuteSqlRawAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12475
12537
  { method: "FromSqlRaw", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12476
12538
  { method: "FromSqlRawAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12539
+ { method: "Query", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12540
+ { method: "QueryAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12541
+ { method: "QueryFirst", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12542
+ { method: "QueryFirstAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12543
+ { method: "QueryFirstOrDefault", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12544
+ { method: "QueryFirstOrDefaultAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12545
+ { method: "QuerySingle", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12546
+ { method: "QuerySingleOrDefault", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12547
+ { method: "QueryMultiple", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12548
+ { method: "Execute", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12549
+ { method: "ExecuteAsync", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12477
12550
  { method: "CommandText", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12478
12551
  { method: "Filter", type: "ldap_injection", cwe: "CWE-90", severity: "high", arg_positions: [0], languages: ["csharp"] },
12479
12552
  { method: "ExecuteScalar", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["csharp"] },
@@ -12515,12 +12588,16 @@ var DEFAULT_SINKS = [
12515
12588
  { method: "DeleteAsync", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
12516
12589
  { method: "GetStringAsync", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
12517
12590
  { method: "GetByteArrayAsync", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
12591
+ { method: "GetJsonAsync", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
12592
+ { method: "PatchAsync", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
12593
+ { method: "HeadAsync", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
12518
12594
  { method: "GetStreamAsync", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
12519
12595
  { method: "SendAsync", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
12520
12596
  { method: "DownloadString", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
12521
12597
  { method: "DownloadData", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
12522
12598
  { method: "DownloadFile", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [1], languages: ["csharp"] },
12523
12599
  { method: "Create", class: "WebRequest", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
12600
+ { method: "RestClient", class: "constructor", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [0], languages: ["csharp"] },
12524
12601
  { method: "EvaluateAsync", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12525
12602
  { method: "RunAsync", class: "CSharpScript", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["csharp"] },
12526
12603
  { method: "Load", class: "Assembly", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["csharp"] },
@@ -12538,6 +12615,7 @@ var DEFAULT_SINKS = [
12538
12615
  { method: "Write", class: "Response", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["csharp"] },
12539
12616
  { method: "HtmlString", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["csharp"] },
12540
12617
  { method: "MarkupString", class: "constructor", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["csharp"] },
12618
+ { method: "Content", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0], languages: ["csharp"] },
12541
12619
  { method: "Format", class: "String", type: "format_string", cwe: "CWE-134", severity: "medium", arg_positions: [0], languages: ["csharp"] },
12542
12620
  { method: "DirectorySearcher", type: "ldap_injection", cwe: "CWE-90", severity: "high", arg_positions: [0], languages: ["csharp"] },
12543
12621
  { method: "DirectoryEntry", type: "ldap_injection", cwe: "CWE-90", severity: "high", arg_positions: [0], languages: ["csharp"] },
@@ -12546,12 +12624,18 @@ var DEFAULT_SINKS = [
12546
12624
  { method: "AddHeader", type: "crlf", cwe: "CWE-113", severity: "medium", arg_positions: [1], languages: ["csharp"] },
12547
12625
  { method: "AppendHeader", type: "crlf", cwe: "CWE-113", severity: "medium", arg_positions: [1], languages: ["csharp"] },
12548
12626
  { method: "Parse", class: "BsonDocument", type: "nosql_injection", cwe: "CWE-943", severity: "high", arg_positions: [0], languages: ["csharp"] },
12627
+ { method: "BsonJavaScript", class: "constructor", type: "nosql_injection", cwe: "CWE-943", severity: "high", arg_positions: [0], languages: ["csharp"] },
12549
12628
  { method: "LogInformation", type: "log_injection", cwe: "CWE-117", severity: "low", arg_positions: [0], languages: ["csharp"] },
12550
12629
  { method: "LogWarning", type: "log_injection", cwe: "CWE-117", severity: "low", arg_positions: [0], languages: ["csharp"] },
12551
12630
  { method: "LogError", type: "log_injection", cwe: "CWE-117", severity: "low", arg_positions: [0], languages: ["csharp"] },
12552
12631
  { method: "LogDebug", type: "log_injection", cwe: "CWE-117", severity: "low", arg_positions: [0], languages: ["csharp"] },
12553
12632
  { method: "LogCritical", type: "log_injection", cwe: "CWE-117", severity: "low", arg_positions: [0], languages: ["csharp"] },
12554
12633
  { method: "LogTrace", type: "log_injection", cwe: "CWE-117", severity: "low", arg_positions: [0], languages: ["csharp"] },
12634
+ { method: "IsMatch", class: "Regex", type: "redos", cwe: "CWE-1333", severity: "medium", arg_positions: [1], languages: ["csharp"] },
12635
+ { method: "Match", class: "Regex", type: "redos", cwe: "CWE-1333", severity: "medium", arg_positions: [1], languages: ["csharp"] },
12636
+ { method: "Matches", class: "Regex", type: "redos", cwe: "CWE-1333", severity: "medium", arg_positions: [1], languages: ["csharp"] },
12637
+ { method: "Replace", class: "Regex", type: "redos", cwe: "CWE-1333", severity: "medium", arg_positions: [1], languages: ["csharp"] },
12638
+ { method: "Regex", class: "constructor", type: "redos", cwe: "CWE-1333", severity: "medium", arg_positions: [0], languages: ["csharp"] },
12555
12639
  { method: "Log", class: "ILogger", type: "log_injection", cwe: "CWE-117", severity: "low", arg_positions: [1], languages: ["csharp"] },
12556
12640
  { method: "SelectSingleNode", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0], languages: ["csharp"] },
12557
12641
  { method: "SelectNodes", type: "xpath_injection", cwe: "CWE-643", severity: "high", arg_positions: [0], languages: ["csharp"] },
@@ -12691,6 +12775,8 @@ var DEFAULT_SANITIZERS = [
12691
12775
  { method: "encodeToString", removes: ["sql_injection", "command_injection", "xss", "path_traversal", "code_injection"] },
12692
12776
  { method: "encodeHexString", removes: ["sql_injection", "command_injection", "xss", "path_traversal", "code_injection"] },
12693
12777
  { method: "encodeForURL", removes: ["xss", "ssrf", "open_redirect"] },
12778
+ { method: "IsLocalUrl", removes: ["open_redirect"] },
12779
+ { method: "LocalRedirect", removes: ["open_redirect"] },
12694
12780
  { method: "encodeURL", removes: ["xss", "ssrf", "open_redirect"] },
12695
12781
  { method: "urlEncode", removes: ["xss", "ssrf", "open_redirect"] },
12696
12782
  { method: "escapeUrl", removes: ["xss", "ssrf", "open_redirect"] },
@@ -15388,12 +15474,12 @@ function walkBackwardDefs(startDefId, chainsByToDef, defById, options = {}) {
15388
15474
  // node_modules/circle-ir/dist/analysis/findings.js
15389
15475
  function canSourceReachSink(sourceType, sinkType) {
15390
15476
  const sourceToSinkMapping = {
15391
- http_param: ["sql_injection", "command_injection", "path_traversal", "xss", "xpath_injection", "ldap_injection", "ssrf", "mybatis_mapper_call", "code_injection", "crlf", "mass_assignment", "open_redirect", "trust_boundary", "deserialization", "log_injection", "format_string", "nosql_injection", "prompt_injection"],
15477
+ http_param: ["sql_injection", "command_injection", "path_traversal", "xss", "xpath_injection", "ldap_injection", "ssrf", "mybatis_mapper_call", "code_injection", "crlf", "mass_assignment", "open_redirect", "trust_boundary", "deserialization", "xxe", "log_injection", "format_string", "nosql_injection", "prompt_injection"],
15392
15478
  http_body: ["sql_injection", "command_injection", "deserialization", "xxe", "xss", "code_injection", "mybatis_mapper_call", "crlf", "mass_assignment", "open_redirect", "trust_boundary", "log_injection", "format_string", "nosql_injection", "prompt_injection"],
15393
15479
  http_header: ["sql_injection", "xss", "ssrf", "mybatis_mapper_call", "code_injection", "crlf", "open_redirect", "trust_boundary", "log_injection", "format_string", "nosql_injection", "prompt_injection"],
15394
15480
  http_cookie: ["sql_injection", "xss", "mybatis_mapper_call", "code_injection", "crlf", "open_redirect", "trust_boundary", "log_injection", "format_string", "nosql_injection", "prompt_injection"],
15395
15481
  http_path: ["path_traversal", "sql_injection", "ssrf", "mybatis_mapper_call", "open_redirect", "trust_boundary", "xss", "log_injection", "format_string", "prompt_injection"],
15396
- http_query: ["sql_injection", "command_injection", "xss", "ssrf", "mybatis_mapper_call", "code_injection", "crlf", "mass_assignment", "open_redirect", "trust_boundary", "deserialization", "log_injection", "format_string", "nosql_injection", "prompt_injection"],
15482
+ http_query: ["sql_injection", "command_injection", "xss", "ssrf", "mybatis_mapper_call", "code_injection", "crlf", "mass_assignment", "open_redirect", "trust_boundary", "deserialization", "xxe", "log_injection", "format_string", "nosql_injection", "prompt_injection"],
15397
15483
  io_input: ["command_injection", "path_traversal", "deserialization", "xxe", "code_injection", "xss", "ssrf", "log_injection", "format_string", "prompt_injection"],
15398
15484
  env_input: ["command_injection", "path_traversal"],
15399
15485
  db_input: ["xss", "sql_injection", "log_injection"],
@@ -23170,13 +23256,6 @@ class RustPlugin extends BaseLanguagePlugin {
23170
23256
  severity: "high",
23171
23257
  argPositions: [0]
23172
23258
  },
23173
- {
23174
- method: "format!",
23175
- type: "format_string",
23176
- cwe: "CWE-134",
23177
- severity: "medium",
23178
- argPositions: [0]
23179
- },
23180
23259
  {
23181
23260
  method: "from_raw_parts",
23182
23261
  type: "unsafe_memory",
@@ -26134,12 +26213,21 @@ function findCSharpRequestSources(sourceCode, language) {
26134
26213
  const requestReadRe = /\bRequest\s*\.\s*(?:Query|Form|Headers|Cookies|QueryString|RouteValues|Body|Files|Params)\b/;
26135
26214
  const consoleReadRe = /\bConsole\s*\.\s*ReadLine\s*\(/;
26136
26215
  const envReadRe = /\bEnvironment\s*\.\s*GetEnvironmentVariables?\s*(?:\(|\[)/;
26216
+ const formFileParams = new Set;
26217
+ const formFileDeclRe = /\bIFormFile\s+([A-Za-z_]\w*)/g;
26218
+ for (const line of lines) {
26219
+ const re = new RegExp(formFileDeclRe.source, "g");
26220
+ let d;
26221
+ while ((d = re.exec(line)) !== null)
26222
+ formFileParams.add(d[1]);
26223
+ }
26224
+ const formFileReadRe = formFileParams.size > 0 ? new RegExp(`\\b(?:${[...formFileParams].join("|")})\\s*\\.\\s*(?:FileName|ContentType)\\b`) : null;
26137
26225
  for (let i2 = 0;i2 < lines.length; i2++) {
26138
26226
  const m = assignRe.exec(lines[i2]);
26139
26227
  if (!m)
26140
26228
  continue;
26141
26229
  const [, varName, rhs] = m;
26142
- const type = requestReadRe.test(rhs) ? "http_param" : consoleReadRe.test(rhs) ? "io_input" : envReadRe.test(rhs) ? "env_input" : null;
26230
+ const type = requestReadRe.test(rhs) ? "http_param" : formFileReadRe?.test(rhs) ? "http_param" : consoleReadRe.test(rhs) ? "io_input" : envReadRe.test(rhs) ? "env_input" : null;
26143
26231
  if (!type)
26144
26232
  continue;
26145
26233
  const lineNumber = i2 + 1;
@@ -48210,14 +48298,14 @@ function toSpdx(deps, meta = {}) {
48210
48298
  relationships
48211
48299
  };
48212
48300
  }
48213
- // ../project-profile-detect/dist/index.js
48214
- import { relative as relative3 } from "path";
48301
+ // node_modules/@cognium/project-profile-detect/dist/index.js
48302
+ import { relative as relative2 } from "path";
48215
48303
 
48216
- // ../project-profile-detect/dist/walk.js
48304
+ // node_modules/@cognium/project-profile-detect/dist/walk.js
48217
48305
  import { readdir, readFile, stat } from "fs/promises";
48218
- import { join, relative as relative2 } from "path";
48306
+ import { join, relative } from "path";
48219
48307
 
48220
- // ../project-profile-detect/dist/maven-parse.js
48308
+ // node_modules/@cognium/project-profile-detect/dist/maven-parse.js
48221
48309
  var TAG = (name2) => new RegExp(`<${name2}\\b[^>]*>([\\s\\S]*?)<\\/${name2}>`, "i");
48222
48310
  var ALL_TAGS = (name2) => new RegExp(`<${name2}\\b[^>]*>([\\s\\S]*?)<\\/${name2}>`, "gi");
48223
48311
  function firstTag(xml, name2) {
@@ -48241,12 +48329,7 @@ var MAVEN_PLUGIN_MAP = {
48241
48329
  "exec-maven-plugin": "application",
48242
48330
  "maven-assembly-plugin": "application"
48243
48331
  };
48244
- var MAVEN_PUBLISH_PLUGIN_URLS = {
48245
- "central-publishing-maven-plugin": "https://central.sonatype.com/",
48246
- "nexus-staging-maven-plugin": "https://oss.sonatype.org/"
48247
- };
48248
48332
  function parseMavenPom(xml, moduleRoot, buildFile, directorySignals) {
48249
- const parentRef = extractParentRef(xml);
48250
48333
  const stripped = xml.replace(/<parent\b[\s\S]*?<\/parent>/i, "");
48251
48334
  const groupId = firstTag(stripped, "groupId");
48252
48335
  const artifactId = firstTag(stripped, "artifactId");
@@ -48255,15 +48338,10 @@ function parseMavenPom(xml, moduleRoot, buildFile, directorySignals) {
48255
48338
  const buildBlock = firstTag(xml, "build") ?? "";
48256
48339
  const pluginBlocks = allTags(buildBlock, "plugin");
48257
48340
  const plugins = new Set;
48258
- const publishUrls = new Set;
48259
48341
  for (const p of pluginBlocks) {
48260
48342
  const aid = firstTag(p, "artifactId");
48261
- if (!aid)
48262
- continue;
48263
- if (MAVEN_PLUGIN_MAP[aid])
48343
+ if (aid && MAVEN_PLUGIN_MAP[aid])
48264
48344
  plugins.add(MAVEN_PLUGIN_MAP[aid]);
48265
- if (MAVEN_PUBLISH_PLUGIN_URLS[aid])
48266
- publishUrls.add(MAVEN_PUBLISH_PLUGIN_URLS[aid]);
48267
48345
  }
48268
48346
  if (/<parent\b[\s\S]*?<artifactId>\s*spring-boot-starter-parent\s*<\/artifactId>/i.test(xml)) {
48269
48347
  plugins.add("spring-boot");
@@ -48276,8 +48354,7 @@ function parseMavenPom(xml, moduleRoot, buildFile, directorySignals) {
48276
48354
  plugins.add("maven-plugin");
48277
48355
  const distBlock = firstTag(xml, "distributionManagement") ?? "";
48278
48356
  const urls = [
48279
- ...allTags(distBlock, "url"),
48280
- ...publishUrls
48357
+ ...allTags(distBlock, "url")
48281
48358
  ].map((u) => u.trim()).filter(Boolean);
48282
48359
  const signals = {
48283
48360
  ...directorySignals,
@@ -48292,36 +48369,11 @@ function parseMavenPom(xml, moduleRoot, buildFile, directorySignals) {
48292
48369
  groupId,
48293
48370
  artifactId,
48294
48371
  version,
48295
- signals,
48296
- parentRef
48372
+ signals
48297
48373
  };
48298
48374
  }
48299
- function extractParentRef(xml) {
48300
- const block = TAG("parent").exec(xml);
48301
- if (!block)
48302
- return;
48303
- const inner = block[1];
48304
- const groupId = firstTag(inner, "groupId");
48305
- const artifactId = firstTag(inner, "artifactId");
48306
- const version = firstTag(inner, "version");
48307
- let relativePath;
48308
- let emptyRelativePath = false;
48309
- const selfClosing = /<relativePath\b[^>]*\/\s*>/i.test(inner);
48310
- if (selfClosing) {
48311
- emptyRelativePath = true;
48312
- } else {
48313
- const rp = firstTag(inner, "relativePath");
48314
- if (rp !== undefined) {
48315
- if (rp.length === 0)
48316
- emptyRelativePath = true;
48317
- else
48318
- relativePath = rp;
48319
- }
48320
- }
48321
- return { groupId, artifactId, version, relativePath, emptyRelativePath };
48322
- }
48323
48375
 
48324
- // ../project-profile-detect/dist/gradle-parse.js
48376
+ // node_modules/@cognium/project-profile-detect/dist/gradle-parse.js
48325
48377
  var GRADLE_PLUGIN_MAP = {
48326
48378
  "org.springframework.boot": "spring-boot",
48327
48379
  "io.spring.dependency-management": "spring-boot",
@@ -48386,71 +48438,7 @@ function parseGradleBuild(text, moduleRoot, buildFile, buildSystem, directorySig
48386
48438
  };
48387
48439
  }
48388
48440
 
48389
- // ../project-profile-detect/dist/maven-inherit.js
48390
- import { dirname as dirname2, isAbsolute, normalize, relative, resolve } from "path";
48391
- var MAX_DEPTH = 6;
48392
- var DEFAULT_RELATIVE_PATH = "../pom.xml";
48393
- function mergeMavenInheritance(modules, scanRoot) {
48394
- const normalizedScanRoot = normalize(scanRoot);
48395
- const byBuildFile = new Map;
48396
- for (const m of modules) {
48397
- if (m.buildSystem === "maven") {
48398
- byBuildFile.set(normalize(m.buildFile), m);
48399
- }
48400
- }
48401
- for (const child of modules) {
48402
- if (child.buildSystem !== "maven")
48403
- continue;
48404
- if (!child.parentRef)
48405
- continue;
48406
- const inheritedUrls = new Set;
48407
- const inheritedPlugins = new Set;
48408
- walkParents(child, byBuildFile, normalizedScanRoot, inheritedUrls, inheritedPlugins);
48409
- if (inheritedUrls.size === 0 && inheritedPlugins.size === 0)
48410
- continue;
48411
- const existingUrls = new Set(child.signals.distributionUrls);
48412
- for (const u of inheritedUrls) {
48413
- if (!existingUrls.has(u))
48414
- child.signals.distributionUrls.push(u);
48415
- }
48416
- const existingPlugins = new Set(child.signals.plugins);
48417
- for (const p of inheritedPlugins) {
48418
- if (!existingPlugins.has(p))
48419
- child.signals.plugins.push(p);
48420
- }
48421
- }
48422
- }
48423
- function walkParents(start2, byBuildFile, scanRoot, outUrls, outPlugins) {
48424
- const visited = new Set([normalize(start2.buildFile)]);
48425
- let current = start2;
48426
- for (let depth = 0;depth < MAX_DEPTH; depth++) {
48427
- const ref = current.parentRef;
48428
- if (!ref)
48429
- return;
48430
- if (ref.emptyRelativePath)
48431
- return;
48432
- const childDir = dirname2(current.buildFile);
48433
- const rel = ref.relativePath ?? DEFAULT_RELATIVE_PATH;
48434
- const candidateAbs = normalize(isAbsolute(rel) ? rel : resolve(childDir, rel));
48435
- const parentBuildFile = candidateAbs.endsWith("pom.xml") ? candidateAbs : normalize(resolve(candidateAbs, "pom.xml"));
48436
- const relToRoot = relative(scanRoot, parentBuildFile);
48437
- if (relToRoot.startsWith("..") || isAbsolute(relToRoot))
48438
- return;
48439
- if (visited.has(parentBuildFile))
48440
- return;
48441
- visited.add(parentBuildFile);
48442
- const parent = byBuildFile.get(parentBuildFile);
48443
- if (!parent)
48444
- return;
48445
- for (const u of parent.signals.distributionUrls)
48446
- outUrls.add(u);
48447
- for (const p of parent.signals.plugins)
48448
- outPlugins.add(p);
48449
- current = parent;
48450
- }
48451
- }
48452
-
48453
- // ../project-profile-detect/dist/walk.js
48441
+ // node_modules/@cognium/project-profile-detect/dist/walk.js
48454
48442
  var BUILD_FILES = ["pom.xml", "build.gradle", "build.gradle.kts"];
48455
48443
  var SKIP_DIRS = new Set([
48456
48444
  "node_modules",
@@ -48470,7 +48458,6 @@ var SKIP_DIRS = new Set([
48470
48458
  async function discoverBuildModules(scanRoot) {
48471
48459
  const modules = [];
48472
48460
  await walk(scanRoot, modules);
48473
- mergeMavenInheritance(modules, scanRoot);
48474
48461
  return modules;
48475
48462
  }
48476
48463
  async function walk(dir, out2) {
@@ -48612,7 +48599,7 @@ function ownerOf(file, modules) {
48612
48599
  return best;
48613
48600
  }
48614
48601
 
48615
- // ../project-profile-detect/dist/publication-detect.js
48602
+ // node_modules/@cognium/project-profile-detect/dist/publication-detect.js
48616
48603
  var PUBLIC_REGISTRY_HOSTS = new Set([
48617
48604
  "repo.maven.apache.org",
48618
48605
  "repo1.maven.org",
@@ -48637,7 +48624,7 @@ function isPubliclyPublished(urls) {
48637
48624
  return false;
48638
48625
  }
48639
48626
 
48640
- // ../project-profile-detect/dist/shape-resolve.js
48627
+ // node_modules/@cognium/project-profile-detect/dist/shape-resolve.js
48641
48628
  function resolveShape(mod) {
48642
48629
  const sig = mod.signals;
48643
48630
  const has = (tag) => sig.plugins.includes(tag);
@@ -48678,15 +48665,11 @@ function resolveShape(mod) {
48678
48665
  reasons.push(...libSignals, "no public-registry distribution (internal helper)");
48679
48666
  return { shape: "application", reasons };
48680
48667
  }
48681
- if (isPubliclyPublished(sig.distributionUrls)) {
48682
- reasons.push("public-registry distribution", "no application/server/plugin signals → implicit library");
48683
- return { shape: "library", reasons };
48684
- }
48685
48668
  reasons.push("no shape signals");
48686
48669
  return { shape: "unknown", reasons };
48687
48670
  }
48688
48671
 
48689
- // ../project-profile-detect/dist/env-resolve.js
48672
+ // node_modules/@cognium/project-profile-detect/dist/env-resolve.js
48690
48673
  var TEST_RE = /(?:^|\/)tests?\//;
48691
48674
  var SAMPLE_RE = /(?:^|\/)(?:samples?|examples?|demos?|fixtures?)\//;
48692
48675
  var BENCHMARK_RE = /(?:^|\/)benchmarks?\//;
@@ -48704,7 +48687,7 @@ function resolveEnv(absoluteFile) {
48704
48687
  return "dev";
48705
48688
  }
48706
48689
 
48707
- // ../project-profile-detect/dist/overrides.js
48690
+ // node_modules/@cognium/project-profile-detect/dist/overrides.js
48708
48691
  function compileGlob(glob) {
48709
48692
  let re = "";
48710
48693
  let i2 = 0;
@@ -48751,7 +48734,7 @@ function applyOverrides(relativePath, compiled) {
48751
48734
  return;
48752
48735
  }
48753
48736
 
48754
- // ../project-profile-detect/dist/index.js
48737
+ // node_modules/@cognium/project-profile-detect/dist/index.js
48755
48738
  async function detectProjectProfiles(scanRoot, options = {}) {
48756
48739
  const modules = await discoverBuildModules(scanRoot);
48757
48740
  const files = await enumerateScanFiles(scanRoot);
@@ -48769,7 +48752,7 @@ async function detectProjectProfiles(scanRoot, options = {}) {
48769
48752
  const profileByFile = new Map;
48770
48753
  const unknownFiles = [];
48771
48754
  for (const file of files) {
48772
- const rel = relative3(scanRoot, file);
48755
+ const rel = relative2(scanRoot, file);
48773
48756
  const ov = applyOverrides(rel, compiledOverrides);
48774
48757
  if (ov) {
48775
48758
  profileByFile.set(file, ov.profile);
@@ -48821,7 +48804,7 @@ var colors = {
48821
48804
  };
48822
48805
 
48823
48806
  // src/version.ts
48824
- var version = "4.9.10";
48807
+ var version = "4.9.11";
48825
48808
 
48826
48809
  // src/formatters.ts
48827
48810
  var LIBRARY_API_SURFACE_TAG2 = "library-api-surface:caller-responsibility";
@@ -49374,8 +49357,8 @@ function generateSarifResults(results, crossFileData) {
49374
49357
 
49375
49358
  // src/build-info.ts
49376
49359
  var buildInfo = {
49377
- gitSha: "132eaf6",
49378
- builtAt: "2026-09-02T06:21:26.855Z"
49360
+ gitSha: "6c811aa",
49361
+ builtAt: "2026-09-10T06:22:49.258Z"
49379
49362
  };
49380
49363
 
49381
49364
  // src/utils/args.ts
@@ -49663,7 +49646,7 @@ function applySuppressionsToResults(results, suppressions, basePath) {
49663
49646
  if (suppressions.length === 0)
49664
49647
  return results;
49665
49648
  return results.map((result) => {
49666
- const relativeFile = relative4(basePath, result.file) || result.file;
49649
+ const relativeFile = relative3(basePath, result.file) || result.file;
49667
49650
  const filteredVulns = result.vulnerabilities.filter((vuln) => {
49668
49651
  for (const supp of suppressions) {
49669
49652
  if (supp.pass !== vuln.type)
@@ -49719,6 +49702,22 @@ var LANG_MAP = {
49719
49702
  ".html": "html",
49720
49703
  ".htm": "html"
49721
49704
  };
49705
+ var VULN_SEVERITY_RANK = { critical: 3, high: 2, medium: 1, low: 0 };
49706
+ function dedupeVulnerabilities(vulns) {
49707
+ const best = new Map;
49708
+ const order = [];
49709
+ for (const v of vulns) {
49710
+ const key = `${v.type}:${v.line}`;
49711
+ const current = best.get(key);
49712
+ if (current === undefined) {
49713
+ best.set(key, v);
49714
+ order.push(key);
49715
+ } else if ((VULN_SEVERITY_RANK[v.severity] ?? -1) > (VULN_SEVERITY_RANK[current.severity] ?? -1)) {
49716
+ best.set(key, v);
49717
+ }
49718
+ }
49719
+ return order.map((k) => best.get(k));
49720
+ }
49722
49721
  function detectLanguage7(filePath) {
49723
49722
  const ext = extname(filePath).toLowerCase();
49724
49723
  return LANG_MAP[ext] || null;
@@ -49753,7 +49752,7 @@ async function collectFiles(targetPath, options = {}) {
49753
49752
  return files;
49754
49753
  }
49755
49754
  if (fileMatchesLanguage(targetPath, language)) {
49756
- const relativePath = basePath ? relative4(basePath, targetPath) : targetPath;
49755
+ const relativePath = basePath ? relative3(basePath, targetPath) : targetPath;
49757
49756
  if (includePatterns && includePatterns.length > 0) {
49758
49757
  if (!matchesAnyPattern(relativePath, includePatterns)) {
49759
49758
  return files;
@@ -49772,7 +49771,7 @@ async function collectFiles(targetPath, options = {}) {
49772
49771
  if (excludeTests && /^(test|tests|__tests__|spec|__mocks__)$/i.test(entry.name))
49773
49772
  continue;
49774
49773
  const fullPath = join2(targetPath, entry.name);
49775
- const relativePath = basePath ? relative4(basePath, fullPath) : fullPath;
49774
+ const relativePath = basePath ? relative3(basePath, fullPath) : fullPath;
49776
49775
  if (excludePatterns && entry.isDirectory()) {
49777
49776
  const dirPattern = relativePath + "/";
49778
49777
  if (excludePatterns.some((p) => matchesGlob(dirPattern, p) || matchesGlob(relativePath, p))) {
@@ -49813,7 +49812,7 @@ async function scanFile(filePath, language, analyzeOpts) {
49813
49812
  ...finding.tags && finding.tags.length > 0 ? { tags: [...finding.tags] } : {}
49814
49813
  });
49815
49814
  }
49816
- return { file: filePath, vulnerabilities };
49815
+ return { file: filePath, vulnerabilities: dedupeVulnerabilities(vulnerabilities) };
49817
49816
  } catch (error) {
49818
49817
  return {
49819
49818
  file: filePath,
@@ -49856,7 +49855,7 @@ async function scanProject(files, language, analyzeOpts, crossFileBudgetMs) {
49856
49855
  ...finding.tags && finding.tags.length > 0 ? { tags: [...finding.tags] } : {}
49857
49856
  });
49858
49857
  }
49859
- return { file, vulnerabilities };
49858
+ return { file, vulnerabilities: dedupeVulnerabilities(vulnerabilities) };
49860
49859
  });
49861
49860
  return {
49862
49861
  results,
@@ -49870,14 +49869,14 @@ async function scanProject(files, language, analyzeOpts, crossFileBudgetMs) {
49870
49869
  async function initWasm(spin) {
49871
49870
  const isStandalone = import.meta.url.includes("/$bunfs/");
49872
49871
  if (isStandalone) {
49873
- const { dirname: dirname4, join: join3 } = await import("path");
49874
- const binaryDir = dirname4(process.execPath);
49872
+ const { dirname: dirname3, join: join3 } = await import("path");
49873
+ const binaryDir = dirname3(process.execPath);
49875
49874
  const cwd = process.cwd();
49876
49875
  let scriptDir = null;
49877
49876
  if (!import.meta.url.includes("/$bunfs/")) {
49878
49877
  try {
49879
49878
  const { fileURLToPath } = await import("url");
49880
- scriptDir = dirname4(fileURLToPath(import.meta.url));
49879
+ scriptDir = dirname3(fileURLToPath(import.meta.url));
49881
49880
  } catch {}
49882
49881
  }
49883
49882
  const wasmLocations = [
@@ -49932,7 +49931,7 @@ Please ensure the wasm/ directory is located next to the binary or in your curre
49932
49931
  } else {
49933
49932
  const require2 = createRequire2(import.meta.url);
49934
49933
  const circleIrPkg = require2.resolve("circle-ir/package.json");
49935
- const wasmBasePath = join2(dirname3(circleIrPkg), "dist", "wasm") + "/";
49934
+ const wasmBasePath = join2(dirname2(circleIrPkg), "dist", "wasm") + "/";
49936
49935
  await initAnalyzer({
49937
49936
  wasmPath: wasmBasePath + "web-tree-sitter.wasm",
49938
49937
  languagePaths: {
@@ -49963,7 +49962,7 @@ function buildProfileSummary(scanRoot, modules, resolvedProfiles) {
49963
49962
  return {
49964
49963
  scanRoot,
49965
49964
  modules: modules.map((m) => ({
49966
- root: relative4(scanRoot, m.module.root) || ".",
49965
+ root: relative3(scanRoot, m.module.root) || ".",
49967
49966
  profile: m.profile,
49968
49967
  reasons: m.reasons,
49969
49968
  buildSystem: m.module.buildSystem
@@ -49992,9 +49991,9 @@ function printProfileExplain(scanRoot, detection) {
49992
49991
  out2.push(" (no pom.xml, build.gradle, or build.gradle.kts found)");
49993
49992
  } else {
49994
49993
  for (const r of detection.modules) {
49995
- const rel = relative4(scanRoot, r.module.root) || ".";
49994
+ const rel = relative3(scanRoot, r.module.root) || ".";
49996
49995
  out2.push(` ${colors.cyan(rel || ".")} → ${colors.bold(r.profile)}`);
49997
- out2.push(` build: ${r.module.buildSystem} (${relative4(scanRoot, r.module.buildFile)})`);
49996
+ out2.push(` build: ${r.module.buildSystem} (${relative3(scanRoot, r.module.buildFile)})`);
49998
49997
  if (r.module.artifactId) {
49999
49998
  out2.push(` coords: ${r.module.groupId ?? "?"}:${r.module.artifactId}:${r.module.version ?? "?"}`);
50000
49999
  }
@@ -50039,7 +50038,7 @@ async function runScan(targetPath, options) {
50039
50038
  await initWasm(spin);
50040
50039
  if (spin)
50041
50040
  spin.text = "Collecting files...";
50042
- const absPath = resolve2(targetPath);
50041
+ const absPath = resolve(targetPath);
50043
50042
  if (!existsSync(absPath)) {
50044
50043
  if (spin)
50045
50044
  spin.fail(`Path not found: ${absPath}`);
@@ -50103,7 +50102,7 @@ async function runScan(targetPath, options) {
50103
50102
  results = [];
50104
50103
  let processed = 0;
50105
50104
  const formatCurrentFile = (file) => {
50106
- const rel = relative4(absPath, file) || file;
50105
+ const rel = relative3(absPath, file) || file;
50107
50106
  return rel.length > 80 ? `...${rel.slice(-77)}` : rel;
50108
50107
  };
50109
50108
  const concurrency = options.threads;
@@ -50279,7 +50278,7 @@ async function runMetrics(targetPath, options) {
50279
50278
  await initWasm(spin);
50280
50279
  if (spin)
50281
50280
  spin.text = "Collecting files...";
50282
- const absPath = resolve2(targetPath);
50281
+ const absPath = resolve(targetPath);
50283
50282
  if (!existsSync(absPath)) {
50284
50283
  if (spin)
50285
50284
  spin.fail(`Path not found: ${absPath}`);
@@ -50307,7 +50306,7 @@ async function runMetrics(targetPath, options) {
50307
50306
  continue;
50308
50307
  }
50309
50308
  if (spin) {
50310
- const rel = relative4(absPath, file) || file;
50309
+ const rel = relative3(absPath, file) || file;
50311
50310
  const maxLen = 80;
50312
50311
  const label = rel.length > maxLen ? `...${rel.slice(-(maxLen - 3))}` : rel;
50313
50312
  spin.text = `Analyzing ${label}... (${processed}/${totalFiles})`;
@@ -50352,7 +50351,7 @@ async function runMetrics(targetPath, options) {
50352
50351
  } else {
50353
50352
  const lines = [];
50354
50353
  for (const fm of filtered) {
50355
- const rel = relative4(absPath, fm.file) || fm.file;
50354
+ const rel = relative3(absPath, fm.file) || fm.file;
50356
50355
  lines.push(rel);
50357
50356
  const byCategory = new Map;
50358
50357
  for (const m of fm.metrics) {
@@ -50580,7 +50579,7 @@ async function collectManifestFiles(targetPath) {
50580
50579
  return found;
50581
50580
  }
50582
50581
  async function runSbom(targetPath, options) {
50583
- const absPath = resolve2(targetPath);
50582
+ const absPath = resolve(targetPath);
50584
50583
  if (!existsSync(absPath)) {
50585
50584
  console.error(colors.red(`Error: path not found: ${targetPath}`));
50586
50585
  process.exit(2);
@@ -50594,9 +50593,9 @@ async function runSbom(targetPath, options) {
50594
50593
  for (const m of manifests) {
50595
50594
  const superseded = SBOM_SUPERSEDES[basename(m)];
50596
50595
  if (superseded)
50597
- supersededInDir.add(`${dirname3(m)}\x00${superseded}`);
50596
+ supersededInDir.add(`${dirname2(m)}\x00${superseded}`);
50598
50597
  }
50599
- const effective = manifests.filter((m) => !supersededInDir.has(`${dirname3(m)}\x00${basename(m)}`));
50598
+ const effective = manifests.filter((m) => !supersededInDir.has(`${dirname2(m)}\x00${basename(m)}`));
50600
50599
  let projectName = options.name;
50601
50600
  let projectLicense;
50602
50601
  {
@@ -50756,6 +50755,7 @@ export {
50756
50755
  loadConfig,
50757
50756
  isTestFile2 as isTestFile,
50758
50757
  detectLanguage7 as detectLanguage,
50758
+ dedupeVulnerabilities,
50759
50759
  convertConfigToPassOptions,
50760
50760
  applySuppressionsToResults,
50761
50761
  PASS_REGISTRY
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cognium-dev",
3
- "version": "4.9.10",
3
+ "version": "4.9.11",
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",
@@ -14,7 +14,7 @@
14
14
  "test": "bun test",
15
15
  "clean": "rm -rf dist cognium-dev cognium-dev-* *.bun-build wasm",
16
16
  "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",
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 \u2014 use \\`npm version patch|minor|major\\` instead.\\n */\\nexport const version = \\x27' + v + '\\x27;\\n')\" && git add src/version.ts",
18
18
  "dogfood": "bun run src/cli.ts scan src/ -q",
19
19
  "prepublishOnly": "bun run build"
20
20
  },
@@ -65,8 +65,8 @@
65
65
  "registry": "https://registry.npmjs.org/"
66
66
  },
67
67
  "dependencies": {
68
- "@cognium/project-profile-detect": "1.1.0",
69
- "circle-ir": "4.9.10"
68
+ "@cognium/project-profile-detect": "1.1.1",
69
+ "circle-ir": "4.9.11"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/node": "^25.5.0",