cognium-dev 3.82.0 → 3.84.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 +271 -7
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -10517,10 +10517,6 @@ var DEFAULT_SINKS = [
|
|
|
10517
10517
|
{ method: "setCommandline", class: "DefaultExecutor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10518
10518
|
{ method: "parse", class: "CommandLine", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10519
10519
|
{ method: "addArgument", class: "CommandLine", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
10520
|
-
{ method: "waitFor", class: "Process", type: "command_injection", cwe: "CWE-78", severity: "medium", arg_positions: [] },
|
|
10521
|
-
{ method: "inheritIO", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "medium", arg_positions: [] },
|
|
10522
|
-
{ method: "redirectOutput", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "medium", arg_positions: [0] },
|
|
10523
|
-
{ method: "redirectInput", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "medium", arg_positions: [0] },
|
|
10524
10520
|
{ method: "File", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0, 1] },
|
|
10525
10521
|
{ method: "FileInputStream", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10526
10522
|
{ method: "FileOutputStream", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
@@ -10764,7 +10760,6 @@ var DEFAULT_SINKS = [
|
|
|
10764
10760
|
{ method: "entity", class: "ResponseBuilder", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
10765
10761
|
{ method: "ok", class: "Response", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
10766
10762
|
{ method: "eval", class: "ScriptEngine", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
|
|
10767
|
-
{ method: "compile", class: "Pattern", type: "code_injection", cwe: "CWE-94", severity: "high", arg_positions: [0] },
|
|
10768
10763
|
{ method: "parseExpression", class: "ExpressionParser", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
|
|
10769
10764
|
{ method: "parseExpression", class: "SpelExpressionParser", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
|
|
10770
10765
|
{ method: "getValue", class: "Expression", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [] },
|
|
@@ -11239,7 +11234,6 @@ var DEFAULT_SINKS = [
|
|
|
11239
11234
|
{ method: "log", class: "logging", type: "log_injection", cwe: "CWE-117", severity: "low", arg_positions: [1] },
|
|
11240
11235
|
{ method: "exception", class: "logging", type: "log_injection", cwe: "CWE-117", severity: "low", arg_positions: [0] },
|
|
11241
11236
|
{ method: "command", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
11242
|
-
{ method: "inheritIO", class: "ProcessBuilder", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [] },
|
|
11243
11237
|
{ method: "step", class: "StepExecution", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
11244
11238
|
{ method: "invokeMethod", class: "Script", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0, 1] },
|
|
11245
11239
|
{ method: "evaluate", class: "Script", type: "code_injection", cwe: "CWE-94", severity: "critical", arg_positions: [0] },
|
|
@@ -12053,6 +12047,61 @@ function isSafeGoExecCommandCall(call, pattern, language) {
|
|
|
12053
12047
|
return false;
|
|
12054
12048
|
return true;
|
|
12055
12049
|
}
|
|
12050
|
+
function isSafeRustCommandCall(call, pattern, language) {
|
|
12051
|
+
if (language !== "rust")
|
|
12052
|
+
return false;
|
|
12053
|
+
if (pattern.type !== "command_injection")
|
|
12054
|
+
return false;
|
|
12055
|
+
if (pattern.class !== undefined && pattern.class !== "Command")
|
|
12056
|
+
return false;
|
|
12057
|
+
const SHELL_PROGRAMS = new Set([
|
|
12058
|
+
"sh",
|
|
12059
|
+
"bash",
|
|
12060
|
+
"zsh",
|
|
12061
|
+
"dash",
|
|
12062
|
+
"ash",
|
|
12063
|
+
"ksh",
|
|
12064
|
+
"cmd",
|
|
12065
|
+
"cmd.exe",
|
|
12066
|
+
"powershell",
|
|
12067
|
+
"pwsh",
|
|
12068
|
+
"powershell.exe",
|
|
12069
|
+
"pwsh.exe"
|
|
12070
|
+
]);
|
|
12071
|
+
const PROGRAM_RE = /\bCommand\s*::\s*new\s*\(\s*(?:r?"([^"]*)"|'([^']*)')/;
|
|
12072
|
+
const extractProgram = (text) => {
|
|
12073
|
+
const m = PROGRAM_RE.exec(text);
|
|
12074
|
+
if (!m)
|
|
12075
|
+
return null;
|
|
12076
|
+
const lit = m[1] ?? m[2] ?? "";
|
|
12077
|
+
return lit.split("/").pop() ?? lit;
|
|
12078
|
+
};
|
|
12079
|
+
if (pattern.method === "new") {
|
|
12080
|
+
const programArg = call.arguments.find((a) => a.position === 0);
|
|
12081
|
+
if (!programArg)
|
|
12082
|
+
return false;
|
|
12083
|
+
let program;
|
|
12084
|
+
if (programArg.literal !== null && programArg.literal !== undefined) {
|
|
12085
|
+
program = String(programArg.literal).split("/").pop() ?? String(programArg.literal);
|
|
12086
|
+
} else {
|
|
12087
|
+
const expr = (programArg.expression ?? "").trim();
|
|
12088
|
+
if (!(expr.startsWith('"') || expr.startsWith("'"))) {
|
|
12089
|
+
return false;
|
|
12090
|
+
}
|
|
12091
|
+
const stripped = expr.slice(1, -1);
|
|
12092
|
+
program = stripped.split("/").pop() ?? stripped;
|
|
12093
|
+
}
|
|
12094
|
+
return !SHELL_PROGRAMS.has(program);
|
|
12095
|
+
}
|
|
12096
|
+
if (pattern.method === "arg" || pattern.method === "args" || pattern.method === "spawn" || pattern.method === "output") {
|
|
12097
|
+
const receiverText = call.receiver ?? "";
|
|
12098
|
+
const program = extractProgram(receiverText);
|
|
12099
|
+
if (program === null)
|
|
12100
|
+
return false;
|
|
12101
|
+
return !SHELL_PROGRAMS.has(program);
|
|
12102
|
+
}
|
|
12103
|
+
return false;
|
|
12104
|
+
}
|
|
12056
12105
|
var CLASS_LITERAL_RE = /^(?:[A-Za-z_][\w]*\.)*[A-Z][\w]*(?:\[\])*\.class$/;
|
|
12057
12106
|
function argIsClassLiteral(call, position) {
|
|
12058
12107
|
const arg = call.arguments.find((a) => a.position === position);
|
|
@@ -12077,6 +12126,9 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines) {
|
|
|
12077
12126
|
if (isSafeGoExecCommandCall(call, pattern, language)) {
|
|
12078
12127
|
continue;
|
|
12079
12128
|
}
|
|
12129
|
+
if (isSafeRustCommandCall(call, pattern, language)) {
|
|
12130
|
+
continue;
|
|
12131
|
+
}
|
|
12080
12132
|
if (pattern.safe_if_class_literal_at !== undefined && argIsClassLiteral(call, pattern.safe_if_class_literal_at)) {
|
|
12081
12133
|
continue;
|
|
12082
12134
|
}
|
|
@@ -21313,6 +21365,14 @@ class LanguageSourcesPass {
|
|
|
21313
21365
|
additionalSanitizers.push(...findGoMapAllowlistGuardSanitizers(code));
|
|
21314
21366
|
additionalSanitizers.push(...findGoHtmlTemplateImportSanitizers(code));
|
|
21315
21367
|
}
|
|
21368
|
+
if (language === "python") {
|
|
21369
|
+
additionalSanitizers.push(...findPythonNetlocAllowlistGuardSanitizers(code));
|
|
21370
|
+
additionalSanitizers.push(...findPythonRangeCheckGuardSanitizers(code));
|
|
21371
|
+
}
|
|
21372
|
+
if (language === "rust") {
|
|
21373
|
+
additionalSanitizers.push(...findRustSetAllowlistGuardSanitizers(code));
|
|
21374
|
+
additionalSanitizers.push(...findRustCanonicalizeGuardSanitizers(code));
|
|
21375
|
+
}
|
|
21316
21376
|
attachSourceLineCode(additionalSources, additionalSinks, code);
|
|
21317
21377
|
return { additionalSources, additionalSinks, additionalSanitizers, pyTaintedVars, pySanitizedVars, jsTaintedVars };
|
|
21318
21378
|
}
|
|
@@ -22427,6 +22487,210 @@ function findGoHtmlTemplateImportSanitizers(code) {
|
|
|
22427
22487
|
}
|
|
22428
22488
|
return sanitizers;
|
|
22429
22489
|
}
|
|
22490
|
+
function findPythonNetlocAllowlistGuardSanitizers(code) {
|
|
22491
|
+
const sanitizers = [];
|
|
22492
|
+
const lines = code.split(`
|
|
22493
|
+
`);
|
|
22494
|
+
const guardOpen = /^(\s*)if\s+.+?\s+not\s+in\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*$/;
|
|
22495
|
+
const allowlistName = /^(?:[A-Z][A-Z0-9_]+|.*?(allowed|accepted|whitelist|permitted|valid|approved).*)$/i;
|
|
22496
|
+
const terminator = /\b(return|raise|abort\s*\(|sys\.exit\s*\()/;
|
|
22497
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
22498
|
+
const m = guardOpen.exec(lines[i2]);
|
|
22499
|
+
if (!m)
|
|
22500
|
+
continue;
|
|
22501
|
+
const guardIndent = m[1].length;
|
|
22502
|
+
const allowName = m[2];
|
|
22503
|
+
if (!allowlistName.test(allowName))
|
|
22504
|
+
continue;
|
|
22505
|
+
let bodyHasTerminator = false;
|
|
22506
|
+
let blockEnd = -1;
|
|
22507
|
+
const maxScan = Math.min(lines.length, i2 + 26);
|
|
22508
|
+
for (let j = i2 + 1;j < maxScan; j++) {
|
|
22509
|
+
const line = lines[j];
|
|
22510
|
+
if (line.trim() === "")
|
|
22511
|
+
continue;
|
|
22512
|
+
const indent = line.length - line.trimStart().length;
|
|
22513
|
+
if (indent <= guardIndent) {
|
|
22514
|
+
blockEnd = j - 1;
|
|
22515
|
+
break;
|
|
22516
|
+
}
|
|
22517
|
+
if (terminator.test(line))
|
|
22518
|
+
bodyHasTerminator = true;
|
|
22519
|
+
}
|
|
22520
|
+
if (blockEnd === -1)
|
|
22521
|
+
blockEnd = Math.min(lines.length - 1, i2 + 25);
|
|
22522
|
+
if (!bodyHasTerminator)
|
|
22523
|
+
continue;
|
|
22524
|
+
for (let l = blockEnd + 2;l <= lines.length; l++) {
|
|
22525
|
+
sanitizers.push({
|
|
22526
|
+
type: "python_netloc_allowlist_guard",
|
|
22527
|
+
method: "if",
|
|
22528
|
+
line: l,
|
|
22529
|
+
sanitizes: [
|
|
22530
|
+
"open_redirect",
|
|
22531
|
+
"ssrf",
|
|
22532
|
+
"path_traversal",
|
|
22533
|
+
"external_taint_escape"
|
|
22534
|
+
]
|
|
22535
|
+
});
|
|
22536
|
+
}
|
|
22537
|
+
}
|
|
22538
|
+
return sanitizers;
|
|
22539
|
+
}
|
|
22540
|
+
function findPythonRangeCheckGuardSanitizers(code) {
|
|
22541
|
+
const sanitizers = [];
|
|
22542
|
+
const lines = code.split(`
|
|
22543
|
+
`);
|
|
22544
|
+
const rangeGuard = /^(\s*)if\s+([A-Za-z_][A-Za-z0-9_]*)\s*[<>]=?\s*(?:\d+|-?\d+\.?\d*|[A-Z][A-Z0-9_]+)\s*(?:(?:or|and)\s+\2\s*[<>]=?\s*(?:\d+|-?\d+\.?\d*|[A-Z][A-Z0-9_]+)\s*)?:\s*$/;
|
|
22545
|
+
const terminator = /\b(return|raise|abort\s*\(|sys\.exit\s*\()/;
|
|
22546
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
22547
|
+
const m = rangeGuard.exec(lines[i2]);
|
|
22548
|
+
if (!m)
|
|
22549
|
+
continue;
|
|
22550
|
+
const guardIndent = m[1].length;
|
|
22551
|
+
let bodyHasTerminator = false;
|
|
22552
|
+
let blockEnd = -1;
|
|
22553
|
+
const maxScan = Math.min(lines.length, i2 + 26);
|
|
22554
|
+
for (let j = i2 + 1;j < maxScan; j++) {
|
|
22555
|
+
const line = lines[j];
|
|
22556
|
+
if (line.trim() === "")
|
|
22557
|
+
continue;
|
|
22558
|
+
const indent = line.length - line.trimStart().length;
|
|
22559
|
+
if (indent <= guardIndent) {
|
|
22560
|
+
blockEnd = j - 1;
|
|
22561
|
+
break;
|
|
22562
|
+
}
|
|
22563
|
+
if (terminator.test(line))
|
|
22564
|
+
bodyHasTerminator = true;
|
|
22565
|
+
}
|
|
22566
|
+
if (blockEnd === -1)
|
|
22567
|
+
blockEnd = Math.min(lines.length - 1, i2 + 25);
|
|
22568
|
+
if (!bodyHasTerminator)
|
|
22569
|
+
continue;
|
|
22570
|
+
for (let l = blockEnd + 2;l <= lines.length; l++) {
|
|
22571
|
+
sanitizers.push({
|
|
22572
|
+
type: "python_range_check_guard",
|
|
22573
|
+
method: "if",
|
|
22574
|
+
line: l,
|
|
22575
|
+
sanitizes: ["xss", "external_taint_escape"]
|
|
22576
|
+
});
|
|
22577
|
+
}
|
|
22578
|
+
}
|
|
22579
|
+
return sanitizers;
|
|
22580
|
+
}
|
|
22581
|
+
function findRustSetAllowlistGuardSanitizers(code) {
|
|
22582
|
+
const sanitizers = [];
|
|
22583
|
+
const lines = code.split(`
|
|
22584
|
+
`);
|
|
22585
|
+
const guardOpen = /^\s*if\s+!\s*([A-Za-z_][A-Za-z0-9_]*)\s*\.\s*(?:contains|contains_key)\s*\(/;
|
|
22586
|
+
const allowlistName = /^(?:[A-Z][A-Z0-9_]+|.*?(allowed|accepted|whitelist|permitted|valid|approved).*)$/i;
|
|
22587
|
+
const terminator = /\b(return|Err\s*\(|panic!\s*\(|HttpResponse::(?:Forbidden|BadRequest|Unauthorized))/;
|
|
22588
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
22589
|
+
const m = guardOpen.exec(lines[i2]);
|
|
22590
|
+
if (!m)
|
|
22591
|
+
continue;
|
|
22592
|
+
const setName = m[1];
|
|
22593
|
+
if (!allowlistName.test(setName))
|
|
22594
|
+
continue;
|
|
22595
|
+
let depth = 0;
|
|
22596
|
+
for (const ch of lines[i2]) {
|
|
22597
|
+
if (ch === "{")
|
|
22598
|
+
depth++;
|
|
22599
|
+
else if (ch === "}")
|
|
22600
|
+
depth--;
|
|
22601
|
+
}
|
|
22602
|
+
if (depth <= 0)
|
|
22603
|
+
continue;
|
|
22604
|
+
let closeLine = -1;
|
|
22605
|
+
let bodyHasTerminator = false;
|
|
22606
|
+
const maxScan = Math.min(lines.length, i2 + 26);
|
|
22607
|
+
for (let j = i2 + 1;j < maxScan; j++) {
|
|
22608
|
+
const line = lines[j];
|
|
22609
|
+
if (terminator.test(line))
|
|
22610
|
+
bodyHasTerminator = true;
|
|
22611
|
+
for (const ch of line) {
|
|
22612
|
+
if (ch === "{")
|
|
22613
|
+
depth++;
|
|
22614
|
+
else if (ch === "}")
|
|
22615
|
+
depth--;
|
|
22616
|
+
}
|
|
22617
|
+
if (depth === 0) {
|
|
22618
|
+
closeLine = j;
|
|
22619
|
+
break;
|
|
22620
|
+
}
|
|
22621
|
+
}
|
|
22622
|
+
if (closeLine === -1 || !bodyHasTerminator)
|
|
22623
|
+
continue;
|
|
22624
|
+
for (let l = closeLine + 2;l <= lines.length; l++) {
|
|
22625
|
+
sanitizers.push({
|
|
22626
|
+
type: "rust_set_allowlist_guard",
|
|
22627
|
+
method: "if",
|
|
22628
|
+
line: l,
|
|
22629
|
+
sanitizes: [
|
|
22630
|
+
"ssrf",
|
|
22631
|
+
"open_redirect",
|
|
22632
|
+
"command_injection",
|
|
22633
|
+
"external_taint_escape"
|
|
22634
|
+
]
|
|
22635
|
+
});
|
|
22636
|
+
}
|
|
22637
|
+
}
|
|
22638
|
+
return sanitizers;
|
|
22639
|
+
}
|
|
22640
|
+
function findRustCanonicalizeGuardSanitizers(code) {
|
|
22641
|
+
const sanitizers = [];
|
|
22642
|
+
const lines = code.split(`
|
|
22643
|
+
`);
|
|
22644
|
+
const guardOpen = /^\s*if\s+!\s*[A-Za-z_][\w?.()&]*\.starts_with\s*\(/;
|
|
22645
|
+
const terminator = /\b(return|Err\s*\(|panic!\s*\(|HttpResponse::(?:Forbidden|BadRequest|Unauthorized|NotFound))/;
|
|
22646
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
22647
|
+
if (!guardOpen.test(lines[i2]))
|
|
22648
|
+
continue;
|
|
22649
|
+
let depth = 0;
|
|
22650
|
+
for (const ch of lines[i2]) {
|
|
22651
|
+
if (ch === "{")
|
|
22652
|
+
depth++;
|
|
22653
|
+
else if (ch === "}")
|
|
22654
|
+
depth--;
|
|
22655
|
+
}
|
|
22656
|
+
if (depth <= 0)
|
|
22657
|
+
continue;
|
|
22658
|
+
let closeLine = -1;
|
|
22659
|
+
let bodyHasTerminator = false;
|
|
22660
|
+
const maxScan = Math.min(lines.length, i2 + 26);
|
|
22661
|
+
for (let j = i2 + 1;j < maxScan; j++) {
|
|
22662
|
+
const line = lines[j];
|
|
22663
|
+
if (terminator.test(line))
|
|
22664
|
+
bodyHasTerminator = true;
|
|
22665
|
+
for (const ch of line) {
|
|
22666
|
+
if (ch === "{")
|
|
22667
|
+
depth++;
|
|
22668
|
+
else if (ch === "}")
|
|
22669
|
+
depth--;
|
|
22670
|
+
}
|
|
22671
|
+
if (depth === 0) {
|
|
22672
|
+
closeLine = j;
|
|
22673
|
+
break;
|
|
22674
|
+
}
|
|
22675
|
+
}
|
|
22676
|
+
if (closeLine === -1 || !bodyHasTerminator)
|
|
22677
|
+
continue;
|
|
22678
|
+
for (let l = closeLine + 2;l <= lines.length; l++) {
|
|
22679
|
+
sanitizers.push({
|
|
22680
|
+
type: "rust_canonicalize_guard",
|
|
22681
|
+
method: "if",
|
|
22682
|
+
line: l,
|
|
22683
|
+
sanitizes: [
|
|
22684
|
+
"path_traversal",
|
|
22685
|
+
"xss",
|
|
22686
|
+
"ssrf",
|
|
22687
|
+
"external_taint_escape"
|
|
22688
|
+
]
|
|
22689
|
+
});
|
|
22690
|
+
}
|
|
22691
|
+
}
|
|
22692
|
+
return sanitizers;
|
|
22693
|
+
}
|
|
22430
22694
|
|
|
22431
22695
|
// ../circle-ir/dist/analysis/passes/sink-filter-pass.js
|
|
22432
22696
|
var JS_XSS_SANITIZERS = [
|
|
@@ -33592,7 +33856,7 @@ var colors = {
|
|
|
33592
33856
|
};
|
|
33593
33857
|
|
|
33594
33858
|
// src/version.ts
|
|
33595
|
-
var version = "3.
|
|
33859
|
+
var version = "3.84.0";
|
|
33596
33860
|
|
|
33597
33861
|
// src/formatters.ts
|
|
33598
33862
|
var SINK_SEVERITY = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognium-dev",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.84.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.
|
|
68
|
+
"circle-ir": "^3.84.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/node": "^25.5.0",
|