cognium-dev 3.175.0 → 3.176.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.
- package/dist/cli.js +128 -6
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -11948,6 +11948,84 @@ var DEFAULT_HEADER_RULES = [
|
|
|
11948
11948
|
note: "Fires when the value is not a string literal (likely reflected from request)"
|
|
11949
11949
|
}
|
|
11950
11950
|
];
|
|
11951
|
+
// ../circle-ir/dist/analysis/arg-type-resolver.js
|
|
11952
|
+
function findEnclosingType(callInMethod, types) {
|
|
11953
|
+
if (!callInMethod)
|
|
11954
|
+
return null;
|
|
11955
|
+
for (const t of types) {
|
|
11956
|
+
for (const m of t.methods) {
|
|
11957
|
+
if (m.name === callInMethod)
|
|
11958
|
+
return t;
|
|
11959
|
+
}
|
|
11960
|
+
}
|
|
11961
|
+
return null;
|
|
11962
|
+
}
|
|
11963
|
+
function resolveIdentifierType(name2, callInMethod, types) {
|
|
11964
|
+
if (!name2)
|
|
11965
|
+
return null;
|
|
11966
|
+
const enclosing = findEnclosingType(callInMethod, types);
|
|
11967
|
+
if (enclosing) {
|
|
11968
|
+
for (const m of enclosing.methods) {
|
|
11969
|
+
if (m.name !== callInMethod)
|
|
11970
|
+
continue;
|
|
11971
|
+
for (const p of m.parameters) {
|
|
11972
|
+
if (p.name === name2 && p.type)
|
|
11973
|
+
return p.type;
|
|
11974
|
+
}
|
|
11975
|
+
}
|
|
11976
|
+
for (const f of enclosing.fields) {
|
|
11977
|
+
if (f.name === name2 && f.type)
|
|
11978
|
+
return f.type;
|
|
11979
|
+
}
|
|
11980
|
+
return null;
|
|
11981
|
+
}
|
|
11982
|
+
for (const t of types) {
|
|
11983
|
+
for (const m of t.methods) {
|
|
11984
|
+
for (const p of m.parameters) {
|
|
11985
|
+
if (p.name === name2 && p.type)
|
|
11986
|
+
return p.type;
|
|
11987
|
+
}
|
|
11988
|
+
}
|
|
11989
|
+
for (const f of t.fields) {
|
|
11990
|
+
if (f.name === name2 && f.type)
|
|
11991
|
+
return f.type;
|
|
11992
|
+
}
|
|
11993
|
+
}
|
|
11994
|
+
return null;
|
|
11995
|
+
}
|
|
11996
|
+
function resolveCallReturnType(calleeName, callInMethod, types) {
|
|
11997
|
+
if (!calleeName)
|
|
11998
|
+
return null;
|
|
11999
|
+
const enclosing = findEnclosingType(callInMethod, types);
|
|
12000
|
+
if (enclosing) {
|
|
12001
|
+
for (const m of enclosing.methods) {
|
|
12002
|
+
if (m.name === calleeName && m.return_type)
|
|
12003
|
+
return m.return_type;
|
|
12004
|
+
}
|
|
12005
|
+
}
|
|
12006
|
+
for (const t of types) {
|
|
12007
|
+
for (const m of t.methods) {
|
|
12008
|
+
if (m.name === calleeName && m.return_type)
|
|
12009
|
+
return m.return_type;
|
|
12010
|
+
}
|
|
12011
|
+
}
|
|
12012
|
+
return null;
|
|
12013
|
+
}
|
|
12014
|
+
function isBoundedClassType(rawType) {
|
|
12015
|
+
if (!rawType)
|
|
12016
|
+
return false;
|
|
12017
|
+
const stripped = rawType.trim().replace(/^(?:java\.lang\.)+/, "");
|
|
12018
|
+
return /^Class(?:\s*<[\s\S]*>)?$/.test(stripped);
|
|
12019
|
+
}
|
|
12020
|
+
function isArgvContainerType(rawType) {
|
|
12021
|
+
if (!rawType)
|
|
12022
|
+
return false;
|
|
12023
|
+
const s = rawType.trim().replace(/^(?:java\.util\.|java\.lang\.)+/, "");
|
|
12024
|
+
if (/^String\s*(?:\[\s*\]|\.\.\.)$/.test(s))
|
|
12025
|
+
return true;
|
|
12026
|
+
return /^(?:List|ArrayList|LinkedList|Collection|Iterable|Deque|Queue)\s*<\s*(?:String|CharSequence|java\.lang\.String)\b/.test(s);
|
|
12027
|
+
}
|
|
12028
|
+
|
|
11951
12029
|
// ../circle-ir/dist/analysis/taint-matcher.js
|
|
11952
12030
|
var PYTHON_TAINTED_PATTERNS = [
|
|
11953
12031
|
{ pattern: /\brequest\.args\b/, sourceType: "http_param" },
|
|
@@ -11971,7 +12049,7 @@ function analyzeTaint(calls, types, config = getDefaultConfig(), typeHierarchy,
|
|
|
11971
12049
|
const sources = findSources(calls, types, config.sources, sourceLines, language);
|
|
11972
12050
|
let sinkPatterns = expandPromisifyAliases(config.sinks, sourceLines, language);
|
|
11973
12051
|
sinkPatterns = expandIndirectEvalAliases(sinkPatterns, sourceLines, language);
|
|
11974
|
-
const sinks = findSinks(calls, sinkPatterns, typeHierarchy, language, sourceLines);
|
|
12052
|
+
const sinks = findSinks(calls, sinkPatterns, typeHierarchy, language, sourceLines, types);
|
|
11975
12053
|
const sanitizers = findSanitizers(calls, types, config.sanitizers, sourceLines);
|
|
11976
12054
|
return { sources, sinks, sanitizers };
|
|
11977
12055
|
}
|
|
@@ -12587,7 +12665,7 @@ function isSafeRustCommandCall(call, pattern, language) {
|
|
|
12587
12665
|
return false;
|
|
12588
12666
|
}
|
|
12589
12667
|
var CLASS_LITERAL_RE = /^(?:[A-Za-z_][\w]*\.)*[A-Z][\w]*(?:\[\])*\.class$/;
|
|
12590
|
-
function argIsClassLiteral(call, position) {
|
|
12668
|
+
function argIsClassLiteral(call, position, types) {
|
|
12591
12669
|
const arg = call.arguments.find((a) => a.position === position);
|
|
12592
12670
|
if (!arg)
|
|
12593
12671
|
return false;
|
|
@@ -12596,7 +12674,28 @@ function argIsClassLiteral(call, position) {
|
|
|
12596
12674
|
return false;
|
|
12597
12675
|
if (CLASS_LITERAL_RE.test(expr))
|
|
12598
12676
|
return true;
|
|
12599
|
-
|
|
12677
|
+
if (TYPE_TOKEN_RE.test(expr))
|
|
12678
|
+
return true;
|
|
12679
|
+
if (!types || types.length === 0)
|
|
12680
|
+
return false;
|
|
12681
|
+
const argExpr = (arg.expression ?? "").trim();
|
|
12682
|
+
const varName = arg.variable ?? "";
|
|
12683
|
+
const isBareIdentifier = varName !== "" && argExpr === varName && !/[(.]/.test(argExpr);
|
|
12684
|
+
if (isBareIdentifier) {
|
|
12685
|
+
const t = resolveIdentifierType(varName, call.in_method, types);
|
|
12686
|
+
if (isBoundedClassType(t))
|
|
12687
|
+
return true;
|
|
12688
|
+
}
|
|
12689
|
+
const isCallExpr = varName !== "" && new RegExp(`^${escapeRe(varName)}\\s*\\(`).test(argExpr);
|
|
12690
|
+
if (isCallExpr) {
|
|
12691
|
+
const t = resolveCallReturnType(varName, call.in_method, types);
|
|
12692
|
+
if (isBoundedClassType(t))
|
|
12693
|
+
return true;
|
|
12694
|
+
}
|
|
12695
|
+
return false;
|
|
12696
|
+
}
|
|
12697
|
+
function escapeRe(s) {
|
|
12698
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
12600
12699
|
}
|
|
12601
12700
|
var TYPE_TOKEN_RE = /^new\s+(?:TypeReference|TypeToken)\s*<[\s\S]*>\s*\(\s*\)\s*\{\s*\}$/;
|
|
12602
12701
|
function argIsStringLiteral(call, position) {
|
|
@@ -12779,7 +12878,7 @@ function isSafeJinjaRenderCall(call, pattern, language, sourceLines) {
|
|
|
12779
12878
|
}
|
|
12780
12879
|
return false;
|
|
12781
12880
|
}
|
|
12782
|
-
function findSinks(calls, patterns, typeHierarchy, language, sourceLines) {
|
|
12881
|
+
function findSinks(calls, patterns, typeHierarchy, language, sourceLines, types) {
|
|
12783
12882
|
const sinkMap = new Map;
|
|
12784
12883
|
for (const call of calls) {
|
|
12785
12884
|
for (const pattern of patterns) {
|
|
@@ -12799,7 +12898,7 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines) {
|
|
|
12799
12898
|
if (isSafeJSChildProcessCall(call, pattern, language)) {
|
|
12800
12899
|
continue;
|
|
12801
12900
|
}
|
|
12802
|
-
if (pattern.safe_if_class_literal_at !== undefined && argIsClassLiteral(call, pattern.safe_if_class_literal_at)) {
|
|
12901
|
+
if (pattern.safe_if_class_literal_at !== undefined && argIsClassLiteral(call, pattern.safe_if_class_literal_at, types)) {
|
|
12803
12902
|
continue;
|
|
12804
12903
|
}
|
|
12805
12904
|
if (pattern.safe_if_string_literal_at !== undefined && argIsStringLiteral(call, pattern.safe_if_string_literal_at)) {
|
|
@@ -30796,6 +30895,9 @@ class MyBatisAnnotationSqlSinkPass {
|
|
|
30796
30895
|
}
|
|
30797
30896
|
|
|
30798
30897
|
// ../circle-ir/dist/analysis/passes/sink-filter-pass.js
|
|
30898
|
+
function escapeReSf(s) {
|
|
30899
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
30900
|
+
}
|
|
30799
30901
|
var JS_XSS_SANITIZERS = [
|
|
30800
30902
|
/\bDOMPurify\.sanitize\s*\(/,
|
|
30801
30903
|
/\bsanitizeHtml\s*\(/,
|
|
@@ -31425,6 +31527,8 @@ class SinkFilterPass {
|
|
|
31425
31527
|
if (language === "java") {
|
|
31426
31528
|
const sourceLines = ctx.code.split(`
|
|
31427
31529
|
`);
|
|
31530
|
+
const irCalls = ctx.graph.ir.calls;
|
|
31531
|
+
const irTypes = ctx.graph.ir.types;
|
|
31428
31532
|
filtered = filtered.filter((sink) => {
|
|
31429
31533
|
if (sink.type !== "command_injection")
|
|
31430
31534
|
return true;
|
|
@@ -31435,6 +31539,24 @@ class SinkFilterPass {
|
|
|
31435
31539
|
return true;
|
|
31436
31540
|
if (PROCESS_BUILDER_ARGV_FORM_RE.test(sinkLineText))
|
|
31437
31541
|
return false;
|
|
31542
|
+
const ctorCall = irCalls.find((c) => c.method_name === "ProcessBuilder" && c.location.line === sink.line && (c.receiver === null || c.receiver === undefined));
|
|
31543
|
+
if (!ctorCall || ctorCall.arguments.length === 0)
|
|
31544
|
+
return true;
|
|
31545
|
+
const arg0 = ctorCall.arguments[0];
|
|
31546
|
+
if (!arg0)
|
|
31547
|
+
return true;
|
|
31548
|
+
const argExpr = (arg0.expression ?? "").trim();
|
|
31549
|
+
const varName = arg0.variable ?? "";
|
|
31550
|
+
if (varName !== "" && argExpr === varName && !/[(.]/.test(argExpr)) {
|
|
31551
|
+
const t = resolveIdentifierType(varName, ctorCall.in_method, irTypes);
|
|
31552
|
+
if (isArgvContainerType(t))
|
|
31553
|
+
return false;
|
|
31554
|
+
}
|
|
31555
|
+
if (varName !== "" && new RegExp(`^${escapeReSf(varName)}\\s*\\(`).test(argExpr)) {
|
|
31556
|
+
const t = resolveCallReturnType(varName, ctorCall.in_method, irTypes);
|
|
31557
|
+
if (isArgvContainerType(t))
|
|
31558
|
+
return false;
|
|
31559
|
+
}
|
|
31438
31560
|
return true;
|
|
31439
31561
|
});
|
|
31440
31562
|
}
|
|
@@ -44796,7 +44918,7 @@ var colors = {
|
|
|
44796
44918
|
};
|
|
44797
44919
|
|
|
44798
44920
|
// src/version.ts
|
|
44799
|
-
var version = "3.
|
|
44921
|
+
var version = "3.176.0";
|
|
44800
44922
|
|
|
44801
44923
|
// src/formatters.ts
|
|
44802
44924
|
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.
|
|
3
|
+
"version": "3.176.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.
|
|
69
|
+
"circle-ir": "^3.176.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/node": "^25.5.0",
|