checkmate5 4.0.67__py3-none-any.whl
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.
- checkmate/__init__.py +21 -0
- checkmate/__main__.py +25 -0
- checkmate/contrib/__init__.py +21 -0
- checkmate/contrib/plugins/__init__.py +0 -0
- checkmate/contrib/plugins/all/gptanalyzer/__init__.py +0 -0
- checkmate/contrib/plugins/all/gptanalyzer/analyzer.py +99 -0
- checkmate/contrib/plugins/all/gptanalyzer/issues_data.py +6 -0
- checkmate/contrib/plugins/all/gptanalyzer/setup.py +13 -0
- checkmate/contrib/plugins/cve/__init__.py +0 -0
- checkmate/contrib/plugins/cve/text4shell/__init__.py +0 -0
- checkmate/contrib/plugins/cve/text4shell/analyzer.py +64 -0
- checkmate/contrib/plugins/cve/text4shell/issues_data.py +8 -0
- checkmate/contrib/plugins/cve/text4shell/setup.py +13 -0
- checkmate/contrib/plugins/git/__init__.py +0 -0
- checkmate/contrib/plugins/git/commands/__init__.py +6 -0
- checkmate/contrib/plugins/git/commands/analyze.py +364 -0
- checkmate/contrib/plugins/git/commands/base.py +16 -0
- checkmate/contrib/plugins/git/commands/diff.py +199 -0
- checkmate/contrib/plugins/git/commands/init.py +59 -0
- checkmate/contrib/plugins/git/commands/update_stats.py +41 -0
- checkmate/contrib/plugins/git/hooks/__init__.py +0 -0
- checkmate/contrib/plugins/git/hooks/project.py +19 -0
- checkmate/contrib/plugins/git/lib/__init__.py +1 -0
- checkmate/contrib/plugins/git/lib/repository.py +557 -0
- checkmate/contrib/plugins/git/lib/repository_pygit2.py +531 -0
- checkmate/contrib/plugins/git/models.py +178 -0
- checkmate/contrib/plugins/git/setup.py +27 -0
- checkmate/contrib/plugins/golang/__init__.py +0 -0
- checkmate/contrib/plugins/golang/gostaticcheck/__init__.py +0 -0
- checkmate/contrib/plugins/golang/gostaticcheck/analyzer.py +94 -0
- checkmate/contrib/plugins/golang/gostaticcheck/issues_data.py +1246 -0
- checkmate/contrib/plugins/golang/gostaticcheck/setup.py +13 -0
- checkmate/contrib/plugins/iac/__init__.py +0 -0
- checkmate/contrib/plugins/iac/kubescape/__init__.py +0 -0
- checkmate/contrib/plugins/iac/kubescape/analyzer.py +115 -0
- checkmate/contrib/plugins/iac/kubescape/issues_data.py +636 -0
- checkmate/contrib/plugins/iac/kubescape/setup.py +14 -0
- checkmate/contrib/plugins/iac/tfsec/__init__.py +0 -0
- checkmate/contrib/plugins/iac/tfsec/analyzer.py +92 -0
- checkmate/contrib/plugins/iac/tfsec/issues_data.py +1917 -0
- checkmate/contrib/plugins/iac/tfsec/setup.py +13 -0
- checkmate/contrib/plugins/java/__init__.py +0 -0
- checkmate/contrib/plugins/java/semgrepjava/__init__.py +0 -0
- checkmate/contrib/plugins/java/semgrepjava/analyzer.py +96 -0
- checkmate/contrib/plugins/java/semgrepjava/issues_data.py +5 -0
- checkmate/contrib/plugins/java/semgrepjava/setup.py +13 -0
- checkmate/contrib/plugins/javascript/__init__.py +0 -0
- checkmate/contrib/plugins/javascript/semgrepeslint/__init__.py +0 -0
- checkmate/contrib/plugins/javascript/semgrepeslint/analyzer.py +95 -0
- checkmate/contrib/plugins/javascript/semgrepeslint/issues_data.py +6 -0
- checkmate/contrib/plugins/javascript/semgrepeslint/setup.py +13 -0
- checkmate/contrib/plugins/perl/__init__.py +0 -0
- checkmate/contrib/plugins/perl/graudit/__init__.py +0 -0
- checkmate/contrib/plugins/perl/graudit/analyzer.py +70 -0
- checkmate/contrib/plugins/perl/graudit/issues_data.py +8 -0
- checkmate/contrib/plugins/perl/graudit/setup.py +13 -0
- checkmate/contrib/plugins/python/__init__.py +0 -0
- checkmate/contrib/plugins/python/bandit/__init__.py +0 -0
- checkmate/contrib/plugins/python/bandit/analyzer.py +74 -0
- checkmate/contrib/plugins/python/bandit/issues_data.py +426 -0
- checkmate/contrib/plugins/python/bandit/setup.py +13 -0
- checkmate/contrib/plugins/ruby/__init__.py +0 -0
- checkmate/contrib/plugins/ruby/brakeman/__init__.py +0 -0
- checkmate/contrib/plugins/ruby/brakeman/analyzer.py +96 -0
- checkmate/contrib/plugins/ruby/brakeman/issues_data.py +518 -0
- checkmate/contrib/plugins/ruby/brakeman/setup.py +13 -0
- checkmate/helpers/__init__.py +0 -0
- checkmate/helpers/facts.py +26 -0
- checkmate/helpers/hashing.py +68 -0
- checkmate/helpers/issue.py +101 -0
- checkmate/helpers/settings.py +14 -0
- checkmate/lib/__init__.py +1 -0
- checkmate/lib/analysis/__init__.py +3 -0
- checkmate/lib/analysis/base.py +103 -0
- checkmate/lib/code/__init__.py +3 -0
- checkmate/lib/code/environment.py +809 -0
- checkmate/lib/models.py +515 -0
- checkmate/lib/stats/__init__.py +1 -0
- checkmate/lib/stats/helpers.py +19 -0
- checkmate/lib/stats/mapreduce.py +29 -0
- checkmate/management/__init__.py +1 -0
- checkmate/management/commands/__init__.py +18 -0
- checkmate/management/commands/alembic.py +32 -0
- checkmate/management/commands/analyze.py +42 -0
- checkmate/management/commands/analyzers.py +1 -0
- checkmate/management/commands/base.py +66 -0
- checkmate/management/commands/compare.py +0 -0
- checkmate/management/commands/export.py +0 -0
- checkmate/management/commands/info.py +0 -0
- checkmate/management/commands/init.py +103 -0
- checkmate/management/commands/issues.py +478 -0
- checkmate/management/commands/props/__init__.py +1 -0
- checkmate/management/commands/props/delete.py +29 -0
- checkmate/management/commands/props/get.py +30 -0
- checkmate/management/commands/props/set.py +29 -0
- checkmate/management/commands/reset.py +53 -0
- checkmate/management/commands/shell.py +19 -0
- checkmate/management/commands/snapshots.py +22 -0
- checkmate/management/commands/stats.py +21 -0
- checkmate/management/commands/summary.py +19 -0
- checkmate/management/commands/sync.py +63 -0
- checkmate/management/commands/trend.py +1 -0
- checkmate/management/commands/watch.py +27 -0
- checkmate/management/decorators.py +1 -0
- checkmate/management/helpers.py +140 -0
- checkmate/scripts/__init__.py +18 -0
- checkmate/scripts/manage.py +121 -0
- checkmate/settings/__init__.py +2 -0
- checkmate/settings/base.py +127 -0
- checkmate/settings/defaults.py +133 -0
- checkmate5-4.0.67.dist-info/LICENSE.txt +4095 -0
- checkmate5-4.0.67.dist-info/METADATA +15 -0
- checkmate5-4.0.67.dist-info/RECORD +116 -0
- checkmate5-4.0.67.dist-info/WHEEL +5 -0
- checkmate5-4.0.67.dist-info/entry_points.txt +2 -0
- checkmate5-4.0.67.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from collections import defaultdict
|
|
2
|
+
from checkmate.lib.stats.mapreduce import MapReducer
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class IssuesMapReducer(MapReducer):
|
|
6
|
+
|
|
7
|
+
def __init__(self, aggregators, count_column='count', group_by=['language', 'analyzer', 'code']):
|
|
8
|
+
self.aggregators = aggregators
|
|
9
|
+
self.count_column = count_column
|
|
10
|
+
self.group_by = group_by
|
|
11
|
+
|
|
12
|
+
def map(self, item):
|
|
13
|
+
for group in self.group_by:
|
|
14
|
+
if not group in item:
|
|
15
|
+
return []
|
|
16
|
+
return [(key, item) for aggregator in self.aggregators
|
|
17
|
+
for key in aggregator(item)]
|
|
18
|
+
|
|
19
|
+
def reduce(self, key, items):
|
|
20
|
+
grouped_issues = {}
|
|
21
|
+
|
|
22
|
+
if self.group_by:
|
|
23
|
+
for item in items:
|
|
24
|
+
invalid_item = False
|
|
25
|
+
current_dict = grouped_issues
|
|
26
|
+
for group in self.group_by[:-1]:
|
|
27
|
+
if not group in item:
|
|
28
|
+
invalid_item = True
|
|
29
|
+
break
|
|
30
|
+
if not item[group] in current_dict:
|
|
31
|
+
current_dict[item[group]] = {}
|
|
32
|
+
current_dict = current_dict[item[group]]
|
|
33
|
+
if not self.group_by[-1] in item:
|
|
34
|
+
invalid_item = True
|
|
35
|
+
if invalid_item:
|
|
36
|
+
continue
|
|
37
|
+
if not item[self.group_by[-1]] in current_dict:
|
|
38
|
+
current_dict[item[self.group_by[-1]]] = [0, 0]
|
|
39
|
+
cd = current_dict[item[self.group_by[-1]]]
|
|
40
|
+
cd[0] += 1
|
|
41
|
+
cd[1] += item[self.count_column]
|
|
42
|
+
return grouped_issues
|
|
43
|
+
else:
|
|
44
|
+
issues_sum = [0, 0]
|
|
45
|
+
for item in items:
|
|
46
|
+
issues_sum[0] += 1
|
|
47
|
+
issues_sum[1] += item[self.count_column]
|
|
48
|
+
return issues_sum
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def group_issues_by_fingerprint(issues):
|
|
52
|
+
"""
|
|
53
|
+
Groups issues by fingerprint. Grouping is done by issue code in addition.
|
|
54
|
+
IMPORTANT: It is assumed that all issues come from the SAME analyzer.
|
|
55
|
+
"""
|
|
56
|
+
issues_by_fingerprint = defaultdict(list)
|
|
57
|
+
for issue in issues:
|
|
58
|
+
if not 'fingerprint' in issue:
|
|
59
|
+
raise AttributeError("No fingerprint defined for issue with analyzer %s and code %s!" %
|
|
60
|
+
(issue.get('analyzer', '(undefined)'), issue['code']))
|
|
61
|
+
fp_code = "%s:%s" % (issue['fingerprint'], issue['code'])
|
|
62
|
+
if fp_code in issues_by_fingerprint:
|
|
63
|
+
grouped_issue = issues_by_fingerprint[fp_code]
|
|
64
|
+
else:
|
|
65
|
+
grouped_issue = issue.copy()
|
|
66
|
+
grouped_issue['occurrences'] = []
|
|
67
|
+
if 'location' in grouped_issue:
|
|
68
|
+
del grouped_issue['location']
|
|
69
|
+
issues_by_fingerprint[fp_code] = grouped_issue
|
|
70
|
+
|
|
71
|
+
locations = issue.get('location', [])
|
|
72
|
+
if locations:
|
|
73
|
+
for i, start_stop in enumerate(locations):
|
|
74
|
+
|
|
75
|
+
occurrence = {
|
|
76
|
+
'from_row': None,
|
|
77
|
+
'to_row': None,
|
|
78
|
+
'from_column': None,
|
|
79
|
+
'to_column': None,
|
|
80
|
+
'sequence': i
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
grouped_issue['occurrences'].append(occurrence)
|
|
84
|
+
|
|
85
|
+
if not isinstance(start_stop, (list, tuple)) or not len(start_stop) == 2:
|
|
86
|
+
continue
|
|
87
|
+
|
|
88
|
+
start, stop = start_stop
|
|
89
|
+
|
|
90
|
+
if isinstance(start, (list, tuple)) and len(start) == 2:
|
|
91
|
+
occurrence['from_row'] = start[0]
|
|
92
|
+
occurrence['from_column'] = start[1]
|
|
93
|
+
|
|
94
|
+
if isinstance(stop, (list, tuple)) and len(stop) == 2:
|
|
95
|
+
occurrence['to_row'] = stop[0]
|
|
96
|
+
occurrence['to_column'] = stop[1]
|
|
97
|
+
|
|
98
|
+
grouped_issue['occurrences'] = sorted(
|
|
99
|
+
grouped_issue['occurrences'], key=lambda x: (x['from_row'], x['from_column']))
|
|
100
|
+
|
|
101
|
+
return list(issues_by_fingerprint.values())
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
def update(d, ud):
|
|
3
|
+
"""
|
|
4
|
+
Recursively merge the values of ud into d.
|
|
5
|
+
"""
|
|
6
|
+
if ud is None:
|
|
7
|
+
return
|
|
8
|
+
for key, value in list(ud.items()):
|
|
9
|
+
if not key in d:
|
|
10
|
+
d[key] = value
|
|
11
|
+
elif isinstance(value, dict):
|
|
12
|
+
update(d[key], value)
|
|
13
|
+
else:
|
|
14
|
+
d[key] = value
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import abc
|
|
5
|
+
from checkmate.helpers.hashing import Hasher
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AnalyzerSettingsError(BaseException):
|
|
9
|
+
|
|
10
|
+
def __init__(self, errors):
|
|
11
|
+
"Errors should be a dictionary"
|
|
12
|
+
self.errors = errors
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class BaseAnalyzer(object):
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
This abstract base class defines an analyzer, which takes file content and produces
|
|
19
|
+
statistics as well as a list of issues. It is also responsible for diffing statistical
|
|
20
|
+
data and issues obtained for different file revisions or snapshots.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self,
|
|
24
|
+
code_environment,
|
|
25
|
+
settings=None,
|
|
26
|
+
ignore=None):
|
|
27
|
+
self.code_environment = code_environment
|
|
28
|
+
if settings:
|
|
29
|
+
self.validate_settings(settings)
|
|
30
|
+
self.settings = settings
|
|
31
|
+
if ignore is not None:
|
|
32
|
+
self.ignore = {}
|
|
33
|
+
for code in ignore:
|
|
34
|
+
self.ignore[code] = True
|
|
35
|
+
|
|
36
|
+
def get_fingerprint_from_code(self, file_revision, location, extra_data=None):
|
|
37
|
+
"""
|
|
38
|
+
This function generates a fingerprint from a series of code snippets.
|
|
39
|
+
|
|
40
|
+
Can be used by derived analyzers to generate fingerprints based on code
|
|
41
|
+
if nothing better is available.
|
|
42
|
+
"""
|
|
43
|
+
code = file_revision.get_file_content()
|
|
44
|
+
if not isinstance(code, str):
|
|
45
|
+
code = str(code, errors='ignore')
|
|
46
|
+
lines = code.split("\n")
|
|
47
|
+
s = ""
|
|
48
|
+
for l in location:
|
|
49
|
+
((from_row, from_column), (to_row, to_column)) = l
|
|
50
|
+
if from_column is None:
|
|
51
|
+
continue
|
|
52
|
+
if from_row == to_row:
|
|
53
|
+
s += lines[from_row-1][from_column:to_column]
|
|
54
|
+
else:
|
|
55
|
+
if to_row < from_row:
|
|
56
|
+
raise ValueError("from_row must be smaller than to_row")
|
|
57
|
+
s += lines[from_row-1][from_column:]
|
|
58
|
+
current_row = from_row+1
|
|
59
|
+
while current_row < to_row:
|
|
60
|
+
s += lines[current_row-1]
|
|
61
|
+
current_row += 1
|
|
62
|
+
s += lines[current_row-1][:to_column]
|
|
63
|
+
|
|
64
|
+
hasher = Hasher()
|
|
65
|
+
hasher.add(s)
|
|
66
|
+
|
|
67
|
+
if extra_data is not None:
|
|
68
|
+
hasher.add(extra_data)
|
|
69
|
+
|
|
70
|
+
return hasher.digest.hexdigest()
|
|
71
|
+
|
|
72
|
+
@classmethod
|
|
73
|
+
def validate_settings(cls, settings):
|
|
74
|
+
# should raise AnalyzerSettingsError if the settings are not valid
|
|
75
|
+
raise NotImplementedError
|
|
76
|
+
|
|
77
|
+
@abc.abstractmethod
|
|
78
|
+
def analyze(self, file_revision):
|
|
79
|
+
"""
|
|
80
|
+
Analyze a file and return a tuple (stats,issues) containing statistics and issues.
|
|
81
|
+
|
|
82
|
+
This method should return a dictionary with one of the following entries:
|
|
83
|
+
|
|
84
|
+
* issues: A list of issues found in the file revision
|
|
85
|
+
* stats: Statistics about the file revision
|
|
86
|
+
* depends_on: A list of dependencies for the file revision
|
|
87
|
+
* provides: A list of things the file revision provides (e.g. a module),
|
|
88
|
+
to be used with the `depends_on` field.
|
|
89
|
+
"""
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
def diff(self, results_a, results_b):
|
|
93
|
+
pass
|
|
94
|
+
|
|
95
|
+
def diff_summary(self, summary_a, summary_b):
|
|
96
|
+
pass
|
|
97
|
+
|
|
98
|
+
@abc.abstractmethod
|
|
99
|
+
def summarize(self, items):
|
|
100
|
+
"""
|
|
101
|
+
Aggregate a list of items containing statistical information generated by 'analyze'.
|
|
102
|
+
"""
|
|
103
|
+
pass
|