cognium-dev 3.166.1 → 3.168.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 +152 -21
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -13624,6 +13624,66 @@ function formatCallCode(call) {
|
|
|
13624
13624
|
}
|
|
13625
13625
|
return `${call.method_name}(${args2})`;
|
|
13626
13626
|
}
|
|
13627
|
+
// ../circle-ir/dist/analysis/non-executable-lines.js
|
|
13628
|
+
function isNonExecutableSourceLine(sourceCode, line, language) {
|
|
13629
|
+
if (!sourceCode || line < 1)
|
|
13630
|
+
return false;
|
|
13631
|
+
const lines = sourceCode.split(`
|
|
13632
|
+
`);
|
|
13633
|
+
if (line > lines.length)
|
|
13634
|
+
return false;
|
|
13635
|
+
const raw = lines[line - 1] ?? "";
|
|
13636
|
+
const trimmed = raw.trim();
|
|
13637
|
+
if (trimmed === "")
|
|
13638
|
+
return true;
|
|
13639
|
+
const lang = language.toLowerCase();
|
|
13640
|
+
if (trimmed.startsWith("//") || trimmed.startsWith("/*") || trimmed.startsWith("*/") || trimmed.startsWith("*") || trimmed === "/**") {
|
|
13641
|
+
return true;
|
|
13642
|
+
}
|
|
13643
|
+
switch (lang) {
|
|
13644
|
+
case "java":
|
|
13645
|
+
case "javascript":
|
|
13646
|
+
case "typescript":
|
|
13647
|
+
case "go":
|
|
13648
|
+
case "rust":
|
|
13649
|
+
return isNonExecutableCurly(trimmed);
|
|
13650
|
+
case "python":
|
|
13651
|
+
return isNonExecutablePython(trimmed);
|
|
13652
|
+
default:
|
|
13653
|
+
return false;
|
|
13654
|
+
}
|
|
13655
|
+
}
|
|
13656
|
+
function isNonExecutableCurly(trimmed) {
|
|
13657
|
+
if (/^(import|package|use|from)\s/.test(trimmed))
|
|
13658
|
+
return true;
|
|
13659
|
+
if (/^@[A-Za-z_][\w.]*(?:\s*\([^)]*\))?\s*$/.test(trimmed))
|
|
13660
|
+
return true;
|
|
13661
|
+
if (/^(?:(?:public|private|protected|internal)\s+)?(?:static\s+)?(?:final\s+|readonly\s+|const\s+)(?:[A-Za-z_][\w<>.\[\]]*\s+)?[A-Za-z_]\w*(?:\s*:\s*[^=]+)?\s*=\s*(?:["'`][^"'`]*["'`]|-?\d+(?:\.\d+)?)\s*;?\s*$/.test(trimmed)) {
|
|
13662
|
+
return true;
|
|
13663
|
+
}
|
|
13664
|
+
if (/^(?:const|let|var|static)\s+[A-Za-z_]\w*(?:\s*:\s*[^=]+)?\s*=\s*(?:["'`][^"'`]*["'`]|-?\d+(?:\.\d+)?)\s*;?\s*$/.test(trimmed)) {
|
|
13665
|
+
return true;
|
|
13666
|
+
}
|
|
13667
|
+
if (/^(?:(?:public|private|protected)\s+)?(?:static\s+)?(?:final\s+)[A-Za-z_][\w<>.\[\]]*\s+[A-Za-z_]\w*\s*;\s*$/.test(trimmed)) {
|
|
13668
|
+
return true;
|
|
13669
|
+
}
|
|
13670
|
+
return false;
|
|
13671
|
+
}
|
|
13672
|
+
function isNonExecutablePython(trimmed) {
|
|
13673
|
+
if (/^(import|from)\s/.test(trimmed))
|
|
13674
|
+
return true;
|
|
13675
|
+
if (trimmed.startsWith("#"))
|
|
13676
|
+
return true;
|
|
13677
|
+
if (trimmed === '"""' || trimmed === "'''")
|
|
13678
|
+
return true;
|
|
13679
|
+
if (/^@[A-Za-z_][\w.]*(?:\s*\([^)]*\))?\s*$/.test(trimmed))
|
|
13680
|
+
return true;
|
|
13681
|
+
if (/^[A-Z_][A-Z0-9_]*\s*(?::\s*[^=]+)?\s*=\s*(?:["'][^"']*["']|-?\d+(?:\.\d+)?)\s*$/.test(trimmed)) {
|
|
13682
|
+
return true;
|
|
13683
|
+
}
|
|
13684
|
+
return false;
|
|
13685
|
+
}
|
|
13686
|
+
|
|
13627
13687
|
// ../circle-ir/dist/analysis/findings.js
|
|
13628
13688
|
function canSourceReachSink(sourceType, sinkType) {
|
|
13629
13689
|
const sourceToSinkMapping = {
|
|
@@ -19132,6 +19192,9 @@ function classifyJsTsEntryPoint(method, enclosingType, ctx) {
|
|
|
19132
19192
|
if (methodIsRuntimeRegistrationHandler(method, ctx.runtimeRegistrations)) {
|
|
19133
19193
|
return "TIER_1_ENTRY_POINT";
|
|
19134
19194
|
}
|
|
19195
|
+
if (fileHasJsTsFrameworkRegistration(ctx.runtimeRegistrations) && (!enclosingType || looksLikeModuleType(enclosingType))) {
|
|
19196
|
+
return "TIER_1_ENTRY_POINT";
|
|
19197
|
+
}
|
|
19135
19198
|
if (JSTS_TIER_1_MODULE_EXPORTS.has(method.name) && (!enclosingType || looksLikeModuleType(enclosingType))) {
|
|
19136
19199
|
return "TIER_1_ENTRY_POINT";
|
|
19137
19200
|
}
|
|
@@ -19140,6 +19203,25 @@ function classifyJsTsEntryPoint(method, enclosingType, ctx) {
|
|
|
19140
19203
|
}
|
|
19141
19204
|
return "TIER_UNKNOWN";
|
|
19142
19205
|
}
|
|
19206
|
+
var JSTS_FILE_LEVEL_TIER_1_FRAMEWORKS = new Set([
|
|
19207
|
+
"express",
|
|
19208
|
+
"fastify",
|
|
19209
|
+
"koa",
|
|
19210
|
+
"nestjs"
|
|
19211
|
+
]);
|
|
19212
|
+
function fileHasJsTsFrameworkRegistration(regs) {
|
|
19213
|
+
if (!regs || regs.length === 0)
|
|
19214
|
+
return false;
|
|
19215
|
+
for (const reg of regs) {
|
|
19216
|
+
if (reg.kind !== "http_route" && reg.kind !== "middleware" && reg.kind !== "event_listener") {
|
|
19217
|
+
continue;
|
|
19218
|
+
}
|
|
19219
|
+
if (reg.framework && JSTS_FILE_LEVEL_TIER_1_FRAMEWORKS.has(reg.framework)) {
|
|
19220
|
+
return true;
|
|
19221
|
+
}
|
|
19222
|
+
}
|
|
19223
|
+
return false;
|
|
19224
|
+
}
|
|
19143
19225
|
var GO_HTTP_REGISTRAR_METHODS = new Set([
|
|
19144
19226
|
"HandleFunc",
|
|
19145
19227
|
"Handle",
|
|
@@ -19417,30 +19499,78 @@ function applyRequireEntryPath(fileAnalyses, options = {}) {
|
|
|
19417
19499
|
const entryPointKeysByLanguage = countEntryPointKeysByLanguage(graph, entryPointKeys);
|
|
19418
19500
|
const profileResolver = makeProfileResolver(options.projectProfile);
|
|
19419
19501
|
for (const fa of fileAnalyses) {
|
|
19502
|
+
const profile = profileResolver(fa.file);
|
|
19420
19503
|
const findings = fa.analysis.findings;
|
|
19421
|
-
if (
|
|
19422
|
-
|
|
19423
|
-
|
|
19424
|
-
|
|
19425
|
-
|
|
19426
|
-
|
|
19427
|
-
|
|
19428
|
-
|
|
19429
|
-
|
|
19430
|
-
|
|
19431
|
-
|
|
19432
|
-
|
|
19433
|
-
|
|
19434
|
-
|
|
19435
|
-
|
|
19436
|
-
|
|
19437
|
-
|
|
19438
|
-
|
|
19504
|
+
if (findings && findings.length > 0) {
|
|
19505
|
+
const kept = [];
|
|
19506
|
+
for (const finding of findings) {
|
|
19507
|
+
const decision = classifyFinding(finding, fa.analysis, graph, entryPointKeys, entryPointKeysByLanguage, profile);
|
|
19508
|
+
switch (decision.action) {
|
|
19509
|
+
case "keep":
|
|
19510
|
+
kept.push(finding);
|
|
19511
|
+
break;
|
|
19512
|
+
case "annotate":
|
|
19513
|
+
kept.push({
|
|
19514
|
+
...finding,
|
|
19515
|
+
entryPath: decision.entryPath,
|
|
19516
|
+
entryPathTier: decision.tier
|
|
19517
|
+
});
|
|
19518
|
+
break;
|
|
19519
|
+
case "drop":
|
|
19520
|
+
break;
|
|
19521
|
+
}
|
|
19522
|
+
}
|
|
19523
|
+
fa.analysis.findings = kept.length > 0 ? kept : undefined;
|
|
19524
|
+
}
|
|
19525
|
+
const flows = fa.analysis.taint?.flows;
|
|
19526
|
+
if (flows && flows.length > 0) {
|
|
19527
|
+
const keptFlows = [];
|
|
19528
|
+
for (const flow of flows) {
|
|
19529
|
+
const pseudo = flowToPseudoFinding(fa.file, flow);
|
|
19530
|
+
if (!pseudo) {
|
|
19531
|
+
keptFlows.push(flow);
|
|
19532
|
+
continue;
|
|
19533
|
+
}
|
|
19534
|
+
const decision = classifyFinding(pseudo, fa.analysis, graph, entryPointKeys, entryPointKeysByLanguage, profile);
|
|
19535
|
+
if (decision.action !== "drop")
|
|
19536
|
+
keptFlows.push(flow);
|
|
19439
19537
|
}
|
|
19538
|
+
fa.analysis.taint.flows = keptFlows;
|
|
19440
19539
|
}
|
|
19441
|
-
fa.analysis.findings = kept.length > 0 ? kept : undefined;
|
|
19442
19540
|
}
|
|
19443
19541
|
}
|
|
19542
|
+
var SINK_HC_SEVERITY = {
|
|
19543
|
+
sql_injection: "critical",
|
|
19544
|
+
nosql_injection: "high",
|
|
19545
|
+
command_injection: "critical",
|
|
19546
|
+
path_traversal: "high",
|
|
19547
|
+
xss: "high",
|
|
19548
|
+
xxe: "critical",
|
|
19549
|
+
deserialization: "critical",
|
|
19550
|
+
ldap_injection: "high",
|
|
19551
|
+
xpath_injection: "high",
|
|
19552
|
+
ssrf: "high",
|
|
19553
|
+
code_injection: "critical",
|
|
19554
|
+
format_string: "high",
|
|
19555
|
+
mass_assignment: "high"
|
|
19556
|
+
};
|
|
19557
|
+
function flowToPseudoFinding(file, flow) {
|
|
19558
|
+
const severity = SINK_HC_SEVERITY[flow.sink_type];
|
|
19559
|
+
if (!severity)
|
|
19560
|
+
return null;
|
|
19561
|
+
return {
|
|
19562
|
+
id: `taint-flow:${file}:${flow.sink_line}:${flow.sink_type}`,
|
|
19563
|
+
pass: "taint-propagation",
|
|
19564
|
+
category: "security",
|
|
19565
|
+
rule_id: flow.sink_type,
|
|
19566
|
+
cwe: "",
|
|
19567
|
+
severity,
|
|
19568
|
+
level: "error",
|
|
19569
|
+
message: `${flow.sink_type} at line ${flow.sink_line}`,
|
|
19570
|
+
file,
|
|
19571
|
+
line: flow.sink_line
|
|
19572
|
+
};
|
|
19573
|
+
}
|
|
19444
19574
|
function buildProjectMethodGraph(fileAnalyses) {
|
|
19445
19575
|
const methodsByKey = new Map;
|
|
19446
19576
|
const methodsByName = new Map;
|
|
@@ -30860,7 +30990,8 @@ class SinkFilterPass {
|
|
|
30860
30990
|
const taintMatcher = ctx.getResult("taint-matcher");
|
|
30861
30991
|
const constProp = ctx.getResult("constant-propagation");
|
|
30862
30992
|
const langSources = ctx.getResult("language-sources");
|
|
30863
|
-
const
|
|
30993
|
+
const mergedSources = [...taintMatcher.sources, ...langSources.additionalSources];
|
|
30994
|
+
const sources = ctx.code && ctx.language ? mergedSources.filter((s) => !isNonExecutableSourceLine(ctx.code, s.line, ctx.language)) : mergedSources;
|
|
30864
30995
|
const sinks = [...taintMatcher.sinks];
|
|
30865
30996
|
for (const s of langSources.additionalSinks) {
|
|
30866
30997
|
if (!sinks.some((x) => x.line === s.line && x.cwe === s.cwe && x.type === s.type)) {
|
|
@@ -44464,7 +44595,7 @@ var colors = {
|
|
|
44464
44595
|
};
|
|
44465
44596
|
|
|
44466
44597
|
// src/version.ts
|
|
44467
|
-
var version = "3.
|
|
44598
|
+
var version = "3.168.0";
|
|
44468
44599
|
|
|
44469
44600
|
// src/formatters.ts
|
|
44470
44601
|
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.168.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.168.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/node": "^25.5.0",
|