cognium-dev 3.39.0 → 3.41.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 +63 -21
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -10475,13 +10475,13 @@ var DEFAULT_SINKS = [
10475
10475
  { method: "readObject", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [] },
10476
10476
  { method: "readUnshared", class: "ObjectInputStream", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [] },
10477
10477
  { method: "fromXML", class: "XStream", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
10478
- { method: "readValue", class: "ObjectMapper", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0] },
10479
- { method: "load", class: "Yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
10478
+ { method: "readValue", class: "ObjectMapper", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0], safe_if_class_literal_at: 1 },
10479
+ { method: "load", class: "Yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0], safe_if_class_literal_at: 1 },
10480
10480
  { method: "loadAll", class: "Yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
10481
- { method: "loadAs", class: "Yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
10482
- { method: "parseObject", class: "JSON", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0] },
10483
- { method: "parseObject", class: "JSONObject", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0] },
10484
- { method: "fromJson", class: "Gson", type: "deserialization", cwe: "CWE-502", severity: "medium", arg_positions: [0] },
10481
+ { method: "loadAs", class: "Yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0], safe_if_class_literal_at: 1 },
10482
+ { method: "parseObject", class: "JSON", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0], safe_if_class_literal_at: 1 },
10483
+ { method: "parseObject", class: "JSONObject", type: "deserialization", cwe: "CWE-502", severity: "high", arg_positions: [0], safe_if_class_literal_at: 1 },
10484
+ { method: "fromJson", class: "Gson", type: "deserialization", cwe: "CWE-502", severity: "medium", arg_positions: [0], safe_if_class_literal_at: 1 },
10485
10485
  { method: "readObject", class: "XMLDecoder", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [] },
10486
10486
  { method: "ObjectInputStream", class: "constructor", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
10487
10487
  { method: "search", class: "DirContext", type: "ldap_injection", cwe: "CWE-90", severity: "high", arg_positions: [0, 1] },
@@ -10690,11 +10690,11 @@ var DEFAULT_SINKS = [
10690
10690
  { method: "exec", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0], languages: ["python"] },
10691
10691
  { method: "compile", type: "code_injection", cwe: "CWE-94", severity: "high", arg_positions: [0], languages: ["python"] },
10692
10692
  { method: "__import__", type: "code_injection", cwe: "CWE-94", severity: "high", arg_positions: [0], languages: ["python"] },
10693
- { method: "loads", class: "pickle", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
10694
- { method: "load", class: "pickle", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
10695
- { method: "loads", class: "marshal", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
10696
- { method: "load", class: "yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
10697
- { method: "loads", class: "yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0] },
10693
+ { method: "loads", class: "pickle", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0], languages: ["python"] },
10694
+ { method: "load", class: "pickle", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0], languages: ["python"] },
10695
+ { method: "loads", class: "marshal", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0], languages: ["python"] },
10696
+ { method: "load", class: "yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0], languages: ["python"] },
10697
+ { method: "loads", class: "yaml", type: "deserialization", cwe: "CWE-502", severity: "critical", arg_positions: [0], languages: ["python"] },
10698
10698
  { method: "execute", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["python"] },
10699
10699
  { method: "executemany", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["python"] },
10700
10700
  { method: "raw", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["python"] },
@@ -11092,13 +11092,29 @@ var PYTHON_TAINTED_PATTERNS = [
11092
11092
  { pattern: /\brequest\.query_params\b/, sourceType: "http_param" },
11093
11093
  { pattern: /\brequest\.path_params\b/, sourceType: "http_param" }
11094
11094
  ];
11095
- function analyzeTaint(calls, types, config = getDefaultConfig(), typeHierarchy, language) {
11096
- const sources = findSources(calls, types, config.sources);
11097
- const sinks = findSinks(calls, config.sinks, typeHierarchy, language);
11095
+ function analyzeTaint(calls, types, config = getDefaultConfig(), typeHierarchy, language, code) {
11096
+ const sourceLines = code !== undefined ? code.split(`
11097
+ `) : undefined;
11098
+ const sources = findSources(calls, types, config.sources, sourceLines);
11099
+ const sinks = findSinks(calls, config.sinks, typeHierarchy, language, sourceLines);
11098
11100
  const sanitizers = findSanitizers(calls, types, config.sanitizers);
11099
11101
  return { sources, sinks, sanitizers };
11100
11102
  }
11101
- function findSources(calls, types, patterns) {
11103
+ function attachSourceLineCode(sources, sinks, code) {
11104
+ const lines = code.split(`
11105
+ `);
11106
+ for (const s of sources) {
11107
+ if (s.code === undefined) {
11108
+ s.code = lines[s.line - 1]?.trim();
11109
+ }
11110
+ }
11111
+ for (const s of sinks) {
11112
+ if (s.code === undefined) {
11113
+ s.code = lines[s.line - 1]?.trim();
11114
+ }
11115
+ }
11116
+ }
11117
+ function findSources(calls, types, patterns, sourceLines) {
11102
11118
  const sources = [];
11103
11119
  for (const call of calls) {
11104
11120
  for (const pattern of patterns) {
@@ -11245,7 +11261,13 @@ function findSources(calls, types, patterns) {
11245
11261
  sourceMap.set(key, source);
11246
11262
  }
11247
11263
  }
11248
- return Array.from(sourceMap.values());
11264
+ const result = Array.from(sourceMap.values());
11265
+ if (sourceLines) {
11266
+ for (const s of result) {
11267
+ s.code = sourceLines[s.line - 1]?.trim();
11268
+ }
11269
+ }
11270
+ return result;
11249
11271
  }
11250
11272
  function isInterproceduralTaintableType(typeName) {
11251
11273
  const baseType = typeName.split("<")[0].trim();
@@ -11341,7 +11363,17 @@ function isParameterizedQueryCall(call, pattern) {
11341
11363
  }
11342
11364
  return false;
11343
11365
  }
11344
- function findSinks(calls, patterns, typeHierarchy, language) {
11366
+ var CLASS_LITERAL_RE = /^(?:[A-Za-z_][\w]*\.)*[A-Z][\w]*(?:\[\])*\.class$/;
11367
+ function argIsClassLiteral(call, position) {
11368
+ const arg = call.arguments.find((a) => a.position === position);
11369
+ if (!arg)
11370
+ return false;
11371
+ const expr = (arg.literal ?? arg.expression ?? "").trim();
11372
+ if (!expr)
11373
+ return false;
11374
+ return CLASS_LITERAL_RE.test(expr);
11375
+ }
11376
+ function findSinks(calls, patterns, typeHierarchy, language, sourceLines) {
11345
11377
  const sinkMap = new Map;
11346
11378
  for (const call of calls) {
11347
11379
  for (const pattern of patterns) {
@@ -11349,6 +11381,9 @@ function findSinks(calls, patterns, typeHierarchy, language) {
11349
11381
  if (isParameterizedQueryCall(call, pattern)) {
11350
11382
  continue;
11351
11383
  }
11384
+ if (pattern.safe_if_class_literal_at !== undefined && argIsClassLiteral(call, pattern.safe_if_class_literal_at)) {
11385
+ continue;
11386
+ }
11352
11387
  const location = formatCallLocation(call);
11353
11388
  const key = `${location}:${call.location.line}:${pattern.cwe}`;
11354
11389
  const confidence = calculateSinkConfidence(call, pattern);
@@ -11367,7 +11402,13 @@ function findSinks(calls, patterns, typeHierarchy, language) {
11367
11402
  }
11368
11403
  }
11369
11404
  }
11370
- return Array.from(sinkMap.values());
11405
+ const result = Array.from(sinkMap.values());
11406
+ if (sourceLines) {
11407
+ for (const s of result) {
11408
+ s.code = sourceLines[s.line - 1]?.trim();
11409
+ }
11410
+ }
11411
+ return result;
11371
11412
  }
11372
11413
  function matchesSourcePattern(call, pattern) {
11373
11414
  if (pattern.method) {
@@ -19694,7 +19735,7 @@ class TaintMatcherPass {
19694
19735
  name = "taint-matcher";
19695
19736
  category = "security";
19696
19737
  run(ctx) {
19697
- const { graph, language, config } = ctx;
19738
+ const { graph, language, config, code } = ctx;
19698
19739
  const { calls, types } = graph.ir;
19699
19740
  let mergedConfig = config;
19700
19741
  const plugin = getLanguagePlugin(language);
@@ -19731,7 +19772,7 @@ class TaintMatcherPass {
19731
19772
  }
19732
19773
  const hierarchy = createWithJdkTypes();
19733
19774
  hierarchy.addFromIR(graph.ir, graph.ir.meta.file);
19734
- const taint = analyzeTaint(calls, types, mergedConfig, hierarchy, language);
19775
+ const taint = analyzeTaint(calls, types, mergedConfig, hierarchy, language, code);
19735
19776
  const sanitizerMethods = [];
19736
19777
  for (const type of types) {
19737
19778
  for (const method of type.methods) {
@@ -19913,6 +19954,7 @@ class LanguageSourcesPass {
19913
19954
  ctx.addFinding(finding);
19914
19955
  }
19915
19956
  }
19957
+ attachSourceLineCode(additionalSources, additionalSinks, code);
19916
19958
  return { additionalSources, additionalSinks, pyTaintedVars, pySanitizedVars, jsTaintedVars };
19917
19959
  }
19918
19960
  }
@@ -27590,7 +27632,7 @@ var colors = {
27590
27632
  };
27591
27633
 
27592
27634
  // src/version.ts
27593
- var version = "3.39.0";
27635
+ var version = "3.41.0";
27594
27636
 
27595
27637
  // src/formatters.ts
27596
27638
  var SINK_SEVERITY = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cognium-dev",
3
- "version": "3.39.0",
3
+ "version": "3.41.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",
@@ -65,7 +65,7 @@
65
65
  "registry": "https://registry.npmjs.org/"
66
66
  },
67
67
  "dependencies": {
68
- "circle-ir": "^3.39.0"
68
+ "circle-ir": "^3.41.0"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@types/node": "^25.5.0",