cognium-dev 3.182.0 → 3.186.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 +199 -3
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -10691,6 +10691,19 @@ var DEFAULT_SOURCES = [
10691
10691
  { method: "getMap", class: "Metadata", type: "http_header", severity: "high", return_tainted: true, languages: ["javascript", "typescript"] },
10692
10692
  { method: "FromIncomingContext", class: "metadata", type: "http_header", severity: "high", return_tainted: true, languages: ["go"] },
10693
10693
  { method: "get", class: "Metadata", type: "http_header", severity: "high", return_tainted: true, languages: ["java"] },
10694
+ { method: "receive_text", class: "WebSocket", type: "network_input", severity: "high", return_tainted: true, languages: ["python"] },
10695
+ { method: "receive_bytes", class: "WebSocket", type: "network_input", severity: "high", return_tainted: true, languages: ["python"] },
10696
+ { method: "receive_json", class: "WebSocket", type: "http_body", severity: "high", return_tainted: true, languages: ["python"] },
10697
+ { method: "receive", class: "WebSocket", type: "network_input", severity: "high", return_tainted: true, languages: ["python"] },
10698
+ { method: "receive_json", type: "http_body", severity: "high", return_tainted: true, languages: ["python"] },
10699
+ { method: "receive_text", type: "network_input", severity: "high", return_tainted: true, languages: ["python"] },
10700
+ { method: "receive_bytes", type: "network_input", severity: "high", return_tainted: true, languages: ["python"] },
10701
+ { method: "ReadMessage", class: "Conn", type: "network_input", severity: "high", return_tainted: true, languages: ["go"] },
10702
+ { method: "NextReader", class: "Conn", type: "network_input", severity: "high", return_tainted: true, languages: ["go"] },
10703
+ { method: "Read", class: "Conn", type: "network_input", severity: "high", return_tainted: true, languages: ["go"] },
10704
+ { annotation: "OnMessage", type: "network_input", severity: "high", param_tainted: true, languages: ["java"] },
10705
+ { annotation: "MessageMapping", type: "http_body", severity: "high", param_tainted: true, languages: ["java"] },
10706
+ { annotation: "SubscribeMapping", type: "http_body", severity: "high", param_tainted: true, languages: ["java"] },
10694
10707
  { method: "get", class: "Redis", type: "db_input", severity: "medium", return_tainted: true, languages: ["python"] },
10695
10708
  { method: "hget", class: "Redis", type: "db_input", severity: "medium", return_tainted: true, languages: ["python"] },
10696
10709
  { method: "mget", class: "Redis", type: "db_input", severity: "medium", return_tainted: true, languages: ["python"] },
@@ -11955,6 +11968,36 @@ var DEFAULT_SANITIZERS = [
11955
11968
  { method: "escape", class: "mongo", removes: ["nosql_injection"] },
11956
11969
  { method: "quote", class: "shell", removes: ["command_injection"] },
11957
11970
  { method: "escape", class: "shell-escape", removes: ["command_injection"] },
11971
+ { method: "encode", class: "he", removes: ["xss", "external_taint_escape"] },
11972
+ { method: "escape", class: "he", removes: ["xss", "external_taint_escape"] },
11973
+ { method: "sanitizeHtml", removes: ["xss", "external_taint_escape"] },
11974
+ { method: "xss", removes: ["xss", "external_taint_escape"] },
11975
+ { method: "filterXSS", removes: ["xss", "external_taint_escape"] },
11976
+ { method: "escapeHtml", removes: ["xss", "external_taint_escape"] },
11977
+ { method: "escapeHTML", removes: ["xss", "external_taint_escape"] },
11978
+ { method: "encode", class: "entities", removes: ["xss", "external_taint_escape"] },
11979
+ { method: "escape", class: "entities", removes: ["xss", "external_taint_escape"] },
11980
+ { method: "inHTMLData", class: "xssFilters", removes: ["xss", "external_taint_escape"] },
11981
+ { method: "inHTMLComment", class: "xssFilters", removes: ["xss", "external_taint_escape"] },
11982
+ { method: "uriInHTMLData", class: "xssFilters", removes: ["xss", "external_taint_escape"] },
11983
+ { method: "escape", class: "SqlString", removes: ["sql_injection", "external_taint_escape"] },
11984
+ { method: "escapeId", class: "SqlString", removes: ["sql_injection", "external_taint_escape"] },
11985
+ { method: "format", class: "SqlString", removes: ["sql_injection", "external_taint_escape"] },
11986
+ { method: "format", class: "pgFormat", removes: ["sql_injection", "external_taint_escape"] },
11987
+ { method: "ident", class: "pgFormat", removes: ["sql_injection", "external_taint_escape"] },
11988
+ { method: "literal", class: "pgFormat", removes: ["sql_injection", "external_taint_escape"] },
11989
+ { method: "randomUUID", class: "crypto", removes: ["sql_injection", "nosql_injection", "command_injection", "path_traversal", "code_injection", "xss"] },
11990
+ { method: "randomUUID", removes: ["sql_injection", "nosql_injection", "command_injection", "path_traversal", "code_injection", "xss"] },
11991
+ { method: "toString", class: "URLSearchParams", removes: ["ssrf", "open_redirect", "xss"] },
11992
+ { method: "QuoteMeta", class: "regexp", removes: ["redos", "code_injection", "external_taint_escape"] },
11993
+ { method: "Sanitize", class: "bluemonday", removes: ["xss", "external_taint_escape"] },
11994
+ { method: "Sanitize", class: "Policy", removes: ["xss", "external_taint_escape"] },
11995
+ { method: "Sanitize", removes: ["xss", "external_taint_escape"] },
11996
+ { method: "SanitizeBytes", class: "bluemonday", removes: ["xss", "external_taint_escape"] },
11997
+ { method: "SanitizeBytes", class: "Policy", removes: ["xss", "external_taint_escape"] },
11998
+ { method: "SanitizeBytes", removes: ["xss", "external_taint_escape"] },
11999
+ { method: "ParseIP", class: "net", removes: ["ssrf", "command_injection", "path_traversal", "external_taint_escape"] },
12000
+ { method: "Named", class: "sql", removes: ["sql_injection", "external_taint_escape"] },
11958
12001
  { method: "escape", class: "markupsafe", removes: ["xss"] },
11959
12002
  { method: "escape", class: "html", removes: ["xss"] },
11960
12003
  { method: "escape", class: "cgi", removes: ["xss"] },
@@ -11982,6 +12025,26 @@ var DEFAULT_SANITIZERS = [
11982
12025
  { method: "resolve", class: "Path", removes: ["path_traversal"] },
11983
12026
  { method: "int", removes: ["sql_injection", "command_injection", "xss"] },
11984
12027
  { method: "float", removes: ["sql_injection", "command_injection"] },
12028
+ { method: "quote", class: "urllib.parse", removes: ["ssrf", "open_redirect", "xss", "path_traversal"] },
12029
+ { method: "quote_plus", class: "urllib.parse", removes: ["ssrf", "open_redirect", "xss", "path_traversal"] },
12030
+ { method: "urlencode", class: "urllib.parse", removes: ["ssrf", "open_redirect", "xss"] },
12031
+ { method: "quote_plus", removes: ["ssrf", "open_redirect", "xss", "path_traversal"] },
12032
+ { method: "urlencode", removes: ["ssrf", "open_redirect", "xss"] },
12033
+ { method: "linkify", class: "bleach", removes: ["xss"] },
12034
+ { method: "linkify", removes: ["xss"] },
12035
+ { method: "escape", class: "django.utils.html", removes: ["xss"] },
12036
+ { method: "strip_tags", class: "django.utils.html", removes: ["xss"] },
12037
+ { method: "escape", class: "jinja2", removes: ["xss"] },
12038
+ { method: "escape", class: "flask", removes: ["xss"] },
12039
+ { method: "escape", class: "saxutils", removes: ["xss"] },
12040
+ { method: "escape", class: "xml.sax.saxutils", removes: ["xss"] },
12041
+ { method: "quoteattr", class: "saxutils", removes: ["xss"] },
12042
+ { method: "quoteattr", class: "xml.sax.saxutils", removes: ["xss"] },
12043
+ { method: "escape", class: "re", removes: ["redos", "code_injection"] },
12044
+ { method: "bindparams", removes: ["sql_injection"] },
12045
+ { method: "Identifier", class: "sql", removes: ["sql_injection"] },
12046
+ { method: "Literal", class: "sql", removes: ["sql_injection"] },
12047
+ { method: "Placeholder", class: "sql", removes: ["sql_injection"] },
11985
12048
  { method: "query!", removes: ["sql_injection"] },
11986
12049
  { method: "query_as!", removes: ["sql_injection"] },
11987
12050
  { method: "query_scalar!", removes: ["sql_injection"] },
@@ -13905,7 +13968,13 @@ function matchesSanitizerPattern(call, pattern) {
13905
13968
  return false;
13906
13969
  }
13907
13970
  if (pattern.class) {
13908
- if (!call.receiver || !receiverMightBeClass(call.receiver, pattern.class)) {
13971
+ if (!call.receiver) {
13972
+ const target = call.resolution?.target;
13973
+ const expectedTail = `${pattern.class}.${pattern.method}`;
13974
+ if (target && (target === expectedTail || target.endsWith("." + expectedTail))) {} else {
13975
+ return false;
13976
+ }
13977
+ } else if (!receiverMightBeClass(call.receiver, pattern.class)) {
13909
13978
  return false;
13910
13979
  }
13911
13980
  }
@@ -24688,7 +24757,10 @@ var PYTHON_TAINTED_PATTERNS2 = [
24688
24757
  { pattern: /\bget_query_parameter\s*\(/, type: "http_param" },
24689
24758
  { pattern: /\bget_header_value\s*\(/, type: "http_header" },
24690
24759
  { pattern: /\bget_cookie_value\s*\(/, type: "http_cookie" },
24691
- { pattern: /\binput\s*\(/, type: "io_input" }
24760
+ { pattern: /\binput\s*\(/, type: "io_input" },
24761
+ { pattern: /\.receive_text\s*\(/, type: "network_input" },
24762
+ { pattern: /\.receive_bytes\s*\(/, type: "network_input" },
24763
+ { pattern: /\.receive_json\s*\(/, type: "http_body" }
24692
24764
  ];
24693
24765
 
24694
24766
  class LanguageSourcesPass {
@@ -25332,6 +25404,36 @@ function findJavaScriptAssignmentSources(sourceCode, language) {
25332
25404
  }
25333
25405
  }
25334
25406
  }
25407
+ sources.push(...findJavaScriptCallbackParamSources(sourceCode));
25408
+ return sources;
25409
+ }
25410
+ function findJavaScriptCallbackParamSources(sourceCode) {
25411
+ const sources = [];
25412
+ const CB_EVENT_RE = /\.on\s*\(\s*['"](?:message|text|binary)['"]\s*,\s*(?:async\s+)?(?:function\s*\*?\s*(?:\w+\s*)?\(\s*(\w+)|\(\s*(\w+)\s*(?:[,):]|$)|(\w+)\s*=>)/;
25413
+ const lines = sourceCode.split(`
25414
+ `);
25415
+ for (let i2 = 0;i2 < lines.length; i2++) {
25416
+ const line = lines[i2];
25417
+ const trimmed = line.trimStart();
25418
+ if (trimmed.startsWith("//") || trimmed.startsWith("*"))
25419
+ continue;
25420
+ const m = line.match(CB_EVENT_RE);
25421
+ if (!m)
25422
+ continue;
25423
+ const paramName = m[1] ?? m[2] ?? m[3];
25424
+ if (!paramName)
25425
+ continue;
25426
+ if (paramName === "err" || paramName === "error")
25427
+ continue;
25428
+ sources.push({
25429
+ type: "network_input",
25430
+ location: `WebSocket .on(...) callback param '${paramName}' at line ${i2 + 1}`,
25431
+ severity: "high",
25432
+ line: i2 + 1,
25433
+ confidence: 0.95,
25434
+ variable: paramName
25435
+ });
25436
+ }
25335
25437
  return sources;
25336
25438
  }
25337
25439
  function findPythonAssignmentSources(sourceCode, language) {
@@ -25664,6 +25766,16 @@ function buildJavaScriptTaintedVars(sourceCode, language) {
25664
25766
  const tainted = new Map;
25665
25767
  const lines = sourceCode.split(`
25666
25768
  `);
25769
+ const CB_EVENT_RE = /\.on\s*\(\s*['"](?:message|text|binary)['"]\s*,\s*(?:async\s+)?(?:function\s*\*?\s*(?:\w+\s*)?\(\s*(\w+)|\(\s*(\w+)\s*(?:[,):]|$)|(\w+)\s*=>)/;
25770
+ for (let i2 = 0;i2 < lines.length; i2++) {
25771
+ const m = lines[i2].match(CB_EVENT_RE);
25772
+ if (!m)
25773
+ continue;
25774
+ const paramName = m[1] ?? m[2] ?? m[3];
25775
+ if (!paramName || paramName === "err" || paramName === "error")
25776
+ continue;
25777
+ tainted.set(paramName, i2 + 1);
25778
+ }
25667
25779
  for (let i2 = 0;i2 < lines.length; i2++) {
25668
25780
  const line = lines[i2];
25669
25781
  const trimmed = line.trimStart();
@@ -25870,6 +25982,90 @@ function findBashTaintSources(sourceCode, dfg) {
25870
25982
  });
25871
25983
  }
25872
25984
  }
25985
+ const readMatch = /^read\s*\(/.test(trimmed) ? null : trimmed.match(/^read\b([^#(]*)$/);
25986
+ if (readMatch) {
25987
+ const argStr = readMatch[1].trim();
25988
+ const noRedirect = argStr.replace(/\s*<[^<].*$/, "").trim();
25989
+ const tokens = noRedirect.split(/\s+/);
25990
+ const varNames = [];
25991
+ for (let ti = 0;ti < tokens.length; ti++) {
25992
+ const tok = tokens[ti];
25993
+ if (!tok)
25994
+ continue;
25995
+ if (tok.startsWith("-")) {
25996
+ if (/^-[antpidu]$|^-N$/.test(tok))
25997
+ ti++;
25998
+ continue;
25999
+ }
26000
+ if (/^[A-Za-z_][\w]*$/.test(tok))
26001
+ varNames.push(tok);
26002
+ }
26003
+ if (varNames.length === 0)
26004
+ varNames.push("REPLY");
26005
+ for (const v of varNames) {
26006
+ const already = sources.some((s) => s.line === lineNumber && s.variable === v);
26007
+ if (already)
26008
+ continue;
26009
+ sources.push({
26010
+ type: "io_input",
26011
+ location: `read → $${v} (stdin)`,
26012
+ severity: "high",
26013
+ line: lineNumber,
26014
+ confidence: 0.9,
26015
+ variable: v
26016
+ });
26017
+ }
26018
+ }
26019
+ const mapfileMatch = /^(?:mapfile|readarray)\s*\(/.test(trimmed) ? null : trimmed.match(/^(?:mapfile|readarray)\b([^#(]*)$/);
26020
+ if (mapfileMatch) {
26021
+ const argStr = mapfileMatch[1].trim();
26022
+ const tokens = argStr.split(/\s+/);
26023
+ const varNames = [];
26024
+ for (let ti = 0;ti < tokens.length; ti++) {
26025
+ const tok = tokens[ti];
26026
+ if (!tok)
26027
+ continue;
26028
+ if (tok.startsWith("-")) {
26029
+ if (/^-[cCnOsud]$/.test(tok))
26030
+ ti++;
26031
+ continue;
26032
+ }
26033
+ if (/^[A-Za-z_][\w]*$/.test(tok))
26034
+ varNames.push(tok);
26035
+ }
26036
+ if (varNames.length === 0)
26037
+ varNames.push("MAPFILE");
26038
+ for (const v of varNames) {
26039
+ const already = sources.some((s) => s.line === lineNumber && s.variable === v);
26040
+ if (already)
26041
+ continue;
26042
+ sources.push({
26043
+ type: "io_input",
26044
+ location: `mapfile → $${v} (stdin array)`,
26045
+ severity: "high",
26046
+ line: lineNumber,
26047
+ confidence: 0.9,
26048
+ variable: v
26049
+ });
26050
+ }
26051
+ }
26052
+ const getoptsMatch = trimmed.match(/\bgetopts\s+["'][^"']+["']\s+(\w+)/);
26053
+ if (getoptsMatch) {
26054
+ const flagVar = getoptsMatch[1];
26055
+ for (const v of [flagVar, "OPTARG"]) {
26056
+ const already = sources.some((s) => s.line === lineNumber && s.variable === v);
26057
+ if (already)
26058
+ continue;
26059
+ sources.push({
26060
+ type: "io_input",
26061
+ location: `getopts → $${v} (CLI arg)`,
26062
+ severity: "high",
26063
+ line: lineNumber,
26064
+ confidence: 0.9,
26065
+ variable: v
26066
+ });
26067
+ }
26068
+ }
25873
26069
  const envRe = /\$([A-Z][A-Z0-9_]{2,})|\$\{([A-Z][A-Z0-9_]{2,})\}/g;
25874
26070
  let em;
25875
26071
  while ((em = envRe.exec(line)) !== null) {
@@ -45650,7 +45846,7 @@ var colors = {
45650
45846
  };
45651
45847
 
45652
45848
  // src/version.ts
45653
- var version = "3.182.0";
45849
+ var version = "3.186.0";
45654
45850
 
45655
45851
  // src/formatters.ts
45656
45852
  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.182.0",
3
+ "version": "3.186.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.182.0"
69
+ "circle-ir": "^3.186.0"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/node": "^25.5.0",