cognium-dev 3.83.0 → 3.85.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 +410 -6
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -12047,6 +12047,61 @@ function isSafeGoExecCommandCall(call, pattern, language) {
|
|
|
12047
12047
|
return false;
|
|
12048
12048
|
return true;
|
|
12049
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
|
+
}
|
|
12050
12105
|
var CLASS_LITERAL_RE = /^(?:[A-Za-z_][\w]*\.)*[A-Z][\w]*(?:\[\])*\.class$/;
|
|
12051
12106
|
function argIsClassLiteral(call, position) {
|
|
12052
12107
|
const arg = call.arguments.find((a) => a.position === position);
|
|
@@ -12071,6 +12126,9 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines) {
|
|
|
12071
12126
|
if (isSafeGoExecCommandCall(call, pattern, language)) {
|
|
12072
12127
|
continue;
|
|
12073
12128
|
}
|
|
12129
|
+
if (isSafeRustCommandCall(call, pattern, language)) {
|
|
12130
|
+
continue;
|
|
12131
|
+
}
|
|
12074
12132
|
if (pattern.safe_if_class_literal_at !== undefined && argIsClassLiteral(call, pattern.safe_if_class_literal_at)) {
|
|
12075
12133
|
continue;
|
|
12076
12134
|
}
|
|
@@ -21307,6 +21365,14 @@ class LanguageSourcesPass {
|
|
|
21307
21365
|
additionalSanitizers.push(...findGoMapAllowlistGuardSanitizers(code));
|
|
21308
21366
|
additionalSanitizers.push(...findGoHtmlTemplateImportSanitizers(code));
|
|
21309
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
|
+
}
|
|
21310
21376
|
attachSourceLineCode(additionalSources, additionalSinks, code);
|
|
21311
21377
|
return { additionalSources, additionalSinks, additionalSanitizers, pyTaintedVars, pySanitizedVars, jsTaintedVars };
|
|
21312
21378
|
}
|
|
@@ -22421,6 +22487,210 @@ function findGoHtmlTemplateImportSanitizers(code) {
|
|
|
22421
22487
|
}
|
|
22422
22488
|
return sanitizers;
|
|
22423
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
|
+
}
|
|
22424
22694
|
|
|
22425
22695
|
// ../circle-ir/dist/analysis/passes/sink-filter-pass.js
|
|
22426
22696
|
var JS_XSS_SANITIZERS = [
|
|
@@ -28687,6 +28957,11 @@ var TEST_FILENAME_RE = /(?:\.(?:test|spec)\.[cm]?[jt]sx?|_test\.go|_test\.py|Tes
|
|
|
28687
28957
|
function isTestFile(file) {
|
|
28688
28958
|
return TEST_PATH_RE3.test(file) || TEST_FILENAME_RE.test(file);
|
|
28689
28959
|
}
|
|
28960
|
+
var GENERATED_PATH_RE = /(?:^|[\\/])(?:gen|generated|build[\\/]generated|src[\\/](?:main|test)[\\/]generated|target[\\/]generated-sources|target[\\/]generated-test-sources|node_modules[\\/]\.cache)(?:[\\/]|$)/i;
|
|
28961
|
+
var GENERATED_FILENAME_RE = /__[ch]\.java$|\.pb\.go$|_pb2\.py$|\.generated\.[cm]?[jt]sx?$/i;
|
|
28962
|
+
function isGeneratedFile(file) {
|
|
28963
|
+
return GENERATED_PATH_RE.test(file) || GENERATED_FILENAME_RE.test(file);
|
|
28964
|
+
}
|
|
28690
28965
|
var PROVIDER_PATTERNS = [
|
|
28691
28966
|
{
|
|
28692
28967
|
name: "AWS access key",
|
|
@@ -28867,6 +29142,126 @@ function shannonEntropy(s) {
|
|
|
28867
29142
|
return h;
|
|
28868
29143
|
}
|
|
28869
29144
|
var CREDENTIAL_NAME_RE = /(?:key|secret|token|password|passwd|credential|api[_-]?key)/i;
|
|
29145
|
+
function findAnnotationLineRanges(code) {
|
|
29146
|
+
const lines = code.split(`
|
|
29147
|
+
`);
|
|
29148
|
+
const inAnnotation = new Set;
|
|
29149
|
+
const OPEN_RE = /(?:@[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*\s*\(|#\[)/g;
|
|
29150
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
29151
|
+
OPEN_RE.lastIndex = 0;
|
|
29152
|
+
let m;
|
|
29153
|
+
while ((m = OPEN_RE.exec(lines[i2])) !== null) {
|
|
29154
|
+
const isRustAttr = m[0].startsWith("#[");
|
|
29155
|
+
const openCh = isRustAttr ? "[" : "(";
|
|
29156
|
+
const closeCh = isRustAttr ? "]" : ")";
|
|
29157
|
+
let depth = 1;
|
|
29158
|
+
let li = i2;
|
|
29159
|
+
let col = m.index + m[0].length;
|
|
29160
|
+
let lineBudget = 200;
|
|
29161
|
+
inAnnotation.add(li + 1);
|
|
29162
|
+
while (depth > 0 && li < lines.length && lineBudget > 0) {
|
|
29163
|
+
const ln = lines[li];
|
|
29164
|
+
let inStr = null;
|
|
29165
|
+
while (col < ln.length && depth > 0) {
|
|
29166
|
+
const ch = ln[col];
|
|
29167
|
+
if (inStr !== null) {
|
|
29168
|
+
if (ch === "\\") {
|
|
29169
|
+
col += 2;
|
|
29170
|
+
continue;
|
|
29171
|
+
}
|
|
29172
|
+
if (ch === inStr)
|
|
29173
|
+
inStr = null;
|
|
29174
|
+
} else if (ch === '"' || ch === "'" || ch === "`") {
|
|
29175
|
+
inStr = ch;
|
|
29176
|
+
} else if (ch === openCh) {
|
|
29177
|
+
depth++;
|
|
29178
|
+
} else if (ch === closeCh) {
|
|
29179
|
+
depth--;
|
|
29180
|
+
}
|
|
29181
|
+
col++;
|
|
29182
|
+
}
|
|
29183
|
+
if (depth > 0) {
|
|
29184
|
+
li++;
|
|
29185
|
+
col = 0;
|
|
29186
|
+
lineBudget--;
|
|
29187
|
+
if (li < lines.length)
|
|
29188
|
+
inAnnotation.add(li + 1);
|
|
29189
|
+
}
|
|
29190
|
+
}
|
|
29191
|
+
}
|
|
29192
|
+
}
|
|
29193
|
+
return inAnnotation;
|
|
29194
|
+
}
|
|
29195
|
+
function findStringArrayLineRanges(code) {
|
|
29196
|
+
const lines = code.split(`
|
|
29197
|
+
`);
|
|
29198
|
+
const inArray = new Set;
|
|
29199
|
+
const OPEN_RE = /=\s*([{\[])/g;
|
|
29200
|
+
const STR_LITERAL_COUNT_RE = /(["'`])(?:\\.|(?!\1).)*\1/g;
|
|
29201
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
29202
|
+
OPEN_RE.lastIndex = 0;
|
|
29203
|
+
let m;
|
|
29204
|
+
while ((m = OPEN_RE.exec(lines[i2])) !== null) {
|
|
29205
|
+
const openCh = m[1];
|
|
29206
|
+
const closeCh = openCh === "{" ? "}" : "]";
|
|
29207
|
+
let depth = 1;
|
|
29208
|
+
let li = i2;
|
|
29209
|
+
let col = m.index + m[0].length;
|
|
29210
|
+
let lineBudget = 500;
|
|
29211
|
+
const spanLines = [li + 1];
|
|
29212
|
+
let spanText = "";
|
|
29213
|
+
while (depth > 0 && li < lines.length && lineBudget > 0) {
|
|
29214
|
+
const ln = lines[li];
|
|
29215
|
+
let inStr = null;
|
|
29216
|
+
const start2 = col;
|
|
29217
|
+
while (col < ln.length && depth > 0) {
|
|
29218
|
+
const ch = ln[col];
|
|
29219
|
+
if (inStr !== null) {
|
|
29220
|
+
if (ch === "\\") {
|
|
29221
|
+
col += 2;
|
|
29222
|
+
continue;
|
|
29223
|
+
}
|
|
29224
|
+
if (ch === inStr)
|
|
29225
|
+
inStr = null;
|
|
29226
|
+
} else if (ch === '"' || ch === "'" || ch === "`") {
|
|
29227
|
+
inStr = ch;
|
|
29228
|
+
} else if (ch === openCh) {
|
|
29229
|
+
depth++;
|
|
29230
|
+
} else if (ch === closeCh) {
|
|
29231
|
+
depth--;
|
|
29232
|
+
}
|
|
29233
|
+
col++;
|
|
29234
|
+
}
|
|
29235
|
+
spanText += ln.substring(start2, col) + `
|
|
29236
|
+
`;
|
|
29237
|
+
if (depth > 0) {
|
|
29238
|
+
li++;
|
|
29239
|
+
col = 0;
|
|
29240
|
+
lineBudget--;
|
|
29241
|
+
if (li < lines.length)
|
|
29242
|
+
spanLines.push(li + 1);
|
|
29243
|
+
}
|
|
29244
|
+
}
|
|
29245
|
+
STR_LITERAL_COUNT_RE.lastIndex = 0;
|
|
29246
|
+
let strCount = 0;
|
|
29247
|
+
while (STR_LITERAL_COUNT_RE.exec(spanText) !== null) {
|
|
29248
|
+
strCount++;
|
|
29249
|
+
if (strCount >= 3)
|
|
29250
|
+
break;
|
|
29251
|
+
}
|
|
29252
|
+
if (strCount >= 3) {
|
|
29253
|
+
for (const ln of spanLines)
|
|
29254
|
+
inArray.add(ln);
|
|
29255
|
+
}
|
|
29256
|
+
}
|
|
29257
|
+
}
|
|
29258
|
+
return inArray;
|
|
29259
|
+
}
|
|
29260
|
+
var FIELD_ASSIGN_RE = /(?:^|[\s,(])([A-Za-z_$][\w$]*)\s*[:=]\s*["'`]/;
|
|
29261
|
+
function extractEnclosingFieldName(lineText) {
|
|
29262
|
+
const m = FIELD_ASSIGN_RE.exec(lineText);
|
|
29263
|
+
return m ? m[1] : null;
|
|
29264
|
+
}
|
|
28870
29265
|
var TEST_CALL_RE = /\b(?:expect|assert|describe|it|test)\s*\(/;
|
|
28871
29266
|
var COMMENT_EXAMPLE_RE = /(?:\/\/|#)\s*(?:example|sample|test|fixture)/i;
|
|
28872
29267
|
|
|
@@ -28875,7 +29270,7 @@ class ScanSecretsPass {
|
|
|
28875
29270
|
category = "security";
|
|
28876
29271
|
run(ctx) {
|
|
28877
29272
|
const file = ctx.graph.ir.meta.file;
|
|
28878
|
-
if (isTestFile(file)) {
|
|
29273
|
+
if (isTestFile(file) || isGeneratedFile(file)) {
|
|
28879
29274
|
return { providerFindings: 0, entropyFindings: 0 };
|
|
28880
29275
|
}
|
|
28881
29276
|
const lines = ctx.code.split(`
|
|
@@ -28889,6 +29284,8 @@ class ScanSecretsPass {
|
|
|
28889
29284
|
seen.add(`${f.line}:${f.rule_id}`);
|
|
28890
29285
|
}
|
|
28891
29286
|
}
|
|
29287
|
+
const annotationLines = findAnnotationLineRanges(ctx.code);
|
|
29288
|
+
const arrayLines = findStringArrayLineRanges(ctx.code);
|
|
28892
29289
|
let providerFindings = 0;
|
|
28893
29290
|
let entropyFindings = 0;
|
|
28894
29291
|
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
@@ -28955,12 +29352,18 @@ class ScanSecretsPass {
|
|
|
28955
29352
|
continue;
|
|
28956
29353
|
if (COMMENT_EXAMPLE_RE.test(lineText))
|
|
28957
29354
|
continue;
|
|
29355
|
+
if (annotationLines.has(lineNum))
|
|
29356
|
+
continue;
|
|
29357
|
+
if (arrayLines.has(lineNum))
|
|
29358
|
+
continue;
|
|
28958
29359
|
STRING_LITERAL_RE.lastIndex = 0;
|
|
28959
29360
|
let match;
|
|
28960
29361
|
while ((match = STRING_LITERAL_RE.exec(lineText)) !== null) {
|
|
28961
29362
|
const value = match[2];
|
|
28962
29363
|
if (!this.isCandidate(value))
|
|
28963
29364
|
continue;
|
|
29365
|
+
if (value.length < 32)
|
|
29366
|
+
continue;
|
|
28964
29367
|
if (!this.passesEntropyGate(value, lineText))
|
|
28965
29368
|
continue;
|
|
28966
29369
|
const key = `${lineNum}:hardcoded-credential-entropy`;
|
|
@@ -29007,11 +29410,12 @@ class ScanSecretsPass {
|
|
|
29007
29410
|
return true;
|
|
29008
29411
|
}
|
|
29009
29412
|
passesEntropyGate(value, lineText) {
|
|
29413
|
+
const fieldName = extractEnclosingFieldName(lineText);
|
|
29414
|
+
if (fieldName === null || !CREDENTIAL_NAME_RE.test(fieldName))
|
|
29415
|
+
return false;
|
|
29010
29416
|
const isHex = HEXISH_RE.test(value);
|
|
29011
|
-
const
|
|
29012
|
-
|
|
29013
|
-
const h = shannonEntropy(value);
|
|
29014
|
-
return h >= threshold;
|
|
29417
|
+
const threshold = isHex ? 3.3 : 4.1;
|
|
29418
|
+
return shannonEntropy(value) >= threshold;
|
|
29015
29419
|
}
|
|
29016
29420
|
}
|
|
29017
29421
|
|
|
@@ -33586,7 +33990,7 @@ var colors = {
|
|
|
33586
33990
|
};
|
|
33587
33991
|
|
|
33588
33992
|
// src/version.ts
|
|
33589
|
-
var version = "3.
|
|
33993
|
+
var version = "3.85.0";
|
|
33590
33994
|
|
|
33591
33995
|
// src/formatters.ts
|
|
33592
33996
|
var SINK_SEVERITY = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognium-dev",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.85.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.85.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/node": "^25.5.0",
|