cognium-dev 3.157.0 → 3.159.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 +146 -3
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -18898,6 +18898,42 @@ function shouldGateInterproceduralParam(sourceType, enclosingMethod, enclosingTy
|
|
|
18898
18898
|
// ../circle-ir/dist/analysis/require-entry-path.js
|
|
18899
18899
|
var RULE_ID_REQUIRE_ENTRY_PATH = "require-entry-path";
|
|
18900
18900
|
var MAX_VISITED_METHODS = 2000;
|
|
18901
|
+
var TAINT_FLOW_RULE_IDS = new Set([
|
|
18902
|
+
"sql_injection",
|
|
18903
|
+
"nosql_injection",
|
|
18904
|
+
"command_injection",
|
|
18905
|
+
"path_traversal",
|
|
18906
|
+
"xss",
|
|
18907
|
+
"xxe",
|
|
18908
|
+
"deserialization",
|
|
18909
|
+
"insecure_deserialization",
|
|
18910
|
+
"ldap_injection",
|
|
18911
|
+
"xpath_injection",
|
|
18912
|
+
"ssrf",
|
|
18913
|
+
"open_redirect",
|
|
18914
|
+
"code_injection",
|
|
18915
|
+
"log_injection",
|
|
18916
|
+
"redos",
|
|
18917
|
+
"format_string",
|
|
18918
|
+
"crlf",
|
|
18919
|
+
"mass_assignment",
|
|
18920
|
+
"mybatis_mapper_call",
|
|
18921
|
+
"external_taint_escape",
|
|
18922
|
+
"template_injection",
|
|
18923
|
+
"sql-injection",
|
|
18924
|
+
"nosql-injection",
|
|
18925
|
+
"command-injection",
|
|
18926
|
+
"path-traversal",
|
|
18927
|
+
"ldap-injection",
|
|
18928
|
+
"xpath-injection",
|
|
18929
|
+
"open-redirect",
|
|
18930
|
+
"code-injection",
|
|
18931
|
+
"log-injection",
|
|
18932
|
+
"format-string",
|
|
18933
|
+
"mass-assignment",
|
|
18934
|
+
"template-injection",
|
|
18935
|
+
"insecure-deserialization"
|
|
18936
|
+
]);
|
|
18901
18937
|
function applyRequireEntryPath(fileAnalyses, options = {}) {
|
|
18902
18938
|
const disabledSet = normalizeDisabled(options.disabledPasses);
|
|
18903
18939
|
if (disabledSet.has(RULE_ID_REQUIRE_ENTRY_PATH))
|
|
@@ -19033,6 +19069,8 @@ function collectEntryPointKeys(graph) {
|
|
|
19033
19069
|
function classifyFinding(finding, ir, graph, entryPointKeys, profile) {
|
|
19034
19070
|
if (finding.category !== "security")
|
|
19035
19071
|
return { action: "keep" };
|
|
19072
|
+
if (!TAINT_FLOW_RULE_IDS.has(finding.rule_id))
|
|
19073
|
+
return { action: "keep" };
|
|
19036
19074
|
const isHighOrCritical = finding.severity === "high" || finding.severity === "critical";
|
|
19037
19075
|
const language = (ir.meta.language ?? "").toLowerCase();
|
|
19038
19076
|
if (language !== "java")
|
|
@@ -22478,14 +22516,40 @@ class CrossFilePass {
|
|
|
22478
22516
|
});
|
|
22479
22517
|
}
|
|
22480
22518
|
}
|
|
22519
|
+
const filteredTaintPaths = taintPaths.filter((tp) => {
|
|
22520
|
+
const sinkIR = projectGraph.getIR(tp.sink.file);
|
|
22521
|
+
if (!sinkIR)
|
|
22522
|
+
return true;
|
|
22523
|
+
const sinkTypeStr = tp.sink.type;
|
|
22524
|
+
if (tp.source.file === tp.sink.file) {
|
|
22525
|
+
const lo = Math.min(tp.source.line, tp.sink.line);
|
|
22526
|
+
const hi = Math.max(tp.source.line, tp.sink.line);
|
|
22527
|
+
for (const san of sinkIR.taint.sanitizers ?? []) {
|
|
22528
|
+
if (san.line < lo || san.line > hi)
|
|
22529
|
+
continue;
|
|
22530
|
+
if (san.sanitizes.includes(sinkTypeStr)) {
|
|
22531
|
+
return false;
|
|
22532
|
+
}
|
|
22533
|
+
}
|
|
22534
|
+
return true;
|
|
22535
|
+
}
|
|
22536
|
+
for (const san of sinkIR.taint.sanitizers ?? []) {
|
|
22537
|
+
if (san.line !== tp.sink.line)
|
|
22538
|
+
continue;
|
|
22539
|
+
if (san.sanitizes.includes(sinkTypeStr)) {
|
|
22540
|
+
return false;
|
|
22541
|
+
}
|
|
22542
|
+
}
|
|
22543
|
+
return true;
|
|
22544
|
+
});
|
|
22481
22545
|
const typeHierarchy = projectGraph.typeHierarchy.toTypeHierarchyData();
|
|
22482
22546
|
logger.info("cross-file: complete", {
|
|
22483
22547
|
totalMs: Date.now() - startMs,
|
|
22484
|
-
paths:
|
|
22548
|
+
paths: filteredTaintPaths.length,
|
|
22485
22549
|
crossFileCalls: crossFileCalls.length,
|
|
22486
22550
|
budgetExceeded: exceeded
|
|
22487
22551
|
});
|
|
22488
|
-
const result = { crossFileCalls, taintPaths, typeHierarchy };
|
|
22552
|
+
const result = { crossFileCalls, taintPaths: filteredTaintPaths, typeHierarchy };
|
|
22489
22553
|
if (exceeded)
|
|
22490
22554
|
result.budgetExceeded = true;
|
|
22491
22555
|
return result;
|
|
@@ -23631,6 +23695,7 @@ class LanguageSourcesPass {
|
|
|
23631
23695
|
if (language === "java") {
|
|
23632
23696
|
additionalSanitizers.push(...findJavaSafeJsonParseSanitizers(code));
|
|
23633
23697
|
additionalSanitizers.push(...findJavaPathNormalizeStartsWithGuardSanitizers(code));
|
|
23698
|
+
additionalSanitizers.push(...findJavaPathGetFileNameSanitizers(code));
|
|
23634
23699
|
additionalSanitizers.push(...findJavaInlineCrlfStripLogSanitizers(code));
|
|
23635
23700
|
additionalSanitizers.push(...findJavaArgvFormExecSanitizers(code));
|
|
23636
23701
|
for (const finding of findJavaPatternFindings(code, graph.ir.meta.file)) {
|
|
@@ -25899,6 +25964,48 @@ function findJavaPathNormalizeStartsWithGuardSanitizers(code) {
|
|
|
25899
25964
|
}
|
|
25900
25965
|
return sanitizers;
|
|
25901
25966
|
}
|
|
25967
|
+
function findJavaPathGetFileNameSanitizers(code) {
|
|
25968
|
+
const sanitizers = [];
|
|
25969
|
+
const lines = code.split(`
|
|
25970
|
+
`);
|
|
25971
|
+
const assignmentRe = /^\s*(?:(?:final\s+)?[A-Za-z_][\w.<>?,\s\[\]]*?\s+)?([A-Za-z_]\w*)\s*=\s*(.+?);\s*$/;
|
|
25972
|
+
const rhsHasGetFileNameRe = /\.\s*getFileName\s*\(\s*\)/;
|
|
25973
|
+
const rhsHasPathsChainRe = /\b(?:Paths\s*\.\s*get|Path\s*\.\s*of)\s*\(/;
|
|
25974
|
+
const candidates = [];
|
|
25975
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
25976
|
+
const m = assignmentRe.exec(lines[i2]);
|
|
25977
|
+
if (!m)
|
|
25978
|
+
continue;
|
|
25979
|
+
const rhs = m[2];
|
|
25980
|
+
if (!rhsHasGetFileNameRe.test(rhs))
|
|
25981
|
+
continue;
|
|
25982
|
+
if (!rhsHasPathsChainRe.test(rhs))
|
|
25983
|
+
continue;
|
|
25984
|
+
candidates.push({ line: i2 + 1, boundVar: m[1] });
|
|
25985
|
+
}
|
|
25986
|
+
if (candidates.length === 0)
|
|
25987
|
+
return sanitizers;
|
|
25988
|
+
for (const c of candidates) {
|
|
25989
|
+
sanitizers.push({
|
|
25990
|
+
type: "java_path_get_filename",
|
|
25991
|
+
method: "getFileName",
|
|
25992
|
+
line: c.line,
|
|
25993
|
+
sanitizes: ["path_traversal", "external_taint_escape"]
|
|
25994
|
+
});
|
|
25995
|
+
const varRefRe = new RegExp(`\\b${c.boundVar}\\b`);
|
|
25996
|
+
for (let l = c.line;l < lines.length; l++) {
|
|
25997
|
+
if (!varRefRe.test(lines[l]))
|
|
25998
|
+
continue;
|
|
25999
|
+
sanitizers.push({
|
|
26000
|
+
type: "java_path_get_filename",
|
|
26001
|
+
method: "getFileName",
|
|
26002
|
+
line: l + 1,
|
|
26003
|
+
sanitizes: ["path_traversal", "external_taint_escape"]
|
|
26004
|
+
});
|
|
26005
|
+
}
|
|
26006
|
+
}
|
|
26007
|
+
return sanitizers;
|
|
26008
|
+
}
|
|
25902
26009
|
function findJavaInlineCrlfStripLogSanitizers(code) {
|
|
25903
26010
|
const sanitizers = [];
|
|
25904
26011
|
const lines = code.split(`
|
|
@@ -30415,6 +30522,30 @@ class SinkFilterPass {
|
|
|
30415
30522
|
}
|
|
30416
30523
|
if (language === "java") {
|
|
30417
30524
|
const sourceLines = ctx.code.split(`
|
|
30525
|
+
`);
|
|
30526
|
+
filtered = filtered.filter((sink) => {
|
|
30527
|
+
if (sink.type !== "xss")
|
|
30528
|
+
return true;
|
|
30529
|
+
const sinkLineText = sourceLines[sink.line - 1] ?? "";
|
|
30530
|
+
const receiverMatch = sinkLineText.match(/\b(\w+)\s*\.\s*(\w+)\s*\(/);
|
|
30531
|
+
const receiver = receiverMatch?.[1];
|
|
30532
|
+
const method = sink.method ?? receiverMatch?.[2];
|
|
30533
|
+
if ((method === "render" || method === "process" || method === "merge" || method === "renderTo" || method === "apply") && receiver) {
|
|
30534
|
+
const recvType = resolveJavaReceiverType(receiver, sink.line, sourceLines);
|
|
30535
|
+
if (recvType && COMPILED_TEMPLATE_TYPES.has(recvType))
|
|
30536
|
+
return false;
|
|
30537
|
+
if (recvType && TEMPLATE_ENGINE_LITERAL_TARGETS.has(recvType)) {
|
|
30538
|
+
const args2 = extractJavaCallArgs(method, sinkLineText);
|
|
30539
|
+
if (args2 !== null && args2.length >= 1 && isJavaLiteralOrAnnotationAccessor(args2[0])) {
|
|
30540
|
+
return false;
|
|
30541
|
+
}
|
|
30542
|
+
}
|
|
30543
|
+
}
|
|
30544
|
+
return true;
|
|
30545
|
+
});
|
|
30546
|
+
}
|
|
30547
|
+
if (language === "java") {
|
|
30548
|
+
const sourceLines = ctx.code.split(`
|
|
30418
30549
|
`);
|
|
30419
30550
|
filtered = filtered.filter((sink) => {
|
|
30420
30551
|
if (sink.type !== "command_injection")
|
|
@@ -38674,10 +38805,22 @@ var TEST_PATH_PATTERNS = [
|
|
|
38674
38805
|
/\.spec\.(?:tsx?|jsx?|mjs|cjs)$/i,
|
|
38675
38806
|
/\.test\.(?:java|kt)$/i
|
|
38676
38807
|
];
|
|
38808
|
+
var JVM_TEST_FILE_PATTERNS = [
|
|
38809
|
+
/(?:^|\/)[A-Za-z_]\w*(?:Test|Tests|Spec|IT|ITCase|TestCase)\.(?:java|kt|scala|groovy)$/,
|
|
38810
|
+
/(?:^|\/)[A-Za-z_]\w*\.(?:test|spec)\.(?:java|kt|scala|groovy)$/i
|
|
38811
|
+
];
|
|
38812
|
+
var JVM_SOURCE_FILE_RE = /\.(?:java|kt|scala|groovy)$/i;
|
|
38677
38813
|
function isTestPath(filepath) {
|
|
38678
38814
|
if (!filepath)
|
|
38679
38815
|
return false;
|
|
38680
38816
|
const normalized = filepath.replace(/\\/g, "/");
|
|
38817
|
+
if (JVM_SOURCE_FILE_RE.test(normalized)) {
|
|
38818
|
+
for (const pattern of JVM_TEST_FILE_PATTERNS) {
|
|
38819
|
+
if (pattern.test(normalized))
|
|
38820
|
+
return true;
|
|
38821
|
+
}
|
|
38822
|
+
return false;
|
|
38823
|
+
}
|
|
38681
38824
|
for (const pattern of TEST_PATH_PATTERNS) {
|
|
38682
38825
|
if (pattern.test(normalized))
|
|
38683
38826
|
return true;
|
|
@@ -43608,7 +43751,7 @@ var colors = {
|
|
|
43608
43751
|
};
|
|
43609
43752
|
|
|
43610
43753
|
// src/version.ts
|
|
43611
|
-
var version = "3.
|
|
43754
|
+
var version = "3.159.0";
|
|
43612
43755
|
|
|
43613
43756
|
// src/formatters.ts
|
|
43614
43757
|
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.159.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.159.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/node": "^25.5.0",
|