cognium-dev 3.194.0 → 3.197.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 +497 -573
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -10719,7 +10719,7 @@ var DEFAULT_SOURCES = [
|
|
|
10719
10719
|
{ method: "Json", type: "http_body", severity: "high", return_tainted: true, languages: ["rust"] },
|
|
10720
10720
|
{ method: "Query", type: "http_param", severity: "high", return_tainted: true, languages: ["rust"] },
|
|
10721
10721
|
{ method: "Path", type: "http_path", severity: "high", return_tainted: true, languages: ["rust"] },
|
|
10722
|
-
{ method: "Form", type: "
|
|
10722
|
+
{ method: "Form", type: "http_body", severity: "high", return_tainted: true, languages: ["rust"] },
|
|
10723
10723
|
{ method: "var", class: "env", type: "env_input", severity: "medium", return_tainted: true },
|
|
10724
10724
|
{ method: "var_os", class: "env", type: "env_input", severity: "medium", return_tainted: true },
|
|
10725
10725
|
{ method: "args", class: "env", type: "env_input", severity: "medium", return_tainted: true },
|
|
@@ -11508,7 +11508,7 @@ var DEFAULT_SINKS = [
|
|
|
11508
11508
|
{ method: "execSync", class: "child_process", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
11509
11509
|
{ method: "spawn", class: "child_process", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
11510
11510
|
{ method: "spawnSync", class: "child_process", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
|
|
11511
|
-
{ method: "exec", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0] },
|
|
11511
|
+
{ method: "exec", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], exclude_languages: ["python"] },
|
|
11512
11512
|
{ method: "execSync", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
11513
11513
|
{ method: "spawn", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
11514
11514
|
{ method: "spawnSync", type: "command_injection", cwe: "CWE-78", severity: "high", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
@@ -11528,7 +11528,7 @@ var DEFAULT_SINKS = [
|
|
|
11528
11528
|
{ method: "query", class: "Client", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"], allow_unresolved_receiver: true },
|
|
11529
11529
|
{ method: "execute", class: "Pool", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"], allow_unresolved_receiver: true },
|
|
11530
11530
|
{ method: "execute", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"], allow_unresolved_receiver: true },
|
|
11531
|
-
{ method: "raw", type: "sql_injection", cwe: "CWE-89", severity: "
|
|
11531
|
+
{ method: "raw", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"] },
|
|
11532
11532
|
{ method: "all", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"], allow_unresolved_receiver: true },
|
|
11533
11533
|
{ method: "run", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"], allow_unresolved_receiver: true },
|
|
11534
11534
|
{ method: "each", class: "Connection", type: "sql_injection", cwe: "CWE-89", severity: "critical", arg_positions: [0], languages: ["javascript", "typescript"], allow_unresolved_receiver: true },
|
|
@@ -12483,6 +12483,17 @@ function analyzeTaint(calls, types, config = getDefaultConfig(), typeHierarchy,
|
|
|
12483
12483
|
const sanitizers = findSanitizers(calls, types, config.sanitizers, sourceLines);
|
|
12484
12484
|
return { sources, sinks, sanitizers };
|
|
12485
12485
|
}
|
|
12486
|
+
function sinkPatternAppliesTo(pattern, language) {
|
|
12487
|
+
if (language === undefined)
|
|
12488
|
+
return true;
|
|
12489
|
+
if (pattern.languages && pattern.languages.length > 0 && !pattern.languages.includes(language)) {
|
|
12490
|
+
return false;
|
|
12491
|
+
}
|
|
12492
|
+
if (pattern.exclude_languages && pattern.exclude_languages.includes(language)) {
|
|
12493
|
+
return false;
|
|
12494
|
+
}
|
|
12495
|
+
return true;
|
|
12496
|
+
}
|
|
12486
12497
|
function expandPromisifyAliases(patterns, sourceLines, language) {
|
|
12487
12498
|
if (!sourceLines || sourceLines.length === 0)
|
|
12488
12499
|
return patterns;
|
|
@@ -12491,7 +12502,7 @@ function expandPromisifyAliases(patterns, sourceLines, language) {
|
|
|
12491
12502
|
const PROMISIFY_RE = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:util\s*\.\s*)?promisify\s*\(\s*([A-Za-z_$][\w$]*)\s*\)/;
|
|
12492
12503
|
const innerToPattern = new Map;
|
|
12493
12504
|
for (const p of patterns) {
|
|
12494
|
-
if (p
|
|
12505
|
+
if (!sinkPatternAppliesTo(p, language))
|
|
12495
12506
|
continue;
|
|
12496
12507
|
if (p.class !== undefined)
|
|
12497
12508
|
continue;
|
|
@@ -12499,7 +12510,7 @@ function expandPromisifyAliases(patterns, sourceLines, language) {
|
|
|
12499
12510
|
innerToPattern.set(p.method, p);
|
|
12500
12511
|
}
|
|
12501
12512
|
for (const p of patterns) {
|
|
12502
|
-
if (p
|
|
12513
|
+
if (!sinkPatternAppliesTo(p, language))
|
|
12503
12514
|
continue;
|
|
12504
12515
|
if (innerToPattern.has(p.method))
|
|
12505
12516
|
continue;
|
|
@@ -12541,7 +12552,7 @@ function expandIndirectEvalAliases(patterns, sourceLines, language) {
|
|
|
12541
12552
|
const INDIRECT_EVAL_RE = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*(?::[^=]+)?=\s*(eval|Function)\b(?!\s*\()/;
|
|
12542
12553
|
const innerToPattern = new Map;
|
|
12543
12554
|
for (const p of patterns) {
|
|
12544
|
-
if (p
|
|
12555
|
+
if (!sinkPatternAppliesTo(p, language))
|
|
12545
12556
|
continue;
|
|
12546
12557
|
if (p.class !== undefined)
|
|
12547
12558
|
continue;
|
|
@@ -13301,7 +13312,7 @@ function isSafeJinjaRenderCall(call, pattern, language, sourceLines) {
|
|
|
13301
13312
|
return false;
|
|
13302
13313
|
}
|
|
13303
13314
|
function findSinks(calls, patterns, typeHierarchy, language, sourceLines, types) {
|
|
13304
|
-
const patternsForLanguage = language === undefined ? patterns : patterns.filter((p) =>
|
|
13315
|
+
const patternsForLanguage = language === undefined ? patterns : patterns.filter((p) => sinkPatternAppliesTo(p, language));
|
|
13305
13316
|
const sinkMap = new Map;
|
|
13306
13317
|
for (const call of calls) {
|
|
13307
13318
|
for (const pattern of patternsForLanguage) {
|
|
@@ -13636,10 +13647,8 @@ var SINK_FQN_EXCLUSIONS = {
|
|
|
13636
13647
|
]
|
|
13637
13648
|
};
|
|
13638
13649
|
function matchesSinkPattern(call, pattern, typeHierarchy, language) {
|
|
13639
|
-
if (pattern
|
|
13640
|
-
|
|
13641
|
-
return false;
|
|
13642
|
-
}
|
|
13650
|
+
if (!sinkPatternAppliesTo(pattern, language)) {
|
|
13651
|
+
return false;
|
|
13643
13652
|
}
|
|
13644
13653
|
const callMethodName = call.method_name;
|
|
13645
13654
|
const patternMethod = pattern.method;
|
|
@@ -20987,99 +20996,11 @@ class JavaPlugin extends BaseLanguagePlugin {
|
|
|
20987
20996
|
severity: "high",
|
|
20988
20997
|
confidence: 0.9,
|
|
20989
20998
|
returnTainted: true
|
|
20990
|
-
},
|
|
20991
|
-
{
|
|
20992
|
-
method: "getParameter",
|
|
20993
|
-
class: "HttpServletRequest",
|
|
20994
|
-
type: "http_param",
|
|
20995
|
-
severity: "high",
|
|
20996
|
-
confidence: 0.95,
|
|
20997
|
-
returnTainted: true
|
|
20998
|
-
},
|
|
20999
|
-
{
|
|
21000
|
-
method: "getParameterValues",
|
|
21001
|
-
class: "HttpServletRequest",
|
|
21002
|
-
type: "http_param",
|
|
21003
|
-
severity: "high",
|
|
21004
|
-
confidence: 0.95,
|
|
21005
|
-
returnTainted: true
|
|
21006
|
-
},
|
|
21007
|
-
{
|
|
21008
|
-
method: "getHeader",
|
|
21009
|
-
class: "HttpServletRequest",
|
|
21010
|
-
type: "http_header",
|
|
21011
|
-
severity: "high",
|
|
21012
|
-
confidence: 0.9,
|
|
21013
|
-
returnTainted: true
|
|
21014
|
-
},
|
|
21015
|
-
{
|
|
21016
|
-
method: "getCookies",
|
|
21017
|
-
class: "HttpServletRequest",
|
|
21018
|
-
type: "http_cookie",
|
|
21019
|
-
severity: "high",
|
|
21020
|
-
confidence: 0.9,
|
|
21021
|
-
returnTainted: true
|
|
21022
|
-
},
|
|
21023
|
-
{
|
|
21024
|
-
method: "getInputStream",
|
|
21025
|
-
class: "HttpServletRequest",
|
|
21026
|
-
type: "http_body",
|
|
21027
|
-
severity: "high",
|
|
21028
|
-
confidence: 0.85,
|
|
21029
|
-
returnTainted: true
|
|
21030
|
-
},
|
|
21031
|
-
{
|
|
21032
|
-
method: "getReader",
|
|
21033
|
-
class: "HttpServletRequest",
|
|
21034
|
-
type: "http_body",
|
|
21035
|
-
severity: "high",
|
|
21036
|
-
confidence: 0.85,
|
|
21037
|
-
returnTainted: true
|
|
21038
20999
|
}
|
|
21039
21000
|
];
|
|
21040
21001
|
}
|
|
21041
21002
|
getBuiltinSinks() {
|
|
21042
21003
|
return [
|
|
21043
|
-
{
|
|
21044
|
-
method: "executeQuery",
|
|
21045
|
-
class: "Statement",
|
|
21046
|
-
type: "sql_injection",
|
|
21047
|
-
cwe: "CWE-89",
|
|
21048
|
-
severity: "critical",
|
|
21049
|
-
argPositions: [0]
|
|
21050
|
-
},
|
|
21051
|
-
{
|
|
21052
|
-
method: "executeUpdate",
|
|
21053
|
-
class: "Statement",
|
|
21054
|
-
type: "sql_injection",
|
|
21055
|
-
cwe: "CWE-89",
|
|
21056
|
-
severity: "critical",
|
|
21057
|
-
argPositions: [0]
|
|
21058
|
-
},
|
|
21059
|
-
{
|
|
21060
|
-
method: "execute",
|
|
21061
|
-
class: "Statement",
|
|
21062
|
-
type: "sql_injection",
|
|
21063
|
-
cwe: "CWE-89",
|
|
21064
|
-
severity: "critical",
|
|
21065
|
-
argPositions: [0]
|
|
21066
|
-
},
|
|
21067
|
-
{
|
|
21068
|
-
method: "exec",
|
|
21069
|
-
class: "Runtime",
|
|
21070
|
-
type: "command_injection",
|
|
21071
|
-
cwe: "CWE-78",
|
|
21072
|
-
severity: "critical",
|
|
21073
|
-
argPositions: [0]
|
|
21074
|
-
},
|
|
21075
|
-
{
|
|
21076
|
-
method: "start",
|
|
21077
|
-
class: "ProcessBuilder",
|
|
21078
|
-
type: "command_injection",
|
|
21079
|
-
cwe: "CWE-78",
|
|
21080
|
-
severity: "critical",
|
|
21081
|
-
argPositions: []
|
|
21082
|
-
},
|
|
21083
21004
|
{
|
|
21084
21005
|
method: "FileInputStream",
|
|
21085
21006
|
type: "path_traversal",
|
|
@@ -21094,38 +21015,6 @@ class JavaPlugin extends BaseLanguagePlugin {
|
|
|
21094
21015
|
severity: "high",
|
|
21095
21016
|
argPositions: [0]
|
|
21096
21017
|
},
|
|
21097
|
-
{
|
|
21098
|
-
method: "write",
|
|
21099
|
-
class: "PrintWriter",
|
|
21100
|
-
type: "xss",
|
|
21101
|
-
cwe: "CWE-79",
|
|
21102
|
-
severity: "high",
|
|
21103
|
-
argPositions: [0]
|
|
21104
|
-
},
|
|
21105
|
-
{
|
|
21106
|
-
method: "println",
|
|
21107
|
-
class: "PrintWriter",
|
|
21108
|
-
type: "xss",
|
|
21109
|
-
cwe: "CWE-79",
|
|
21110
|
-
severity: "high",
|
|
21111
|
-
argPositions: [0]
|
|
21112
|
-
},
|
|
21113
|
-
{
|
|
21114
|
-
method: "search",
|
|
21115
|
-
class: "DirContext",
|
|
21116
|
-
type: "ldap_injection",
|
|
21117
|
-
cwe: "CWE-90",
|
|
21118
|
-
severity: "high",
|
|
21119
|
-
argPositions: [0, 1]
|
|
21120
|
-
},
|
|
21121
|
-
{
|
|
21122
|
-
method: "evaluate",
|
|
21123
|
-
class: "XPath",
|
|
21124
|
-
type: "xpath_injection",
|
|
21125
|
-
cwe: "CWE-643",
|
|
21126
|
-
severity: "high",
|
|
21127
|
-
argPositions: [0]
|
|
21128
|
-
},
|
|
21129
21018
|
{
|
|
21130
21019
|
method: "readObject",
|
|
21131
21020
|
class: "ObjectInputStream",
|
|
@@ -21635,37 +21524,6 @@ class JavaScriptPlugin extends BaseLanguagePlugin {
|
|
|
21635
21524
|
}
|
|
21636
21525
|
getBuiltinSinks() {
|
|
21637
21526
|
return [
|
|
21638
|
-
{
|
|
21639
|
-
method: "exec",
|
|
21640
|
-
class: "child_process",
|
|
21641
|
-
type: "command_injection",
|
|
21642
|
-
cwe: "CWE-78",
|
|
21643
|
-
severity: "critical",
|
|
21644
|
-
argPositions: [0]
|
|
21645
|
-
},
|
|
21646
|
-
{
|
|
21647
|
-
method: "execSync",
|
|
21648
|
-
class: "child_process",
|
|
21649
|
-
type: "command_injection",
|
|
21650
|
-
cwe: "CWE-78",
|
|
21651
|
-
severity: "critical",
|
|
21652
|
-
argPositions: [0]
|
|
21653
|
-
},
|
|
21654
|
-
{
|
|
21655
|
-
method: "spawn",
|
|
21656
|
-
class: "child_process",
|
|
21657
|
-
type: "command_injection",
|
|
21658
|
-
cwe: "CWE-78",
|
|
21659
|
-
severity: "critical",
|
|
21660
|
-
argPositions: [0, 1]
|
|
21661
|
-
},
|
|
21662
|
-
{
|
|
21663
|
-
method: "eval",
|
|
21664
|
-
type: "code_injection",
|
|
21665
|
-
cwe: "CWE-94",
|
|
21666
|
-
severity: "critical",
|
|
21667
|
-
argPositions: [0]
|
|
21668
|
-
},
|
|
21669
21527
|
{
|
|
21670
21528
|
method: "Function",
|
|
21671
21529
|
type: "code_injection",
|
|
@@ -21687,44 +21545,6 @@ class JavaScriptPlugin extends BaseLanguagePlugin {
|
|
|
21687
21545
|
severity: "high",
|
|
21688
21546
|
argPositions: [0]
|
|
21689
21547
|
},
|
|
21690
|
-
{
|
|
21691
|
-
method: "readFileSync",
|
|
21692
|
-
class: "fs",
|
|
21693
|
-
type: "path_traversal",
|
|
21694
|
-
cwe: "CWE-22",
|
|
21695
|
-
severity: "high",
|
|
21696
|
-
argPositions: [0]
|
|
21697
|
-
},
|
|
21698
|
-
{
|
|
21699
|
-
method: "writeFileSync",
|
|
21700
|
-
class: "fs",
|
|
21701
|
-
type: "path_traversal",
|
|
21702
|
-
cwe: "CWE-22",
|
|
21703
|
-
severity: "high",
|
|
21704
|
-
argPositions: [0]
|
|
21705
|
-
},
|
|
21706
|
-
{
|
|
21707
|
-
method: "createReadStream",
|
|
21708
|
-
class: "fs",
|
|
21709
|
-
type: "path_traversal",
|
|
21710
|
-
cwe: "CWE-22",
|
|
21711
|
-
severity: "high",
|
|
21712
|
-
argPositions: [0]
|
|
21713
|
-
},
|
|
21714
|
-
{
|
|
21715
|
-
method: "innerHTML",
|
|
21716
|
-
type: "xss",
|
|
21717
|
-
cwe: "CWE-79",
|
|
21718
|
-
severity: "high",
|
|
21719
|
-
argPositions: [0]
|
|
21720
|
-
},
|
|
21721
|
-
{
|
|
21722
|
-
method: "outerHTML",
|
|
21723
|
-
type: "xss",
|
|
21724
|
-
cwe: "CWE-79",
|
|
21725
|
-
severity: "high",
|
|
21726
|
-
argPositions: [0]
|
|
21727
|
-
},
|
|
21728
21548
|
{
|
|
21729
21549
|
method: "document.write",
|
|
21730
21550
|
type: "xss",
|
|
@@ -21774,13 +21594,6 @@ class JavaScriptPlugin extends BaseLanguagePlugin {
|
|
|
21774
21594
|
severity: "critical",
|
|
21775
21595
|
argPositions: [0]
|
|
21776
21596
|
},
|
|
21777
|
-
{
|
|
21778
|
-
method: "raw",
|
|
21779
|
-
type: "sql_injection",
|
|
21780
|
-
cwe: "CWE-89",
|
|
21781
|
-
severity: "critical",
|
|
21782
|
-
argPositions: [0]
|
|
21783
|
-
},
|
|
21784
21597
|
{
|
|
21785
21598
|
method: "$executeRawUnsafe",
|
|
21786
21599
|
type: "sql_injection",
|
|
@@ -21795,29 +21608,6 @@ class JavaScriptPlugin extends BaseLanguagePlugin {
|
|
|
21795
21608
|
severity: "critical",
|
|
21796
21609
|
argPositions: [0]
|
|
21797
21610
|
},
|
|
21798
|
-
{
|
|
21799
|
-
method: "fetch",
|
|
21800
|
-
type: "ssrf",
|
|
21801
|
-
cwe: "CWE-918",
|
|
21802
|
-
severity: "high",
|
|
21803
|
-
argPositions: [0]
|
|
21804
|
-
},
|
|
21805
|
-
{
|
|
21806
|
-
method: "get",
|
|
21807
|
-
class: "axios",
|
|
21808
|
-
type: "ssrf",
|
|
21809
|
-
cwe: "CWE-918",
|
|
21810
|
-
severity: "high",
|
|
21811
|
-
argPositions: [0]
|
|
21812
|
-
},
|
|
21813
|
-
{
|
|
21814
|
-
method: "request",
|
|
21815
|
-
class: "http",
|
|
21816
|
-
type: "ssrf",
|
|
21817
|
-
cwe: "CWE-918",
|
|
21818
|
-
severity: "high",
|
|
21819
|
-
argPositions: [0]
|
|
21820
|
-
},
|
|
21821
21611
|
{
|
|
21822
21612
|
method: "find",
|
|
21823
21613
|
type: "nosql_injection",
|
|
@@ -21825,13 +21615,6 @@ class JavaScriptPlugin extends BaseLanguagePlugin {
|
|
|
21825
21615
|
severity: "high",
|
|
21826
21616
|
argPositions: [0]
|
|
21827
21617
|
},
|
|
21828
|
-
{
|
|
21829
|
-
method: "findOne",
|
|
21830
|
-
type: "nosql_injection",
|
|
21831
|
-
cwe: "CWE-943",
|
|
21832
|
-
severity: "high",
|
|
21833
|
-
argPositions: [0]
|
|
21834
|
-
},
|
|
21835
21618
|
{
|
|
21836
21619
|
method: "merge",
|
|
21837
21620
|
type: "prototype_pollution",
|
|
@@ -21907,13 +21690,6 @@ class JavaScriptPlugin extends BaseLanguagePlugin {
|
|
|
21907
21690
|
severity: "high",
|
|
21908
21691
|
argPositions: [0]
|
|
21909
21692
|
},
|
|
21910
|
-
{
|
|
21911
|
-
method: "redirect",
|
|
21912
|
-
type: "open_redirect",
|
|
21913
|
-
cwe: "CWE-601",
|
|
21914
|
-
severity: "high",
|
|
21915
|
-
argPositions: [0]
|
|
21916
|
-
},
|
|
21917
21693
|
{
|
|
21918
21694
|
method: "push",
|
|
21919
21695
|
class: "router",
|
|
@@ -22156,13 +21932,6 @@ class PythonPlugin extends BaseLanguagePlugin {
|
|
|
22156
21932
|
confidence: 0.9,
|
|
22157
21933
|
returnTainted: true
|
|
22158
21934
|
},
|
|
22159
|
-
{
|
|
22160
|
-
method: "input",
|
|
22161
|
-
type: "user_input",
|
|
22162
|
-
severity: "high",
|
|
22163
|
-
confidence: 0.95,
|
|
22164
|
-
returnTainted: true
|
|
22165
|
-
},
|
|
22166
21935
|
{
|
|
22167
21936
|
method: "argv",
|
|
22168
21937
|
class: "sys",
|
|
@@ -22178,129 +21947,11 @@ class PythonPlugin extends BaseLanguagePlugin {
|
|
|
22178
21947
|
severity: "medium",
|
|
22179
21948
|
confidence: 0.85,
|
|
22180
21949
|
returnTainted: true
|
|
22181
|
-
},
|
|
22182
|
-
{
|
|
22183
|
-
method: "getenv",
|
|
22184
|
-
class: "os",
|
|
22185
|
-
type: "env_var",
|
|
22186
|
-
severity: "medium",
|
|
22187
|
-
confidence: 0.85,
|
|
22188
|
-
returnTainted: true
|
|
22189
|
-
},
|
|
22190
|
-
{
|
|
22191
|
-
method: "read",
|
|
22192
|
-
type: "file_input",
|
|
22193
|
-
severity: "medium",
|
|
22194
|
-
confidence: 0.8,
|
|
22195
|
-
returnTainted: true
|
|
22196
|
-
},
|
|
22197
|
-
{
|
|
22198
|
-
method: "readline",
|
|
22199
|
-
type: "file_input",
|
|
22200
|
-
severity: "medium",
|
|
22201
|
-
confidence: 0.8,
|
|
22202
|
-
returnTainted: true
|
|
22203
|
-
},
|
|
22204
|
-
{
|
|
22205
|
-
method: "readlines",
|
|
22206
|
-
type: "file_input",
|
|
22207
|
-
severity: "medium",
|
|
22208
|
-
confidence: 0.8,
|
|
22209
|
-
returnTainted: true
|
|
22210
21950
|
}
|
|
22211
21951
|
];
|
|
22212
21952
|
}
|
|
22213
21953
|
getBuiltinSinks() {
|
|
22214
21954
|
return [
|
|
22215
|
-
{
|
|
22216
|
-
method: "system",
|
|
22217
|
-
class: "os",
|
|
22218
|
-
type: "command_injection",
|
|
22219
|
-
cwe: "CWE-78",
|
|
22220
|
-
severity: "critical",
|
|
22221
|
-
argPositions: [0]
|
|
22222
|
-
},
|
|
22223
|
-
{
|
|
22224
|
-
method: "popen",
|
|
22225
|
-
class: "os",
|
|
22226
|
-
type: "command_injection",
|
|
22227
|
-
cwe: "CWE-78",
|
|
22228
|
-
severity: "critical",
|
|
22229
|
-
argPositions: [0]
|
|
22230
|
-
},
|
|
22231
|
-
{
|
|
22232
|
-
method: "run",
|
|
22233
|
-
class: "subprocess",
|
|
22234
|
-
type: "command_injection",
|
|
22235
|
-
cwe: "CWE-78",
|
|
22236
|
-
severity: "critical",
|
|
22237
|
-
argPositions: [0]
|
|
22238
|
-
},
|
|
22239
|
-
{
|
|
22240
|
-
method: "call",
|
|
22241
|
-
class: "subprocess",
|
|
22242
|
-
type: "command_injection",
|
|
22243
|
-
cwe: "CWE-78",
|
|
22244
|
-
severity: "critical",
|
|
22245
|
-
argPositions: [0]
|
|
22246
|
-
},
|
|
22247
|
-
{
|
|
22248
|
-
method: "Popen",
|
|
22249
|
-
class: "subprocess",
|
|
22250
|
-
type: "command_injection",
|
|
22251
|
-
cwe: "CWE-78",
|
|
22252
|
-
severity: "critical",
|
|
22253
|
-
argPositions: [0]
|
|
22254
|
-
},
|
|
22255
|
-
{
|
|
22256
|
-
method: "eval",
|
|
22257
|
-
type: "code_injection",
|
|
22258
|
-
cwe: "CWE-94",
|
|
22259
|
-
severity: "critical",
|
|
22260
|
-
argPositions: [0]
|
|
22261
|
-
},
|
|
22262
|
-
{
|
|
22263
|
-
method: "exec",
|
|
22264
|
-
type: "code_injection",
|
|
22265
|
-
cwe: "CWE-94",
|
|
22266
|
-
severity: "critical",
|
|
22267
|
-
argPositions: [0]
|
|
22268
|
-
},
|
|
22269
|
-
{
|
|
22270
|
-
method: "compile",
|
|
22271
|
-
type: "code_injection",
|
|
22272
|
-
cwe: "CWE-94",
|
|
22273
|
-
severity: "high",
|
|
22274
|
-
argPositions: [0]
|
|
22275
|
-
},
|
|
22276
|
-
{
|
|
22277
|
-
method: "execute",
|
|
22278
|
-
type: "sql_injection",
|
|
22279
|
-
cwe: "CWE-89",
|
|
22280
|
-
severity: "critical",
|
|
22281
|
-
argPositions: [0]
|
|
22282
|
-
},
|
|
22283
|
-
{
|
|
22284
|
-
method: "executemany",
|
|
22285
|
-
type: "sql_injection",
|
|
22286
|
-
cwe: "CWE-89",
|
|
22287
|
-
severity: "critical",
|
|
22288
|
-
argPositions: [0]
|
|
22289
|
-
},
|
|
22290
|
-
{
|
|
22291
|
-
method: "raw",
|
|
22292
|
-
type: "sql_injection",
|
|
22293
|
-
cwe: "CWE-89",
|
|
22294
|
-
severity: "critical",
|
|
22295
|
-
argPositions: [0]
|
|
22296
|
-
},
|
|
22297
|
-
{
|
|
22298
|
-
method: "open",
|
|
22299
|
-
type: "path_traversal",
|
|
22300
|
-
cwe: "CWE-22",
|
|
22301
|
-
severity: "high",
|
|
22302
|
-
argPositions: [0]
|
|
22303
|
-
},
|
|
22304
21955
|
{
|
|
22305
21956
|
method: "read",
|
|
22306
21957
|
class: "pathlib",
|
|
@@ -22309,13 +21960,6 @@ class PythonPlugin extends BaseLanguagePlugin {
|
|
|
22309
21960
|
severity: "high",
|
|
22310
21961
|
argPositions: [0]
|
|
22311
21962
|
},
|
|
22312
|
-
{
|
|
22313
|
-
method: "Markup",
|
|
22314
|
-
type: "xss",
|
|
22315
|
-
cwe: "CWE-79",
|
|
22316
|
-
severity: "high",
|
|
22317
|
-
argPositions: [0]
|
|
22318
|
-
},
|
|
22319
21963
|
{
|
|
22320
21964
|
method: "safe",
|
|
22321
21965
|
type: "xss",
|
|
@@ -22323,22 +21967,6 @@ class PythonPlugin extends BaseLanguagePlugin {
|
|
|
22323
21967
|
severity: "high",
|
|
22324
21968
|
argPositions: [0]
|
|
22325
21969
|
},
|
|
22326
|
-
{
|
|
22327
|
-
method: "get",
|
|
22328
|
-
class: "requests",
|
|
22329
|
-
type: "ssrf",
|
|
22330
|
-
cwe: "CWE-918",
|
|
22331
|
-
severity: "high",
|
|
22332
|
-
argPositions: [0]
|
|
22333
|
-
},
|
|
22334
|
-
{
|
|
22335
|
-
method: "post",
|
|
22336
|
-
class: "requests",
|
|
22337
|
-
type: "ssrf",
|
|
22338
|
-
cwe: "CWE-918",
|
|
22339
|
-
severity: "high",
|
|
22340
|
-
argPositions: [0]
|
|
22341
|
-
},
|
|
22342
21970
|
{
|
|
22343
21971
|
method: "urlopen",
|
|
22344
21972
|
class: "urllib",
|
|
@@ -22363,30 +21991,6 @@ class PythonPlugin extends BaseLanguagePlugin {
|
|
|
22363
21991
|
severity: "high",
|
|
22364
21992
|
argPositions: [1]
|
|
22365
21993
|
},
|
|
22366
|
-
{
|
|
22367
|
-
method: "loads",
|
|
22368
|
-
class: "pickle",
|
|
22369
|
-
type: "deserialization",
|
|
22370
|
-
cwe: "CWE-502",
|
|
22371
|
-
severity: "critical",
|
|
22372
|
-
argPositions: [0]
|
|
22373
|
-
},
|
|
22374
|
-
{
|
|
22375
|
-
method: "load",
|
|
22376
|
-
class: "pickle",
|
|
22377
|
-
type: "deserialization",
|
|
22378
|
-
cwe: "CWE-502",
|
|
22379
|
-
severity: "critical",
|
|
22380
|
-
argPositions: [0]
|
|
22381
|
-
},
|
|
22382
|
-
{
|
|
22383
|
-
method: "load",
|
|
22384
|
-
class: "yaml",
|
|
22385
|
-
type: "deserialization",
|
|
22386
|
-
cwe: "CWE-502",
|
|
22387
|
-
severity: "critical",
|
|
22388
|
-
argPositions: [0]
|
|
22389
|
-
},
|
|
22390
21994
|
{
|
|
22391
21995
|
method: "unsafe_load",
|
|
22392
21996
|
class: "yaml",
|
|
@@ -22522,34 +22126,6 @@ class RustPlugin extends BaseLanguagePlugin {
|
|
|
22522
22126
|
}
|
|
22523
22127
|
getBuiltinSources() {
|
|
22524
22128
|
return [
|
|
22525
|
-
{
|
|
22526
|
-
method: "Query",
|
|
22527
|
-
type: "http_param",
|
|
22528
|
-
severity: "high",
|
|
22529
|
-
confidence: 0.95,
|
|
22530
|
-
returnTainted: true
|
|
22531
|
-
},
|
|
22532
|
-
{
|
|
22533
|
-
method: "Json",
|
|
22534
|
-
type: "http_body",
|
|
22535
|
-
severity: "high",
|
|
22536
|
-
confidence: 0.95,
|
|
22537
|
-
returnTainted: true
|
|
22538
|
-
},
|
|
22539
|
-
{
|
|
22540
|
-
method: "Path",
|
|
22541
|
-
type: "http_path",
|
|
22542
|
-
severity: "high",
|
|
22543
|
-
confidence: 0.95,
|
|
22544
|
-
returnTainted: true
|
|
22545
|
-
},
|
|
22546
|
-
{
|
|
22547
|
-
method: "Form",
|
|
22548
|
-
type: "http_body",
|
|
22549
|
-
severity: "high",
|
|
22550
|
-
confidence: 0.95,
|
|
22551
|
-
returnTainted: true
|
|
22552
|
-
},
|
|
22553
22129
|
{
|
|
22554
22130
|
method: "args",
|
|
22555
22131
|
class: "std::env",
|
|
@@ -22597,14 +22173,6 @@ class RustPlugin extends BaseLanguagePlugin {
|
|
|
22597
22173
|
severity: "medium",
|
|
22598
22174
|
confidence: 0.8,
|
|
22599
22175
|
returnTainted: true
|
|
22600
|
-
},
|
|
22601
|
-
{
|
|
22602
|
-
method: "read",
|
|
22603
|
-
class: "TcpStream",
|
|
22604
|
-
type: "network_input",
|
|
22605
|
-
severity: "high",
|
|
22606
|
-
confidence: 0.85,
|
|
22607
|
-
returnTainted: true
|
|
22608
22176
|
}
|
|
22609
22177
|
];
|
|
22610
22178
|
}
|
|
@@ -22618,29 +22186,6 @@ class RustPlugin extends BaseLanguagePlugin {
|
|
|
22618
22186
|
severity: "critical",
|
|
22619
22187
|
argPositions: [0]
|
|
22620
22188
|
},
|
|
22621
|
-
{
|
|
22622
|
-
method: "arg",
|
|
22623
|
-
class: "Command",
|
|
22624
|
-
type: "command_injection",
|
|
22625
|
-
cwe: "CWE-78",
|
|
22626
|
-
severity: "critical",
|
|
22627
|
-
argPositions: [0]
|
|
22628
|
-
},
|
|
22629
|
-
{
|
|
22630
|
-
method: "args",
|
|
22631
|
-
class: "Command",
|
|
22632
|
-
type: "command_injection",
|
|
22633
|
-
cwe: "CWE-78",
|
|
22634
|
-
severity: "critical",
|
|
22635
|
-
argPositions: [0]
|
|
22636
|
-
},
|
|
22637
|
-
{
|
|
22638
|
-
method: "execute",
|
|
22639
|
-
type: "sql_injection",
|
|
22640
|
-
cwe: "CWE-89",
|
|
22641
|
-
severity: "critical",
|
|
22642
|
-
argPositions: [0]
|
|
22643
|
-
},
|
|
22644
22189
|
{
|
|
22645
22190
|
method: "query",
|
|
22646
22191
|
type: "sql_injection",
|
|
@@ -22655,22 +22200,6 @@ class RustPlugin extends BaseLanguagePlugin {
|
|
|
22655
22200
|
severity: "critical",
|
|
22656
22201
|
argPositions: [0]
|
|
22657
22202
|
},
|
|
22658
|
-
{
|
|
22659
|
-
method: "open",
|
|
22660
|
-
class: "File",
|
|
22661
|
-
type: "path_traversal",
|
|
22662
|
-
cwe: "CWE-22",
|
|
22663
|
-
severity: "high",
|
|
22664
|
-
argPositions: [0]
|
|
22665
|
-
},
|
|
22666
|
-
{
|
|
22667
|
-
method: "create",
|
|
22668
|
-
class: "File",
|
|
22669
|
-
type: "path_traversal",
|
|
22670
|
-
cwe: "CWE-22",
|
|
22671
|
-
severity: "high",
|
|
22672
|
-
argPositions: [0]
|
|
22673
|
-
},
|
|
22674
22203
|
{
|
|
22675
22204
|
method: "read_to_string",
|
|
22676
22205
|
class: "std::fs",
|
|
@@ -22708,38 +22237,6 @@ class RustPlugin extends BaseLanguagePlugin {
|
|
|
22708
22237
|
severity: "critical",
|
|
22709
22238
|
argPositions: [0]
|
|
22710
22239
|
},
|
|
22711
|
-
{
|
|
22712
|
-
method: "from_str",
|
|
22713
|
-
class: "serde_json",
|
|
22714
|
-
type: "deserialization",
|
|
22715
|
-
cwe: "CWE-502",
|
|
22716
|
-
severity: "medium",
|
|
22717
|
-
argPositions: [0]
|
|
22718
|
-
},
|
|
22719
|
-
{
|
|
22720
|
-
method: "from_slice",
|
|
22721
|
-
class: "serde_json",
|
|
22722
|
-
type: "deserialization",
|
|
22723
|
-
cwe: "CWE-502",
|
|
22724
|
-
severity: "medium",
|
|
22725
|
-
argPositions: [0]
|
|
22726
|
-
},
|
|
22727
|
-
{
|
|
22728
|
-
method: "get",
|
|
22729
|
-
class: "reqwest",
|
|
22730
|
-
type: "ssrf",
|
|
22731
|
-
cwe: "CWE-918",
|
|
22732
|
-
severity: "high",
|
|
22733
|
-
argPositions: [0]
|
|
22734
|
-
},
|
|
22735
|
-
{
|
|
22736
|
-
method: "post",
|
|
22737
|
-
class: "reqwest",
|
|
22738
|
-
type: "ssrf",
|
|
22739
|
-
cwe: "CWE-918",
|
|
22740
|
-
severity: "high",
|
|
22741
|
-
argPositions: [0]
|
|
22742
|
-
},
|
|
22743
22240
|
{
|
|
22744
22241
|
method: "new",
|
|
22745
22242
|
class: "Regex",
|
|
@@ -22832,13 +22329,6 @@ class BashPlugin extends BaseLanguagePlugin {
|
|
|
22832
22329
|
}
|
|
22833
22330
|
getBuiltinSources() {
|
|
22834
22331
|
return [
|
|
22835
|
-
{
|
|
22836
|
-
method: "read",
|
|
22837
|
-
type: "io_input",
|
|
22838
|
-
severity: "high",
|
|
22839
|
-
confidence: 0.9,
|
|
22840
|
-
returnTainted: true
|
|
22841
|
-
},
|
|
22842
22332
|
{
|
|
22843
22333
|
method: "curl",
|
|
22844
22334
|
type: "http_response",
|
|
@@ -22857,13 +22347,6 @@ class BashPlugin extends BaseLanguagePlugin {
|
|
|
22857
22347
|
}
|
|
22858
22348
|
getBuiltinSinks() {
|
|
22859
22349
|
return [
|
|
22860
|
-
{
|
|
22861
|
-
method: "eval",
|
|
22862
|
-
type: "code_injection",
|
|
22863
|
-
cwe: "CWE-94",
|
|
22864
|
-
severity: "critical",
|
|
22865
|
-
argPositions: [0]
|
|
22866
|
-
},
|
|
22867
22350
|
{
|
|
22868
22351
|
method: "bash",
|
|
22869
22352
|
type: "command_injection",
|
|
@@ -23259,30 +22742,6 @@ class GoPlugin extends BaseLanguagePlugin {
|
|
|
23259
22742
|
confidence: 0.9,
|
|
23260
22743
|
returnTainted: true
|
|
23261
22744
|
},
|
|
23262
|
-
{
|
|
23263
|
-
method: "Query",
|
|
23264
|
-
class: "Context",
|
|
23265
|
-
type: "http_param",
|
|
23266
|
-
severity: "high",
|
|
23267
|
-
confidence: 0.95,
|
|
23268
|
-
returnTainted: true
|
|
23269
|
-
},
|
|
23270
|
-
{
|
|
23271
|
-
method: "Param",
|
|
23272
|
-
class: "Context",
|
|
23273
|
-
type: "http_path",
|
|
23274
|
-
severity: "high",
|
|
23275
|
-
confidence: 0.95,
|
|
23276
|
-
returnTainted: true
|
|
23277
|
-
},
|
|
23278
|
-
{
|
|
23279
|
-
method: "PostForm",
|
|
23280
|
-
class: "Context",
|
|
23281
|
-
type: "http_param",
|
|
23282
|
-
severity: "high",
|
|
23283
|
-
confidence: 0.95,
|
|
23284
|
-
returnTainted: true
|
|
23285
|
-
},
|
|
23286
22745
|
{
|
|
23287
22746
|
method: "GetRawData",
|
|
23288
22747
|
class: "Context",
|
|
@@ -23479,14 +22938,6 @@ class GoPlugin extends BaseLanguagePlugin {
|
|
|
23479
22938
|
severity: "medium",
|
|
23480
22939
|
argPositions: [0]
|
|
23481
22940
|
},
|
|
23482
|
-
{
|
|
23483
|
-
method: "Decode",
|
|
23484
|
-
class: "Decoder",
|
|
23485
|
-
type: "deserialization",
|
|
23486
|
-
cwe: "CWE-502",
|
|
23487
|
-
severity: "medium",
|
|
23488
|
-
argPositions: [0]
|
|
23489
|
-
},
|
|
23490
22941
|
{
|
|
23491
22942
|
method: "Print",
|
|
23492
22943
|
class: "log",
|
|
@@ -25121,6 +24572,10 @@ class LanguageSourcesPass {
|
|
|
25121
24572
|
additionalSanitizers.push(...findPythonRangeCheckGuardSanitizers(code));
|
|
25122
24573
|
additionalSanitizers.push(...findPythonRegexAllowlistWrapperSanitizers(code));
|
|
25123
24574
|
additionalSanitizers.push(...findPythonSetMembershipXssGuardSanitizers(code));
|
|
24575
|
+
additionalSanitizers.push(...findPythonTraversalRejectGuardSanitizers(code));
|
|
24576
|
+
additionalSanitizers.push(...findPythonStringLiteralGuardSanitizers(code));
|
|
24577
|
+
additionalSanitizers.push(...findPythonDefaultSaxParserXxeSanitizers(code));
|
|
24578
|
+
additionalSanitizers.push(...findPythonUrlAllowlistRedirectSanitizers(code));
|
|
25124
24579
|
additionalSanitizers.push(...findPythonDefusedXmlSanitizers(code));
|
|
25125
24580
|
additionalSanitizers.push(...findPythonJinjaAutoescapeSanitizers(code));
|
|
25126
24581
|
const pyMisconfigFindings = findPythonPatternFindings(code, graph.ir.meta.file);
|
|
@@ -25715,15 +25170,165 @@ function findPythonAssignmentSources(sourceCode, language) {
|
|
|
25715
25170
|
}
|
|
25716
25171
|
return sources;
|
|
25717
25172
|
}
|
|
25173
|
+
function evaluatePythonConstExpression(expr, consts) {
|
|
25174
|
+
const COMPARISON = /(<=|>=|==|!=|<|>)/;
|
|
25175
|
+
const parts2 = expr.split(COMPARISON);
|
|
25176
|
+
if (parts2.length === 3) {
|
|
25177
|
+
const left = evaluatePythonConstExpression(parts2[0], consts);
|
|
25178
|
+
const right = evaluatePythonConstExpression(parts2[2], consts);
|
|
25179
|
+
if (typeof left !== "number" || typeof right !== "number")
|
|
25180
|
+
return;
|
|
25181
|
+
switch (parts2[1]) {
|
|
25182
|
+
case "<":
|
|
25183
|
+
return left < right;
|
|
25184
|
+
case ">":
|
|
25185
|
+
return left > right;
|
|
25186
|
+
case "<=":
|
|
25187
|
+
return left <= right;
|
|
25188
|
+
case ">=":
|
|
25189
|
+
return left >= right;
|
|
25190
|
+
case "==":
|
|
25191
|
+
return left === right;
|
|
25192
|
+
case "!=":
|
|
25193
|
+
return left !== right;
|
|
25194
|
+
default:
|
|
25195
|
+
return;
|
|
25196
|
+
}
|
|
25197
|
+
}
|
|
25198
|
+
if (parts2.length !== 1)
|
|
25199
|
+
return;
|
|
25200
|
+
const matched = expr.match(/\d+|[A-Za-z_][A-Za-z0-9_]*|\/\/|[-+*/%()]|\S/g);
|
|
25201
|
+
if (!matched)
|
|
25202
|
+
return;
|
|
25203
|
+
const tokens = matched;
|
|
25204
|
+
let pos = 0;
|
|
25205
|
+
const peek = () => tokens[pos];
|
|
25206
|
+
const parseFactor = () => {
|
|
25207
|
+
const tok = tokens[pos++];
|
|
25208
|
+
if (tok === undefined)
|
|
25209
|
+
return;
|
|
25210
|
+
if (tok === "(") {
|
|
25211
|
+
const inner = parseSum();
|
|
25212
|
+
if (tokens[pos++] !== ")")
|
|
25213
|
+
return;
|
|
25214
|
+
return inner;
|
|
25215
|
+
}
|
|
25216
|
+
if (tok === "-") {
|
|
25217
|
+
const operand = parseFactor();
|
|
25218
|
+
return operand === undefined ? undefined : -operand;
|
|
25219
|
+
}
|
|
25220
|
+
if (/^\d+$/.test(tok))
|
|
25221
|
+
return Number(tok);
|
|
25222
|
+
if (/^[A-Za-z_]/.test(tok))
|
|
25223
|
+
return consts.get(tok);
|
|
25224
|
+
return;
|
|
25225
|
+
};
|
|
25226
|
+
const parseTerm = () => {
|
|
25227
|
+
let value = parseFactor();
|
|
25228
|
+
if (value === undefined)
|
|
25229
|
+
return;
|
|
25230
|
+
while (peek() === "*" || peek() === "/" || peek() === "//" || peek() === "%") {
|
|
25231
|
+
const op = tokens[pos++];
|
|
25232
|
+
const rhs = parseFactor();
|
|
25233
|
+
if (rhs === undefined)
|
|
25234
|
+
return;
|
|
25235
|
+
if ((op === "/" || op === "//" || op === "%") && rhs === 0)
|
|
25236
|
+
return;
|
|
25237
|
+
if (op === "*")
|
|
25238
|
+
value *= rhs;
|
|
25239
|
+
else if (op === "/")
|
|
25240
|
+
value /= rhs;
|
|
25241
|
+
else if (op === "//")
|
|
25242
|
+
value = Math.floor(value / rhs);
|
|
25243
|
+
else
|
|
25244
|
+
value = (value % rhs + rhs) % rhs;
|
|
25245
|
+
}
|
|
25246
|
+
return value;
|
|
25247
|
+
};
|
|
25248
|
+
function parseSum() {
|
|
25249
|
+
let value = parseTerm();
|
|
25250
|
+
if (value === undefined)
|
|
25251
|
+
return;
|
|
25252
|
+
while (peek() === "+" || peek() === "-") {
|
|
25253
|
+
const op = tokens[pos++];
|
|
25254
|
+
const rhs = parseTerm();
|
|
25255
|
+
if (rhs === undefined)
|
|
25256
|
+
return;
|
|
25257
|
+
value = op === "+" ? value + rhs : value - rhs;
|
|
25258
|
+
}
|
|
25259
|
+
return value;
|
|
25260
|
+
}
|
|
25261
|
+
const result = parseSum();
|
|
25262
|
+
return pos === tokens.length ? result : undefined;
|
|
25263
|
+
}
|
|
25264
|
+
function normalizeListIndex(index, length) {
|
|
25265
|
+
const resolved = index < 0 ? length + index : index;
|
|
25266
|
+
return resolved >= 0 && resolved < length ? resolved : undefined;
|
|
25267
|
+
}
|
|
25268
|
+
function computeDeadPythonBranchLines(lines) {
|
|
25269
|
+
const dead = new Set;
|
|
25270
|
+
const consts = new Map;
|
|
25271
|
+
const indentOf = (line) => line.length - line.trimStart().length;
|
|
25272
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
25273
|
+
const line = lines[i2];
|
|
25274
|
+
const assign = line.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=(?!=)\s*(.+)$/);
|
|
25275
|
+
if (assign) {
|
|
25276
|
+
const value = evaluatePythonConstExpression(assign[2].trim(), consts);
|
|
25277
|
+
if (typeof value === "number")
|
|
25278
|
+
consts.set(assign[1], value);
|
|
25279
|
+
else
|
|
25280
|
+
consts.delete(assign[1]);
|
|
25281
|
+
}
|
|
25282
|
+
const ifMatch = line.match(/^(\s*)if\s+(.+?)\s*:\s*$/);
|
|
25283
|
+
if (!ifMatch)
|
|
25284
|
+
continue;
|
|
25285
|
+
const indent = ifMatch[1].length;
|
|
25286
|
+
const decided = evaluatePythonConstExpression(ifMatch[2].trim(), consts);
|
|
25287
|
+
if (decided !== true && decided !== false)
|
|
25288
|
+
continue;
|
|
25289
|
+
const thenStart = i2 + 1;
|
|
25290
|
+
let cursor = thenStart;
|
|
25291
|
+
while (cursor < lines.length && (lines[cursor].trim() === "" || indentOf(lines[cursor]) > indent)) {
|
|
25292
|
+
cursor++;
|
|
25293
|
+
}
|
|
25294
|
+
const thenEnd = cursor - 1;
|
|
25295
|
+
let elseStart = -1;
|
|
25296
|
+
let elseEnd = -1;
|
|
25297
|
+
if (cursor < lines.length && indentOf(lines[cursor]) === indent) {
|
|
25298
|
+
if (/^\s*elif\b/.test(lines[cursor]))
|
|
25299
|
+
continue;
|
|
25300
|
+
if (/^\s*else\s*:\s*$/.test(lines[cursor])) {
|
|
25301
|
+
elseStart = cursor + 1;
|
|
25302
|
+
let k = elseStart;
|
|
25303
|
+
while (k < lines.length && (lines[k].trim() === "" || indentOf(lines[k]) > indent))
|
|
25304
|
+
k++;
|
|
25305
|
+
elseEnd = k - 1;
|
|
25306
|
+
}
|
|
25307
|
+
}
|
|
25308
|
+
if (decided === true) {
|
|
25309
|
+
for (let l = elseStart;l >= 0 && l <= elseEnd; l++)
|
|
25310
|
+
dead.add(l);
|
|
25311
|
+
} else {
|
|
25312
|
+
for (let l = thenStart;l <= thenEnd; l++)
|
|
25313
|
+
dead.add(l);
|
|
25314
|
+
}
|
|
25315
|
+
}
|
|
25316
|
+
return dead;
|
|
25317
|
+
}
|
|
25718
25318
|
function buildPythonTaintedVars(sourceCode) {
|
|
25719
25319
|
const tainted = new Map;
|
|
25720
25320
|
const containerTainted = new Map;
|
|
25721
25321
|
const lines = sourceCode.split(`
|
|
25722
25322
|
`);
|
|
25323
|
+
const deadBranchLines = computeDeadPythonBranchLines(lines);
|
|
25324
|
+
const listElems = new Map;
|
|
25325
|
+
const intConsts = new Map;
|
|
25723
25326
|
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
25724
25327
|
const line = lines[i2];
|
|
25725
25328
|
if (line.trimStart().startsWith("#"))
|
|
25726
25329
|
continue;
|
|
25330
|
+
if (deadBranchLines.has(i2))
|
|
25331
|
+
continue;
|
|
25727
25332
|
const subscriptAssign = line.match(/^\s*([\p{L}\p{N}_]+)\[(['"])([^'"]+)\2\]\s*=\s*(.+)$/u);
|
|
25728
25333
|
if (subscriptAssign) {
|
|
25729
25334
|
const [, container, , key, rhs2] = subscriptAssign;
|
|
@@ -25742,11 +25347,54 @@ function buildPythonTaintedVars(sourceCode) {
|
|
|
25742
25347
|
}
|
|
25743
25348
|
const containerAppendMatch = line.match(/^\s*([\p{L}\p{N}_]+)\.(append|extend|insert|add|push|put|appendleft)\s*\(\s*(.+?)\s*\)\s*$/u);
|
|
25744
25349
|
if (containerAppendMatch) {
|
|
25745
|
-
const [, receiver, , argExpr] = containerAppendMatch;
|
|
25350
|
+
const [, receiver, method, argExpr] = containerAppendMatch;
|
|
25746
25351
|
const argIsTainted = [...tainted.keys()].some((v) => new RegExp(`(?<![\\p{L}\\p{N}_])${v}(?![\\p{L}\\p{N}_])`, "u").test(argExpr));
|
|
25747
25352
|
const argIsDirectSource = PYTHON_TAINTED_PATTERNS2.some((p) => p.pattern.test(argExpr));
|
|
25748
25353
|
if (argIsTainted || argIsDirectSource)
|
|
25749
25354
|
tainted.set(receiver, tainted.get(receiver) ?? i2 + 1);
|
|
25355
|
+
const elems = listElems.get(receiver);
|
|
25356
|
+
if (elems) {
|
|
25357
|
+
if (method === "append") {
|
|
25358
|
+
elems.push(argIsTainted || argIsDirectSource);
|
|
25359
|
+
} else if (method === "insert") {
|
|
25360
|
+
const insertAt = argExpr.match(/^(-?\d+)\s*,\s*(.+)$/);
|
|
25361
|
+
if (insertAt) {
|
|
25362
|
+
const idx = normalizeListIndex(Number(insertAt[1]), elems.length);
|
|
25363
|
+
const valueExpr = insertAt[2];
|
|
25364
|
+
const valueTainted = [...tainted.keys()].some((v) => new RegExp(`(?<![\\p{L}\\p{N}_])${v}(?![\\p{L}\\p{N}_])`, "u").test(valueExpr)) || PYTHON_TAINTED_PATTERNS2.some((p) => p.pattern.test(valueExpr));
|
|
25365
|
+
if (idx !== undefined)
|
|
25366
|
+
elems.splice(idx, 0, valueTainted);
|
|
25367
|
+
else
|
|
25368
|
+
listElems.delete(receiver);
|
|
25369
|
+
} else {
|
|
25370
|
+
listElems.delete(receiver);
|
|
25371
|
+
}
|
|
25372
|
+
} else {
|
|
25373
|
+
listElems.delete(receiver);
|
|
25374
|
+
}
|
|
25375
|
+
}
|
|
25376
|
+
continue;
|
|
25377
|
+
}
|
|
25378
|
+
const popMatch = line.match(/^\s*(?:([\p{L}\p{N}_]+)\s*=\s*)?([\p{L}\p{N}_]+)\.pop\s*\(\s*(-?\d+)?\s*\)\s*$/u);
|
|
25379
|
+
const delMatch = line.match(/^\s*del\s+([\p{L}\p{N}_]+)\s*\[\s*(-?\d+)\s*\]\s*$/u);
|
|
25380
|
+
if (popMatch || delMatch) {
|
|
25381
|
+
const receiver = popMatch ? popMatch[2] : delMatch[1];
|
|
25382
|
+
const rawIndex = popMatch ? popMatch[3] !== undefined ? Number(popMatch[3]) : -1 : Number(delMatch[2]);
|
|
25383
|
+
const elems = listElems.get(receiver);
|
|
25384
|
+
if (elems) {
|
|
25385
|
+
const idx = normalizeListIndex(rawIndex, elems.length);
|
|
25386
|
+
if (idx === undefined)
|
|
25387
|
+
listElems.delete(receiver);
|
|
25388
|
+
else {
|
|
25389
|
+
const [removed] = elems.splice(idx, 1);
|
|
25390
|
+
if (popMatch && popMatch[1]) {
|
|
25391
|
+
if (removed)
|
|
25392
|
+
tainted.set(popMatch[1], i2 + 1);
|
|
25393
|
+
else
|
|
25394
|
+
tainted.delete(popMatch[1]);
|
|
25395
|
+
}
|
|
25396
|
+
}
|
|
25397
|
+
}
|
|
25750
25398
|
continue;
|
|
25751
25399
|
}
|
|
25752
25400
|
const augAssign = line.match(/^\s*([\p{L}\p{N}_]+)\s*\+=\s*(.+)$/u);
|
|
@@ -25769,7 +25417,51 @@ function buildPythonTaintedVars(sourceCode) {
|
|
|
25769
25417
|
const assignMatch = line.match(/^\s*([\p{L}\p{N}_]+)\s*=\s*(.+)$/u);
|
|
25770
25418
|
if (!assignMatch)
|
|
25771
25419
|
continue;
|
|
25772
|
-
const [, lhs,
|
|
25420
|
+
const [, lhs, rhsRaw] = assignMatch;
|
|
25421
|
+
const constValue = evaluatePythonConstExpression(rhsRaw.trim(), intConsts);
|
|
25422
|
+
if (typeof constValue === "number")
|
|
25423
|
+
intConsts.set(lhs, constValue);
|
|
25424
|
+
else
|
|
25425
|
+
intConsts.delete(lhs);
|
|
25426
|
+
let rhs = rhsRaw;
|
|
25427
|
+
const ternary = rhsRaw.match(/^(.+?)\s+if\s+(.+?)\s+else\s+(.+)$/);
|
|
25428
|
+
if (ternary) {
|
|
25429
|
+
const decided = evaluatePythonConstExpression(ternary[2].trim(), intConsts);
|
|
25430
|
+
if (decided === true)
|
|
25431
|
+
rhs = ternary[1].trim();
|
|
25432
|
+
else if (decided === false)
|
|
25433
|
+
rhs = ternary[3].trim();
|
|
25434
|
+
}
|
|
25435
|
+
const listLiteral = rhs.trim().match(/^\[\s*(.*?)\s*\]$/);
|
|
25436
|
+
if (listLiteral) {
|
|
25437
|
+
const inner = listLiteral[1];
|
|
25438
|
+
if (inner === "") {
|
|
25439
|
+
listElems.set(lhs, []);
|
|
25440
|
+
} else if (!inner.includes("[") && !inner.includes("(")) {
|
|
25441
|
+
listElems.set(lhs, inner.split(",").map((part) => {
|
|
25442
|
+
const expr = part.trim();
|
|
25443
|
+
return [...tainted.keys()].some((v) => new RegExp(`(?<![\\p{L}\\p{N}_])${v}(?![\\p{L}\\p{N}_])`, "u").test(expr)) || PYTHON_TAINTED_PATTERNS2.some((p) => p.pattern.test(expr));
|
|
25444
|
+
}));
|
|
25445
|
+
} else {
|
|
25446
|
+
listElems.delete(lhs);
|
|
25447
|
+
}
|
|
25448
|
+
} else {
|
|
25449
|
+
listElems.delete(lhs);
|
|
25450
|
+
}
|
|
25451
|
+
const indexRead = rhs.trim().match(/^([\p{L}\p{N}_]+)\s*\[\s*(-?\d+)\s*\]$/u);
|
|
25452
|
+
if (indexRead) {
|
|
25453
|
+
const elems = listElems.get(indexRead[1]);
|
|
25454
|
+
if (elems) {
|
|
25455
|
+
const idx = normalizeListIndex(Number(indexRead[2]), elems.length);
|
|
25456
|
+
if (idx !== undefined) {
|
|
25457
|
+
if (elems[idx])
|
|
25458
|
+
tainted.set(lhs, i2 + 1);
|
|
25459
|
+
else
|
|
25460
|
+
tainted.delete(lhs);
|
|
25461
|
+
continue;
|
|
25462
|
+
}
|
|
25463
|
+
}
|
|
25464
|
+
}
|
|
25773
25465
|
const isDirectSource = PYTHON_TAINTED_PATTERNS2.some((p) => p.pattern.test(rhs));
|
|
25774
25466
|
let propagatedFrom;
|
|
25775
25467
|
const dictAccessMatch = rhs.trim().match(/^([\p{L}\p{N}_]+)\[(['"])([^'"]+)\2\]$/u);
|
|
@@ -27024,6 +26716,210 @@ function findPythonSetMembershipXssGuardSanitizers(code) {
|
|
|
27024
26716
|
}
|
|
27025
26717
|
return sanitizers;
|
|
27026
26718
|
}
|
|
26719
|
+
function findPythonTraversalRejectGuardSanitizers(code) {
|
|
26720
|
+
const sanitizers = [];
|
|
26721
|
+
const lines = code.split(`
|
|
26722
|
+
`);
|
|
26723
|
+
const guardOpen = /^(\s*)if\s+(['"])(\.\.[/\\]?)\2\s+in\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*$/;
|
|
26724
|
+
const terminator = /\b(return|raise|abort\s*\(|sys\.exit\s*\()/;
|
|
26725
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
26726
|
+
const m = guardOpen.exec(lines[i2]);
|
|
26727
|
+
if (!m)
|
|
26728
|
+
continue;
|
|
26729
|
+
const guardIndent = m[1].length;
|
|
26730
|
+
const guardedVar = m[4];
|
|
26731
|
+
let bodyHasTerminator = false;
|
|
26732
|
+
let blockEnd = -1;
|
|
26733
|
+
const maxScan = Math.min(lines.length, i2 + 26);
|
|
26734
|
+
for (let j = i2 + 1;j < maxScan; j++) {
|
|
26735
|
+
const line = lines[j];
|
|
26736
|
+
if (line.trim() === "")
|
|
26737
|
+
continue;
|
|
26738
|
+
const indent = line.length - line.trimStart().length;
|
|
26739
|
+
if (indent <= guardIndent) {
|
|
26740
|
+
blockEnd = j - 1;
|
|
26741
|
+
break;
|
|
26742
|
+
}
|
|
26743
|
+
if (terminator.test(line))
|
|
26744
|
+
bodyHasTerminator = true;
|
|
26745
|
+
}
|
|
26746
|
+
if (blockEnd === -1)
|
|
26747
|
+
blockEnd = Math.min(lines.length - 1, i2 + 25);
|
|
26748
|
+
if (!bodyHasTerminator)
|
|
26749
|
+
continue;
|
|
26750
|
+
const guarded = new Set([guardedVar]);
|
|
26751
|
+
const assignRe = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=(?!=)\s*(.*)$/;
|
|
26752
|
+
const mentionsGuarded = (text) => {
|
|
26753
|
+
for (const name2 of guarded) {
|
|
26754
|
+
if (new RegExp(`\\b${name2}\\b`).test(text))
|
|
26755
|
+
return true;
|
|
26756
|
+
}
|
|
26757
|
+
return false;
|
|
26758
|
+
};
|
|
26759
|
+
for (let l = blockEnd + 2;l <= lines.length; l++) {
|
|
26760
|
+
const lineText = lines[l - 1];
|
|
26761
|
+
const assign = assignRe.exec(lineText);
|
|
26762
|
+
if (assign) {
|
|
26763
|
+
const target = assign[1];
|
|
26764
|
+
const rhs = assign[2];
|
|
26765
|
+
if (mentionsGuarded(rhs))
|
|
26766
|
+
guarded.add(target);
|
|
26767
|
+
else if (target !== guardedVar)
|
|
26768
|
+
guarded.delete(target);
|
|
26769
|
+
}
|
|
26770
|
+
if (!mentionsGuarded(lineText))
|
|
26771
|
+
continue;
|
|
26772
|
+
sanitizers.push({
|
|
26773
|
+
type: "python_traversal_reject_guard",
|
|
26774
|
+
method: "if",
|
|
26775
|
+
line: l,
|
|
26776
|
+
sanitizes: ["path_traversal"]
|
|
26777
|
+
});
|
|
26778
|
+
}
|
|
26779
|
+
}
|
|
26780
|
+
return sanitizers;
|
|
26781
|
+
}
|
|
26782
|
+
function findPythonStringLiteralGuardSanitizers(code) {
|
|
26783
|
+
const sanitizers = [];
|
|
26784
|
+
const lines = code.split(`
|
|
26785
|
+
`);
|
|
26786
|
+
const terminator = /\b(return|raise|abort\s*\(|sys\.exit\s*\()/;
|
|
26787
|
+
const Q = `(?:'(?:\\\\')'|"'"|'"'|"(?:\\\\")")`;
|
|
26788
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
26789
|
+
const guard = lines[i2].match(new RegExp(`^(\\s*)if\\s+not\\s+([A-Za-z_][A-Za-z0-9_]*)\\.startswith\\(\\s*${Q}\\s*\\)` + `\\s+or\\s+not\\s+\\2\\.endswith\\(\\s*${Q}\\s*\\)` + `\\s+or\\s+${Q}\\s+in\\s+\\2\\[1:-1\\]\\s*:\\s*$`));
|
|
26790
|
+
if (!guard)
|
|
26791
|
+
continue;
|
|
26792
|
+
const guardIndent = guard[1].length;
|
|
26793
|
+
const guardedVar = guard[2];
|
|
26794
|
+
let bodyHasTerminator = false;
|
|
26795
|
+
let blockEnd = -1;
|
|
26796
|
+
const maxScan = Math.min(lines.length, i2 + 26);
|
|
26797
|
+
for (let j = i2 + 1;j < maxScan; j++) {
|
|
26798
|
+
const line = lines[j];
|
|
26799
|
+
if (line.trim() === "")
|
|
26800
|
+
continue;
|
|
26801
|
+
const indent = line.length - line.trimStart().length;
|
|
26802
|
+
if (indent <= guardIndent) {
|
|
26803
|
+
blockEnd = j - 1;
|
|
26804
|
+
break;
|
|
26805
|
+
}
|
|
26806
|
+
if (terminator.test(line))
|
|
26807
|
+
bodyHasTerminator = true;
|
|
26808
|
+
}
|
|
26809
|
+
if (blockEnd === -1)
|
|
26810
|
+
blockEnd = Math.min(lines.length - 1, i2 + 25);
|
|
26811
|
+
if (!bodyHasTerminator)
|
|
26812
|
+
continue;
|
|
26813
|
+
const varRe = new RegExp(`\\b${guardedVar}\\b`);
|
|
26814
|
+
for (let l = blockEnd + 2;l <= lines.length; l++) {
|
|
26815
|
+
if (!varRe.test(lines[l - 1]))
|
|
26816
|
+
continue;
|
|
26817
|
+
sanitizers.push({
|
|
26818
|
+
type: "python_string_literal_guard",
|
|
26819
|
+
method: "if",
|
|
26820
|
+
line: l,
|
|
26821
|
+
sanitizes: ["code_injection"]
|
|
26822
|
+
});
|
|
26823
|
+
}
|
|
26824
|
+
}
|
|
26825
|
+
return sanitizers;
|
|
26826
|
+
}
|
|
26827
|
+
function findPythonDefaultSaxParserXxeSanitizers(code) {
|
|
26828
|
+
const sanitizers = [];
|
|
26829
|
+
const lines = code.split(`
|
|
26830
|
+
`);
|
|
26831
|
+
const parserVars = new Set;
|
|
26832
|
+
for (const line of lines) {
|
|
26833
|
+
const made = line.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(?:xml\.)?sax\.make_parser\s*\(/);
|
|
26834
|
+
if (made)
|
|
26835
|
+
parserVars.add(made[1]);
|
|
26836
|
+
}
|
|
26837
|
+
if (parserVars.size === 0)
|
|
26838
|
+
return sanitizers;
|
|
26839
|
+
for (const line of lines) {
|
|
26840
|
+
for (const parser of [...parserVars]) {
|
|
26841
|
+
const enabled = new RegExp(`\\b${parser}\\.setFeature\\s*\\([^,]*external_(?:ges|pes)[^,]*,\\s*True\\s*\\)`);
|
|
26842
|
+
const resolver = new RegExp(`\\b${parser}\\.setEntityResolver\\s*\\(`);
|
|
26843
|
+
const rebound = new RegExp(`^\\s*${parser}\\s*=(?!=)`);
|
|
26844
|
+
if (enabled.test(line) || resolver.test(line))
|
|
26845
|
+
parserVars.delete(parser);
|
|
26846
|
+
else if (rebound.test(line) && !/make_parser\s*\(/.test(line))
|
|
26847
|
+
parserVars.delete(parser);
|
|
26848
|
+
}
|
|
26849
|
+
}
|
|
26850
|
+
if (parserVars.size === 0)
|
|
26851
|
+
return sanitizers;
|
|
26852
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
26853
|
+
const line = lines[i2];
|
|
26854
|
+
const parseCall = /\b(?:minidom\.)?parseString\s*\(|\b(?:minidom\.)?parse\s*\(|\bsax\.parse(?:String)?\s*\(/;
|
|
26855
|
+
if (!parseCall.test(line))
|
|
26856
|
+
continue;
|
|
26857
|
+
const usesDefaultParser = [...parserVars].some((p) => new RegExp(`\\b${p}\\b`).test(line));
|
|
26858
|
+
if (!usesDefaultParser)
|
|
26859
|
+
continue;
|
|
26860
|
+
sanitizers.push({
|
|
26861
|
+
type: "python_default_sax_parser",
|
|
26862
|
+
method: "make_parser",
|
|
26863
|
+
line: i2 + 1,
|
|
26864
|
+
sanitizes: ["xxe"]
|
|
26865
|
+
});
|
|
26866
|
+
}
|
|
26867
|
+
return sanitizers;
|
|
26868
|
+
}
|
|
26869
|
+
function findPythonUrlAllowlistRedirectSanitizers(code) {
|
|
26870
|
+
const sanitizers = [];
|
|
26871
|
+
const lines = code.split(`
|
|
26872
|
+
`);
|
|
26873
|
+
const parsedFrom = new Map;
|
|
26874
|
+
for (const line of lines) {
|
|
26875
|
+
const m = line.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(?:urllib\.parse\.)?urlparse\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*\)/);
|
|
26876
|
+
if (m)
|
|
26877
|
+
parsedFrom.set(m[1], m[2]);
|
|
26878
|
+
}
|
|
26879
|
+
if (parsedFrom.size === 0)
|
|
26880
|
+
return sanitizers;
|
|
26881
|
+
const terminator = /\b(return|raise|abort\s*\(|sys\.exit\s*\()/;
|
|
26882
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
26883
|
+
const guard = lines[i2].match(/^(\s*)if\s+([A-Za-z_][A-Za-z0-9_]*)\.netloc\s+not\s+in\s+[[({]/);
|
|
26884
|
+
if (!guard)
|
|
26885
|
+
continue;
|
|
26886
|
+
const guardIndent = guard[1].length;
|
|
26887
|
+
const rawVar = parsedFrom.get(guard[2]);
|
|
26888
|
+
if (!rawVar)
|
|
26889
|
+
continue;
|
|
26890
|
+
let bodyHasTerminator = false;
|
|
26891
|
+
let blockEnd = -1;
|
|
26892
|
+
const maxScan = Math.min(lines.length, i2 + 26);
|
|
26893
|
+
for (let j = i2 + 1;j < maxScan; j++) {
|
|
26894
|
+
const line = lines[j];
|
|
26895
|
+
if (line.trim() === "")
|
|
26896
|
+
continue;
|
|
26897
|
+
const indent = line.length - line.trimStart().length;
|
|
26898
|
+
if (indent <= guardIndent) {
|
|
26899
|
+
blockEnd = j - 1;
|
|
26900
|
+
break;
|
|
26901
|
+
}
|
|
26902
|
+
if (terminator.test(line))
|
|
26903
|
+
bodyHasTerminator = true;
|
|
26904
|
+
}
|
|
26905
|
+
if (blockEnd === -1)
|
|
26906
|
+
blockEnd = Math.min(lines.length - 1, i2 + 25);
|
|
26907
|
+
if (!bodyHasTerminator)
|
|
26908
|
+
continue;
|
|
26909
|
+
const varRe = new RegExp(`\\b${rawVar}\\b`);
|
|
26910
|
+
for (let l = blockEnd + 2;l <= lines.length; l++) {
|
|
26911
|
+
if (!varRe.test(lines[l - 1]))
|
|
26912
|
+
continue;
|
|
26913
|
+
sanitizers.push({
|
|
26914
|
+
type: "python_url_allowlist_guard",
|
|
26915
|
+
method: "if",
|
|
26916
|
+
line: l,
|
|
26917
|
+
sanitizes: ["open_redirect"]
|
|
26918
|
+
});
|
|
26919
|
+
}
|
|
26920
|
+
}
|
|
26921
|
+
return sanitizers;
|
|
26922
|
+
}
|
|
27027
26923
|
function findPythonDefusedXmlSanitizers(code) {
|
|
27028
26924
|
const sanitizers = [];
|
|
27029
26925
|
const lines = code.split(`
|
|
@@ -32044,14 +31940,20 @@ class SinkFilterPass {
|
|
|
32044
31940
|
if (sink.type !== "xpath_injection")
|
|
32045
31941
|
return true;
|
|
32046
31942
|
const sinkLineText = sourceLines[sink.line - 1] ?? "";
|
|
32047
|
-
const
|
|
31943
|
+
const taintedValueVars = [...pyTaintedVars.keys()].filter((v) => new RegExp(`(?<![\\w.])${v}\\b(?!\\s*=(?!=))`).test(sinkLineText));
|
|
31944
|
+
const taintedVarOnLine = taintedValueVars[0];
|
|
32048
31945
|
const oopVarOnLine = [...oopFieldVars].find((v) => sinkLineText.includes(v));
|
|
32049
31946
|
if (oopVarOnLine)
|
|
32050
31947
|
return true;
|
|
32051
31948
|
if (!taintedVarOnLine)
|
|
32052
31949
|
return false;
|
|
31950
|
+
const neutralised = (v) => pySanitizedVars.has(v) || new RegExp(`\\.xpath\\s*\\([^)]*\\b\\w+\\s*=\\s*\\b${v}\\b`).test(sinkLineText) || isXPathQuoteEscapedOnLine(sinkLineText, v);
|
|
31951
|
+
if (taintedValueVars.every(neutralised))
|
|
31952
|
+
return false;
|
|
32053
31953
|
if (pySanitizedVars.has(taintedVarOnLine))
|
|
32054
31954
|
return false;
|
|
31955
|
+
if (isXPathQuoteEscapedOnLine(sinkLineText, taintedVarOnLine))
|
|
31956
|
+
return false;
|
|
32055
31957
|
if (new RegExp(`\\.xpath\\s*\\([^)]*\\b\\w+\\s*=\\s*\\b${taintedVarOnLine}\\b`).test(sinkLineText))
|
|
32056
31958
|
return false;
|
|
32057
31959
|
return true;
|
|
@@ -33155,6 +33057,28 @@ function filterSanitizedSinks(sinks, sanitizers, calls) {
|
|
|
33155
33057
|
return true;
|
|
33156
33058
|
});
|
|
33157
33059
|
}
|
|
33060
|
+
function isXPathQuoteEscapedOnLine(lineText, varName) {
|
|
33061
|
+
const STRING_LITERAL = `'(?:[^'\\\\]|\\\\.)*'|"(?:[^"\\\\]|\\\\.)*"`;
|
|
33062
|
+
const replaceCall = new RegExp(`^${varName}\\.replace\\s*\\(\\s*(${STRING_LITERAL})\\s*,\\s*(${STRING_LITERAL})\\s*\\)`);
|
|
33063
|
+
const decode = (literal) => literal.slice(1, -1).replace(/\\(.)/g, "$1");
|
|
33064
|
+
const occurrence = new RegExp(`(?<![\\w.])${varName}\\b`, "g");
|
|
33065
|
+
let match;
|
|
33066
|
+
let seen = 0;
|
|
33067
|
+
while ((match = occurrence.exec(lineText)) !== null) {
|
|
33068
|
+
seen++;
|
|
33069
|
+
const rest = lineText.slice(match.index);
|
|
33070
|
+
const call = replaceCall.exec(rest);
|
|
33071
|
+
if (!call)
|
|
33072
|
+
return false;
|
|
33073
|
+
const searched = decode(call[1]);
|
|
33074
|
+
const replacement = decode(call[2]);
|
|
33075
|
+
if (searched !== "'" && searched !== '"')
|
|
33076
|
+
return false;
|
|
33077
|
+
if (replacement.includes("'") || replacement.includes('"'))
|
|
33078
|
+
return false;
|
|
33079
|
+
}
|
|
33080
|
+
return seen > 0;
|
|
33081
|
+
}
|
|
33158
33082
|
|
|
33159
33083
|
// ../circle-ir/dist/analysis/passes/sink-semantics-pass.js
|
|
33160
33084
|
function buildRegistry(entries) {
|
|
@@ -46492,7 +46416,7 @@ var colors = {
|
|
|
46492
46416
|
};
|
|
46493
46417
|
|
|
46494
46418
|
// src/version.ts
|
|
46495
|
-
var version = "3.
|
|
46419
|
+
var version = "3.197.0";
|
|
46496
46420
|
|
|
46497
46421
|
// src/formatters.ts
|
|
46498
46422
|
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.197.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.197.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/node": "^25.5.0",
|