troubadix 25.12.4__py3-none-any.whl → 26.2.0__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.
- troubadix/__version__.py +1 -1
- troubadix/argparser.py +4 -14
- troubadix/helper/date_format.py +3 -8
- troubadix/helper/helper.py +1 -3
- troubadix/helper/if_block_parser.py +14 -37
- troubadix/helper/linguistic_exception_handler.py +6 -18
- troubadix/helper/patterns.py +7 -19
- troubadix/helper/remove_comments.py +1 -4
- troubadix/helper/text_utils.py +1 -3
- troubadix/plugin.py +3 -9
- troubadix/plugins/__init__.py +6 -20
- troubadix/plugins/badwords.py +3 -9
- troubadix/plugins/copyright_text.py +2 -5
- troubadix/plugins/copyright_year.py +4 -12
- troubadix/plugins/creation_date.py +3 -9
- troubadix/plugins/cvss_format.py +1 -3
- troubadix/plugins/dependencies.py +2 -5
- troubadix/plugins/dependency_category_order.py +7 -20
- troubadix/plugins/deprecated_dependency.py +6 -16
- troubadix/plugins/deprecated_functions.py +2 -4
- troubadix/plugins/double_end_points.py +2 -7
- troubadix/plugins/duplicate_oid.py +1 -3
- troubadix/plugins/duplicated_script_tags.py +1 -2
- troubadix/plugins/forking_nasl_functions.py +1 -4
- troubadix/plugins/get_kb_on_services.py +2 -4
- troubadix/plugins/grammar.py +8 -20
- troubadix/plugins/http_links_in_tags.py +3 -6
- troubadix/plugins/illegal_characters.py +6 -15
- troubadix/plugins/log_messages.py +1 -2
- troubadix/plugins/malformed_dependencies.py +2 -6
- troubadix/plugins/missing_desc_exit.py +1 -3
- troubadix/plugins/multiple_re_parameters.py +2 -7
- troubadix/plugins/newlines.py +1 -2
- troubadix/plugins/overlong_description_lines.py +2 -6
- troubadix/plugins/overlong_script_tags.py +9 -14
- troubadix/plugins/prod_svc_detect_in_vulnvt.py +1 -4
- troubadix/plugins/qod.py +0 -1
- troubadix/plugins/script_add_preference_id.py +3 -10
- troubadix/plugins/script_add_preference_type.py +2 -7
- troubadix/plugins/script_calls_empty_values.py +3 -3
- troubadix/plugins/script_calls_recommended.py +5 -8
- troubadix/plugins/script_copyright.py +1 -3
- troubadix/plugins/script_family.py +1 -2
- troubadix/plugins/script_tag_form.py +1 -3
- troubadix/plugins/script_tag_whitespaces.py +5 -10
- troubadix/plugins/script_tags_mandatory.py +2 -5
- troubadix/plugins/script_version_and_last_modification_tags.py +6 -17
- troubadix/plugins/script_xref_form.py +1 -3
- troubadix/plugins/script_xref_url.py +3 -7
- troubadix/plugins/security_messages.py +8 -21
- troubadix/plugins/severity_date.py +3 -10
- troubadix/plugins/severity_format.py +1 -4
- troubadix/plugins/severity_origin.py +1 -4
- troubadix/plugins/solution_text.py +6 -10
- troubadix/plugins/solution_type.py +1 -2
- troubadix/plugins/spaces_before_dots.py +2 -9
- troubadix/plugins/spaces_in_filename.py +1 -2
- troubadix/plugins/spelling.py +5 -14
- troubadix/plugins/trailing_spaces_tabs.py +2 -5
- troubadix/plugins/using_display.py +2 -6
- troubadix/plugins/valid_oid.py +51 -60
- troubadix/plugins/valid_script_tag_names.py +2 -5
- troubadix/plugins/variable_assigned_in_if.py +2 -7
- troubadix/plugins/variable_redefinition_in_foreach.py +2 -6
- troubadix/plugins/vt_placement.py +2 -8
- troubadix/reporter.py +7 -21
- troubadix/results.py +2 -8
- troubadix/runner.py +5 -14
- troubadix/standalone_plugins/allowed_rev_diff.py +8 -25
- troubadix/standalone_plugins/changed_creation_date.py +4 -14
- troubadix/standalone_plugins/changed_cves.py +4 -12
- troubadix/standalone_plugins/changed_oid.py +3 -8
- troubadix/standalone_plugins/changed_packages/changed_packages.py +3 -8
- troubadix/standalone_plugins/changed_packages/marker/changed_update.py +1 -3
- troubadix/standalone_plugins/changed_packages/marker/dropped_architecture.py +1 -3
- troubadix/standalone_plugins/changed_packages/package.py +13 -7
- troubadix/standalone_plugins/dependency_graph/checks.py +5 -15
- troubadix/standalone_plugins/dependency_graph/dependency_graph.py +5 -13
- troubadix/standalone_plugins/deprecate_vts.py +3 -9
- troubadix/standalone_plugins/file_extensions.py +3 -10
- troubadix/standalone_plugins/last_modification.py +3 -9
- troubadix/standalone_plugins/no_solution.py +12 -34
- troubadix/standalone_plugins/util.py +0 -2
- troubadix/standalone_plugins/version_updated.py +5 -14
- troubadix/troubadix.py +1 -4
- {troubadix-25.12.4.dist-info → troubadix-26.2.0.dist-info}/METADATA +1 -1
- troubadix-26.2.0.dist-info/RECORD +116 -0
- {troubadix-25.12.4.dist-info → troubadix-26.2.0.dist-info}/WHEEL +1 -1
- troubadix-25.12.4.dist-info/RECORD +0 -116
- {troubadix-25.12.4.dist-info → troubadix-26.2.0.dist-info}/entry_points.txt +0 -0
- {troubadix-25.12.4.dist-info → troubadix-26.2.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -47,9 +47,7 @@ class CheckDeprecatedDependency(FilePlugin):
|
|
|
47
47
|
):
|
|
48
48
|
return
|
|
49
49
|
|
|
50
|
-
dependencies_pattern = get_special_script_tag_pattern(
|
|
51
|
-
SpecialScriptTag.DEPENDENCIES
|
|
52
|
-
)
|
|
50
|
+
dependencies_pattern = get_special_script_tag_pattern(SpecialScriptTag.DEPENDENCIES)
|
|
53
51
|
matches = dependencies_pattern.finditer(file_content)
|
|
54
52
|
if not matches:
|
|
55
53
|
return
|
|
@@ -70,9 +68,7 @@ class CheckDeprecatedDependency(FilePlugin):
|
|
|
70
68
|
if match:
|
|
71
69
|
# Remove single and/or double quotes, spaces
|
|
72
70
|
# and create a list by using the comma as a separator
|
|
73
|
-
dependencies = re.sub(
|
|
74
|
-
r'[\'"\s]', "", match.group("value")
|
|
75
|
-
).split(",")
|
|
71
|
+
dependencies = re.sub(r'[\'"\s]', "", match.group("value")).split(",")
|
|
76
72
|
|
|
77
73
|
for dep in dependencies:
|
|
78
74
|
dependency_path = None
|
|
@@ -82,23 +78,17 @@ class CheckDeprecatedDependency(FilePlugin):
|
|
|
82
78
|
|
|
83
79
|
if not dependency_path:
|
|
84
80
|
yield LinterError(
|
|
85
|
-
f"The script dependency {dep} could not "
|
|
86
|
-
"be found within the VTs.",
|
|
81
|
+
f"The script dependency {dep} could not be found within the VTs.",
|
|
87
82
|
file=self.context.nasl_file,
|
|
88
83
|
plugin=self.name,
|
|
89
84
|
)
|
|
90
85
|
else:
|
|
91
|
-
dependency_content = dependency_path.read_text(
|
|
92
|
-
encoding=CURRENT_ENCODING
|
|
93
|
-
)
|
|
86
|
+
dependency_content = dependency_path.read_text(encoding=CURRENT_ENCODING)
|
|
94
87
|
|
|
95
|
-
dependency_deprecated = deprecated_pattern.search(
|
|
96
|
-
dependency_content
|
|
97
|
-
)
|
|
88
|
+
dependency_deprecated = deprecated_pattern.search(dependency_content)
|
|
98
89
|
if dependency_deprecated:
|
|
99
90
|
yield LinterError(
|
|
100
|
-
f"VT depends on {dep}, which is marked "
|
|
101
|
-
"as deprecated.",
|
|
91
|
+
f"VT depends on {dep}, which is marked as deprecated.",
|
|
102
92
|
file=self.context.nasl_file,
|
|
103
93
|
plugin=self.name,
|
|
104
94
|
)
|
|
@@ -44,8 +44,7 @@ class CheckDeprecatedFunctions(FilePlugin):
|
|
|
44
44
|
deprecated_functions = {
|
|
45
45
|
'script_summary();, use script_tag(name:"summary", value:""); '
|
|
46
46
|
"instead": r"script_summary\s*\([^)]*\);",
|
|
47
|
-
"script_id();, use script_oid(); with "
|
|
48
|
-
"the full OID instead": r"script_id\s*\([0-9]+\);",
|
|
47
|
+
"script_id();, use script_oid(); with the full OID instead": r"script_id\s*\([0-9]+\);",
|
|
49
48
|
"security_note();": r"security_note\s*\([^)]*\);",
|
|
50
49
|
"security_warning();": r"security_warning\s*\([^)]*\);",
|
|
51
50
|
"security_hole();": r"security_hole\s*\([^)]*\);",
|
|
@@ -58,8 +57,7 @@ class CheckDeprecatedFunctions(FilePlugin):
|
|
|
58
57
|
for description, pattern in deprecated_functions.items():
|
|
59
58
|
if re.search(pattern, self.context.file_content, re.MULTILINE):
|
|
60
59
|
yield LinterError(
|
|
61
|
-
"Found a deprecated function call / description item: "
|
|
62
|
-
f"{description}",
|
|
60
|
+
f"Found a deprecated function call / description item: {description}",
|
|
63
61
|
file=self.context.nasl_file,
|
|
64
62
|
plugin=self.name,
|
|
65
63
|
)
|
|
@@ -42,9 +42,7 @@ class CheckDoubleEndPoints(FilePlugin):
|
|
|
42
42
|
if self.context.nasl_file.suffix == ".inc":
|
|
43
43
|
return
|
|
44
44
|
|
|
45
|
-
tag_matches = get_common_tag_patterns().finditer(
|
|
46
|
-
self.context.file_content
|
|
47
|
-
)
|
|
45
|
+
tag_matches = get_common_tag_patterns().finditer(self.context.file_content)
|
|
48
46
|
|
|
49
47
|
if tag_matches is not None:
|
|
50
48
|
for tag_match in tag_matches:
|
|
@@ -56,10 +54,7 @@ class CheckDoubleEndPoints(FilePlugin):
|
|
|
56
54
|
)
|
|
57
55
|
if doubled_end_points_match:
|
|
58
56
|
# Valid string used in a few VTs.
|
|
59
|
-
if (
|
|
60
|
-
'and much more...");'
|
|
61
|
-
in doubled_end_points_match.group(0)
|
|
62
|
-
):
|
|
57
|
+
if 'and much more...");' in doubled_end_points_match.group(0):
|
|
63
58
|
continue
|
|
64
59
|
|
|
65
60
|
yield LinterError(
|
|
@@ -50,9 +50,7 @@ class CheckDuplicateOID(FilesPlugin):
|
|
|
50
50
|
|
|
51
51
|
oid = None
|
|
52
52
|
|
|
53
|
-
match = get_special_script_tag_pattern(SpecialScriptTag.OID).search(
|
|
54
|
-
content
|
|
55
|
-
)
|
|
53
|
+
match = get_special_script_tag_pattern(SpecialScriptTag.OID).search(content)
|
|
56
54
|
|
|
57
55
|
if match:
|
|
58
56
|
oid = match.group("oid")
|
|
@@ -81,8 +81,7 @@ class CheckDuplicatedScriptTags(FilePlugin):
|
|
|
81
81
|
match = list(match)
|
|
82
82
|
if len(match) > 1:
|
|
83
83
|
yield LinterError(
|
|
84
|
-
f"The VT is using the script tag '{tag.value}' "
|
|
85
|
-
"multiple number of times.",
|
|
84
|
+
f"The VT is using the script tag '{tag.value}' multiple number of times.",
|
|
86
85
|
file=self.context.nasl_file,
|
|
87
86
|
plugin=self.name,
|
|
88
87
|
)
|
|
@@ -92,10 +92,7 @@ class CheckForkingNaslFunctions(FileContentPlugin):
|
|
|
92
92
|
return
|
|
93
93
|
|
|
94
94
|
# This one is using if/else calls similar to the examples above.
|
|
95
|
-
if (
|
|
96
|
-
"2011/zohocorp/gb_manageengine_adselfservice_plus_xss_vuln.nasl"
|
|
97
|
-
in str(nasl_file)
|
|
98
|
-
):
|
|
95
|
+
if "2011/zohocorp/gb_manageengine_adselfservice_plus_xss_vuln.nasl" in str(nasl_file):
|
|
99
96
|
return
|
|
100
97
|
|
|
101
98
|
# Another example using if/else calls
|
|
@@ -54,8 +54,7 @@ class CheckGetKBOnServices(FileContentPlugin):
|
|
|
54
54
|
return
|
|
55
55
|
|
|
56
56
|
kb_matches = re.finditer(
|
|
57
|
-
r'(get_kb_(?P<type>item|list)\s*\(\s*(?P<quote>[\'"])(?P<value>'
|
|
58
|
-
r"Services/[^)]+)\))",
|
|
57
|
+
r'(get_kb_(?P<type>item|list)\s*\(\s*(?P<quote>[\'"])(?P<value>' r"Services/[^)]+)\))",
|
|
59
58
|
file_content,
|
|
60
59
|
)
|
|
61
60
|
if kb_matches:
|
|
@@ -71,8 +70,7 @@ class CheckGetKBOnServices(FileContentPlugin):
|
|
|
71
70
|
# access "Services/unknown" directly.
|
|
72
71
|
# The same is valid for unknown_services.nasl as well.
|
|
73
72
|
if "unknown_services.nasl" in str(nasl_file) or re.search(
|
|
74
|
-
r"find_service([0-9]+|_("
|
|
75
|
-
r"3digits|spontaneous|nmap|nmap_wrapped))?\.nasl",
|
|
73
|
+
r"find_service([0-9]+|_(" r"3digits|spontaneous|nmap|nmap_wrapped))?\.nasl",
|
|
76
74
|
str(nasl_file),
|
|
77
75
|
):
|
|
78
76
|
continue
|
troubadix/plugins/grammar.py
CHANGED
|
@@ -48,12 +48,8 @@ exceptions = [
|
|
|
48
48
|
# catch this wrongly...
|
|
49
49
|
# - Cases like "this filesystem" vs. "these filesystems" are also handled /
|
|
50
50
|
# excluded here
|
|
51
|
-
PatternCheck(
|
|
52
|
-
|
|
53
|
-
),
|
|
54
|
-
PatternCheck(
|
|
55
|
-
r'these\s+(filesystem|allow\s+list)s([\s.",]+|$)', re.IGNORECASE
|
|
56
|
-
),
|
|
51
|
+
PatternCheck(r'this\s+(filesystem|allow\s+list)([\s.",]+|$)', re.IGNORECASE),
|
|
52
|
+
PatternCheck(r'these\s+(filesystem|allow\s+list)s([\s.",]+|$)', re.IGNORECASE),
|
|
57
53
|
# Like seen in e.g. 2008/freebsd/freebsd_mod_php4-twig.nasl
|
|
58
54
|
PatternCheck(r'(\s+|")[Aa]\s+multiple\s+of'),
|
|
59
55
|
# WITH can be used like e.g. the following which is valid:
|
|
@@ -61,9 +57,7 @@ exceptions = [
|
|
|
61
57
|
# see e.g. gb_sles_2021_3215_1.nasl or gb_sles_2021_2320_1.nasl
|
|
62
58
|
PatternCheck(r"with\s+WITH"),
|
|
63
59
|
# Valid sentences
|
|
64
|
-
PatternCheck(
|
|
65
|
-
r"these\s+error\s+(messages|reports|conditions)", re.IGNORECASE
|
|
66
|
-
),
|
|
60
|
+
PatternCheck(r"these\s+error\s+(messages|reports|conditions)", re.IGNORECASE),
|
|
67
61
|
PatternCheck(
|
|
68
62
|
r"these\s+file\s+(permissions|overwrites|names|includes|systems|formats)",
|
|
69
63
|
re.IGNORECASE,
|
|
@@ -71,8 +65,7 @@ exceptions = [
|
|
|
71
65
|
# nb: Valid sentence
|
|
72
66
|
TextInFileCheck(
|
|
73
67
|
"2012/gb_VMSA-2010-0007.nasl",
|
|
74
|
-
"e. VMware VMnc Codec heap overflow vulnerabilities\n\n"
|
|
75
|
-
" Vulnerabilities in the",
|
|
68
|
+
"e. VMware VMnc Codec heap overflow vulnerabilities\n\n Vulnerabilities in the",
|
|
76
69
|
),
|
|
77
70
|
TextInFileCheck("gb_opensuse_2018_1900_1.nasl", "(Note that"),
|
|
78
71
|
# e.g.:
|
|
@@ -142,11 +135,9 @@ def get_grammer_pattern() -> re.Pattern:
|
|
|
142
135
|
r"links\s+mentioned\s+in(\s+the)?\s+reference|"
|
|
143
136
|
r"\s+an?(\s+remote)?(\s+(un)?authenticated)?\s+attackers|"
|
|
144
137
|
# e.g. "this flaws"
|
|
145
|
-
r"this\s+(vulnerabilities|(flaw|error|problem|issue|feature|file|"
|
|
146
|
-
r"request)s)|"
|
|
138
|
+
r"this\s+(vulnerabilities|(flaw|error|problem|issue|feature|file|request)s)|"
|
|
147
139
|
# e.g. "these flaw "
|
|
148
|
-
r"these\s+(vulnerability|(flaw|error|problem|issue|feature|file|"
|
|
149
|
-
r"request)\s+)|"
|
|
140
|
+
r"these\s+(vulnerability|(flaw|error|problem|issue|feature|file|request)\s+)|"
|
|
150
141
|
r"\s+or\s+not\.?(\"\);)?$|"
|
|
151
142
|
r"from(\s+the)?(\s+below)?mentioned\s+References?\s+link|"
|
|
152
143
|
r"software\s+it\s+fail|"
|
|
@@ -208,7 +199,7 @@ def get_grammer_pattern() -> re.Pattern:
|
|
|
208
199
|
r"in the in the|to an? to a|prior to prior to|to version to version|"
|
|
209
200
|
r"update to update to|"
|
|
210
201
|
# e.g. "is prone to a security bypass vulnerabilities"
|
|
211
|
-
r"is\s+prone\s+to\s+an?\s+[^\s]+\s+([^\s]+\s+)?vulnerabilities
|
|
202
|
+
r"is\s+prone\s+to\s+an?\s+[^\s]+\s+([^\s]+\s+)?vulnerabilities).*",
|
|
212
203
|
re.IGNORECASE,
|
|
213
204
|
)
|
|
214
205
|
|
|
@@ -229,14 +220,11 @@ class CheckGrammar(FilePlugin):
|
|
|
229
220
|
|
|
230
221
|
for match in pattern.finditer(self.context.file_content):
|
|
231
222
|
if match:
|
|
232
|
-
|
|
233
223
|
# nb: No strip() here for so that the exclusions can be handled
|
|
234
224
|
# more strict with e.g. leading or trailing newlines.
|
|
235
225
|
full_line = match.group(0)
|
|
236
226
|
|
|
237
|
-
if handle_linguistic_checks(
|
|
238
|
-
str(self.context.nasl_file), full_line, exceptions
|
|
239
|
-
):
|
|
227
|
+
if handle_linguistic_checks(str(self.context.nasl_file), full_line, exceptions):
|
|
240
228
|
continue
|
|
241
229
|
|
|
242
230
|
stripped_line = full_line.strip()
|
|
@@ -102,9 +102,8 @@ class CheckHttpLinksInTags(FilePlugin):
|
|
|
102
102
|
if match:
|
|
103
103
|
if (
|
|
104
104
|
# fmt: off
|
|
105
|
-
"nvd.nist.gov/vuln/detail/CVE-" in match.group(
|
|
106
|
-
or "cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-"
|
|
107
|
-
in match.group('ref')
|
|
105
|
+
"nvd.nist.gov/vuln/detail/CVE-" in match.group("ref")
|
|
106
|
+
or "cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-" in match.group("ref")
|
|
108
107
|
# fmt: on
|
|
109
108
|
):
|
|
110
109
|
yield LinterError(
|
|
@@ -180,6 +179,4 @@ class CheckHttpLinksInTags(FilePlugin):
|
|
|
180
179
|
"http://target",
|
|
181
180
|
]
|
|
182
181
|
|
|
183
|
-
return any(
|
|
184
|
-
exclusion in http_link_match_group for exclusion in exclusions
|
|
185
|
-
)
|
|
182
|
+
return any(exclusion in http_link_match_group for exclusion in exclusions)
|
|
@@ -55,9 +55,7 @@ def check_forbidden(match: re.match) -> List[str]:
|
|
|
55
55
|
return [char for char in FORBIDDEN_CHARS if char in match.group("value")]
|
|
56
56
|
|
|
57
57
|
|
|
58
|
-
def fix_forbidden(
|
|
59
|
-
match: re.Match, found_forbidden_characters: List[str]
|
|
60
|
-
) -> str:
|
|
58
|
+
def fix_forbidden(match: re.Match, found_forbidden_characters: List[str]) -> str:
|
|
61
59
|
"""Returns the fixed version of the tag with
|
|
62
60
|
the forbidden characters replaced
|
|
63
61
|
|
|
@@ -100,20 +98,15 @@ class CheckIllegalCharacters(FilePlugin):
|
|
|
100
98
|
if match and match.group(0) is not None:
|
|
101
99
|
found_forbidden_characters = check_forbidden(match)
|
|
102
100
|
if found_forbidden_characters:
|
|
103
|
-
self.new_file_content = (
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
fix_forbidden(
|
|
107
|
-
match, found_forbidden_characters
|
|
108
|
-
),
|
|
109
|
-
)
|
|
101
|
+
self.new_file_content = self.context.file_content.replace(
|
|
102
|
+
match.group(0),
|
|
103
|
+
fix_forbidden(match, found_forbidden_characters),
|
|
110
104
|
)
|
|
111
105
|
|
|
112
106
|
for forbidden_char in found_forbidden_characters:
|
|
113
107
|
result, _ = FORBIDDEN_CHARS[forbidden_char]
|
|
114
108
|
yield result(
|
|
115
|
-
f"Found illegal character '{forbidden_char}' "
|
|
116
|
-
f"in {match.group(0)}",
|
|
109
|
+
f"Found illegal character '{forbidden_char}' in {match.group(0)}",
|
|
117
110
|
file=self.context.nasl_file,
|
|
118
111
|
plugin=self.name,
|
|
119
112
|
)
|
|
@@ -122,9 +115,7 @@ class CheckIllegalCharacters(FilePlugin):
|
|
|
122
115
|
if not self.new_file_content:
|
|
123
116
|
return
|
|
124
117
|
|
|
125
|
-
self.context.nasl_file.write_text(
|
|
126
|
-
self.new_file_content, encoding=CURRENT_ENCODING
|
|
127
|
-
)
|
|
118
|
+
self.context.nasl_file.write_text(self.new_file_content, encoding=CURRENT_ENCODING)
|
|
128
119
|
|
|
129
120
|
yield LinterFix(
|
|
130
121
|
"Replaced Illegal Characters.",
|
|
@@ -75,8 +75,7 @@ class CheckLogMessages(FileContentPlugin):
|
|
|
75
75
|
# log_match = re.search(r'.*(log_message[\s]*\([^)]+\)[\s]*;)',
|
|
76
76
|
# file_content, re.MULTILINE)
|
|
77
77
|
log_match = re.search(
|
|
78
|
-
r"log_message\s*\([\w:#\.&\-!,<>\[\]("
|
|
79
|
-
r")\s\"+\'/\\\n]+\)\s*(;|;\s*(\n|#))",
|
|
78
|
+
r"log_message\s*\([\w:#\.&\-!,<>\[\](" r")\s\"+\'/\\\n]+\)\s*(;|;\s*(\n|#))",
|
|
80
79
|
file_content,
|
|
81
80
|
re.MULTILINE,
|
|
82
81
|
)
|
|
@@ -23,9 +23,7 @@ from typing import Iterator
|
|
|
23
23
|
from troubadix.helper.patterns import _get_special_script_tag_pattern
|
|
24
24
|
from troubadix.plugin import FilePlugin, LinterError, LinterResult
|
|
25
25
|
|
|
26
|
-
DEPENDENCY_ENTRY_PATTERN = re.compile(
|
|
27
|
-
r'(?P<quote>[\'"])(?P<value>[^\'"]*)(?P=quote)'
|
|
28
|
-
)
|
|
26
|
+
DEPENDENCY_ENTRY_PATTERN = re.compile(r'(?P<quote>[\'"])(?P<value>[^\'"]*)(?P=quote)')
|
|
29
27
|
WHITESPACE_PATTERN = re.compile(r"\s")
|
|
30
28
|
|
|
31
29
|
|
|
@@ -55,9 +53,7 @@ class CheckMalformedDependencies(FilePlugin):
|
|
|
55
53
|
if not match:
|
|
56
54
|
continue
|
|
57
55
|
|
|
58
|
-
tag_value = (
|
|
59
|
-
f'"{match.group("value")}"' if match.group("value") else ""
|
|
60
|
-
)
|
|
56
|
+
tag_value = f'"{match.group("value")}"' if match.group("value") else ""
|
|
61
57
|
|
|
62
58
|
dependency_entries = DEPENDENCY_ENTRY_PATTERN.finditer(tag_value)
|
|
63
59
|
|
|
@@ -61,9 +61,7 @@ class CheckMissingDescExit(FileContentPlugin):
|
|
|
61
61
|
re.MULTILINE | re.DOTALL,
|
|
62
62
|
)
|
|
63
63
|
if match and match.group(1):
|
|
64
|
-
submatch = re.search(
|
|
65
|
-
r"^\s*exit\s*\(\s*0\s*\)\s*;", match.group(1), re.MULTILINE
|
|
66
|
-
)
|
|
64
|
+
submatch = re.search(r"^\s*exit\s*\(\s*0\s*\)\s*;", match.group(1), re.MULTILINE)
|
|
67
65
|
if not submatch:
|
|
68
66
|
yield LinterError(
|
|
69
67
|
"No mandatory exit(0); found in the description block.",
|
|
@@ -13,9 +13,7 @@ from troubadix.plugin import LineContentPlugin, LinterError, LinterResult
|
|
|
13
13
|
|
|
14
14
|
RE_PATTERN = re.compile(r"re\s*:")
|
|
15
15
|
|
|
16
|
-
MANDATORY_KEYS_PATTERN = get_special_script_tag_pattern(
|
|
17
|
-
SpecialScriptTag.MANDATORY_KEYS
|
|
18
|
-
)
|
|
16
|
+
MANDATORY_KEYS_PATTERN = get_special_script_tag_pattern(SpecialScriptTag.MANDATORY_KEYS)
|
|
19
17
|
|
|
20
18
|
|
|
21
19
|
class CheckMultipleReParameters(LineContentPlugin):
|
|
@@ -25,10 +23,7 @@ class CheckMultipleReParameters(LineContentPlugin):
|
|
|
25
23
|
|
|
26
24
|
name = "check_multiple_re_parameters"
|
|
27
25
|
|
|
28
|
-
def check_lines(
|
|
29
|
-
self, nasl_file: Path, lines: Iterable[str]
|
|
30
|
-
) -> Iterator[LinterResult]:
|
|
31
|
-
|
|
26
|
+
def check_lines(self, nasl_file: Path, lines: Iterable[str]) -> Iterator[LinterResult]:
|
|
32
27
|
if self.context.nasl_file.suffix == ".inc":
|
|
33
28
|
return
|
|
34
29
|
|
troubadix/plugins/newlines.py
CHANGED
|
@@ -58,8 +58,7 @@ class CheckNewlines(FilePlugin):
|
|
|
58
58
|
break
|
|
59
59
|
|
|
60
60
|
newline_match = re.search(
|
|
61
|
-
rf'(script_{tag}\((?P<quote>[\'"])[^\'"\n;]*)[\n]+\s*'
|
|
62
|
-
r'([^\'"\n;]*(?P=quote)\);)',
|
|
61
|
+
rf'(script_{tag}\((?P<quote>[\'"])[^\'"\n;]*)[\n]+\s*' r'([^\'"\n;]*(?P=quote)\);)',
|
|
63
62
|
file_content,
|
|
64
63
|
)
|
|
65
64
|
if newline_match:
|
|
@@ -56,9 +56,7 @@ class CheckOverlongDescriptionLines(FileContentPlugin):
|
|
|
56
56
|
|
|
57
57
|
name = "check_overlong_description_lines"
|
|
58
58
|
|
|
59
|
-
def check_content(
|
|
60
|
-
self, nasl_file: Path, file_content: str
|
|
61
|
-
) -> Iterator[LinterResult]:
|
|
59
|
+
def check_content(self, nasl_file: Path, file_content: str) -> Iterator[LinterResult]:
|
|
62
60
|
if nasl_file.suffix == ".inc":
|
|
63
61
|
return
|
|
64
62
|
|
|
@@ -87,9 +85,7 @@ class CheckOverlongDescriptionLines(FileContentPlugin):
|
|
|
87
85
|
continue
|
|
88
86
|
|
|
89
87
|
yield LinterWarning(
|
|
90
|
-
f"Line {i} is too long"
|
|
91
|
-
f" with {len(line)} characters. "
|
|
92
|
-
f"Max 100",
|
|
88
|
+
f"Line {i} is too long with {len(line)} characters. Max 100",
|
|
93
89
|
plugin=self.name,
|
|
94
90
|
file=nasl_file,
|
|
95
91
|
line=i,
|
|
@@ -1,19 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# SPDX-FileCopyrightText: 2022 Greenbone AG
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
|
-
#
|
|
5
|
-
# This program is free software: you can redistribute it and/or modify
|
|
6
|
-
# it under the terms of the GNU General Public License as published by
|
|
7
|
-
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
# (at your option) any later version.
|
|
9
|
-
#
|
|
10
|
-
# This program is distributed in the hope that it will be useful,
|
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
# GNU General Public License for more details.
|
|
14
|
-
#
|
|
15
|
-
# You should have received a copy of the GNU General Public License
|
|
16
|
-
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
4
|
|
|
18
5
|
from pathlib import Path
|
|
19
6
|
from typing import Iterator
|
|
@@ -27,8 +14,16 @@ from ..plugin import FileContentPlugin, LinterError, LinterResult
|
|
|
27
14
|
VALUE_LIMIT = 3000
|
|
28
15
|
|
|
29
16
|
IGNORE_FILES = [
|
|
17
|
+
# This has so many vulnerabilities, and we want at least mention each of them, so no way to
|
|
18
|
+
# shorten it down.
|
|
30
19
|
"monstra_cms_mult_vuln",
|
|
20
|
+
# Same as previously
|
|
21
|
+
"2017/gb_generic_http_web_app_params_dir_trav.nasl",
|
|
22
|
+
"2017/gb_generic_http_web_root_dir_trav.nasl",
|
|
23
|
+
"2021/gb_generic_http_web_dirs_dir_trav.nasl",
|
|
24
|
+
# These have auto-generated affected tags which we don't want to shorten down.
|
|
31
25
|
"gb_huawei-sa-",
|
|
26
|
+
# Needs a description for each option which we don't want to shorten down.
|
|
32
27
|
"lsc_options.nasl",
|
|
33
28
|
]
|
|
34
29
|
|
|
@@ -97,10 +97,7 @@ class CheckProdSvcDetectInVulnvt(FilePlugin):
|
|
|
97
97
|
)
|
|
98
98
|
if matches:
|
|
99
99
|
for match in matches:
|
|
100
|
-
if all(
|
|
101
|
-
det not in match.group("body")
|
|
102
|
-
for det in ["detected_by", "detected_at"]
|
|
103
|
-
):
|
|
100
|
+
if all(det not in match.group("body") for det in ["detected_by", "detected_at"]):
|
|
104
101
|
yield LinterError(
|
|
105
102
|
"VT has a severity but is using the function '"
|
|
106
103
|
f"{match.group('function')}' which is not allowed for "
|
troubadix/plugins/qod.py
CHANGED
|
@@ -26,20 +26,13 @@ def iter_script_add_preference_values(
|
|
|
26
26
|
class CheckScriptAddPreferenceId(FileContentPlugin):
|
|
27
27
|
name = "check_script_add_preference_id"
|
|
28
28
|
|
|
29
|
-
def check_content(
|
|
30
|
-
|
|
31
|
-
) -> Iterator[LinterResult]:
|
|
32
|
-
if (
|
|
33
|
-
nasl_file.suffix == ".inc"
|
|
34
|
-
or "script_add_preference" not in file_content
|
|
35
|
-
):
|
|
29
|
+
def check_content(self, nasl_file: Path, file_content: str) -> Iterator[LinterResult]:
|
|
30
|
+
if nasl_file.suffix == ".inc" or "script_add_preference" not in file_content:
|
|
36
31
|
return
|
|
37
32
|
|
|
38
33
|
seen_ids: set[int] = set()
|
|
39
34
|
|
|
40
|
-
for index, value in enumerate(
|
|
41
|
-
iter_script_add_preference_values(file_content), 1
|
|
42
|
-
):
|
|
35
|
+
for index, value in enumerate(iter_script_add_preference_values(file_content), 1):
|
|
43
36
|
id_match = ID_PATTERN.search(value)
|
|
44
37
|
pref_id = int(id_match.group("id")) if id_match else index
|
|
45
38
|
|
|
@@ -28,9 +28,7 @@ from troubadix.helper.patterns import (
|
|
|
28
28
|
)
|
|
29
29
|
from troubadix.plugin import FileContentPlugin, LinterError, LinterResult
|
|
30
30
|
|
|
31
|
-
TYPE_PATTERN = re.compile(
|
|
32
|
-
r'type\s*:\s*(?P<quote>[\'"])(?P<type>[^\'"]+)(?P=quote)'
|
|
33
|
-
)
|
|
31
|
+
TYPE_PATTERN = re.compile(r'type\s*:\s*(?P<quote>[\'"])(?P<type>[^\'"]+)(?P=quote)')
|
|
34
32
|
|
|
35
33
|
|
|
36
34
|
class ValidType(Enum):
|
|
@@ -99,10 +97,7 @@ class CheckScriptAddPreferenceType(FileContentPlugin):
|
|
|
99
97
|
# nb: This exists since years and it is currently
|
|
100
98
|
# unclear if we can change it so
|
|
101
99
|
# we're excluding it here for now.
|
|
102
|
-
if
|
|
103
|
-
"ssh_authorization_init.nasl" in nasl_file.name
|
|
104
|
-
and pref_type == "sshlogin"
|
|
105
|
-
):
|
|
100
|
+
if "ssh_authorization_init.nasl" in nasl_file.name and pref_type == "sshlogin":
|
|
106
101
|
continue
|
|
107
102
|
|
|
108
103
|
yield LinterError(
|
|
@@ -64,9 +64,9 @@ class CheckScriptCallsEmptyValues(FileContentPlugin):
|
|
|
64
64
|
)
|
|
65
65
|
|
|
66
66
|
for call in SPECIAL_SCRIPT_TAG_LIST:
|
|
67
|
-
matches = _get_special_script_tag_pattern(
|
|
68
|
-
|
|
69
|
-
)
|
|
67
|
+
matches = _get_special_script_tag_pattern(name=call.value, value="").finditer(
|
|
68
|
+
file_content
|
|
69
|
+
)
|
|
70
70
|
for match in matches:
|
|
71
71
|
yield LinterError(
|
|
72
72
|
f"{match.group(0)} does not contain a value",
|
|
@@ -57,9 +57,7 @@ class CheckScriptCallsRecommended(FileContentPlugin):
|
|
|
57
57
|
|
|
58
58
|
if _get_special_script_tag_pattern(
|
|
59
59
|
name=r"category", value=r"ACT_(SETTINGS|SCANNER|INIT)"
|
|
60
|
-
).search(file_content) or _get_tag_pattern(
|
|
61
|
-
name=r"deprecated", value=r"TRUE"
|
|
62
|
-
).search(
|
|
60
|
+
).search(file_content) or _get_tag_pattern(name=r"deprecated", value=r"TRUE").search(
|
|
63
61
|
file_content
|
|
64
62
|
):
|
|
65
63
|
return
|
|
@@ -84,12 +82,11 @@ class CheckScriptCallsRecommended(FileContentPlugin):
|
|
|
84
82
|
plugin=self.name,
|
|
85
83
|
)
|
|
86
84
|
for call in recommended_single_call:
|
|
87
|
-
if not _get_special_script_tag_pattern(
|
|
88
|
-
|
|
89
|
-
)
|
|
85
|
+
if not _get_special_script_tag_pattern(name=call, value=".*", flags=re.DOTALL).search(
|
|
86
|
+
file_content
|
|
87
|
+
):
|
|
90
88
|
yield LinterWarning(
|
|
91
|
-
"VT does not contain the following recommended call: "
|
|
92
|
-
f"'script_{call}'",
|
|
89
|
+
f"VT does not contain the following recommended call: 'script_{call}'",
|
|
93
90
|
file=nasl_file,
|
|
94
91
|
plugin=self.name,
|
|
95
92
|
)
|
|
@@ -50,9 +50,7 @@ class CheckScriptCopyright(FileContentPlugin):
|
|
|
50
50
|
):
|
|
51
51
|
return
|
|
52
52
|
|
|
53
|
-
if not re.search(
|
|
54
|
-
r'script_copyright\("Copyright \(C\) [0-9]{4}', file_content
|
|
55
|
-
):
|
|
53
|
+
if not re.search(r'script_copyright\("Copyright \(C\) [0-9]{4}', file_content):
|
|
56
54
|
yield LinterError(
|
|
57
55
|
"The VT is using an incorrect syntax for its "
|
|
58
56
|
"copyright statement. Please start (EXACTLY) with: "
|
|
@@ -130,8 +130,7 @@ class CheckScriptFamily(FileContentPlugin):
|
|
|
130
130
|
|
|
131
131
|
if matches[0].group("value") not in VALID_FAMILIES:
|
|
132
132
|
yield LinterError(
|
|
133
|
-
"Invalid or misspelled script family "
|
|
134
|
-
f"'{matches[0].group('value')}'",
|
|
133
|
+
f"Invalid or misspelled script family '{matches[0].group('value')}'",
|
|
135
134
|
file=nasl_file,
|
|
136
135
|
plugin=self.name,
|
|
137
136
|
)
|
|
@@ -40,9 +40,7 @@ class CheckScriptTagForm(FileContentPlugin):
|
|
|
40
40
|
matches = re.finditer(r"script_tag\(.*\);", file_content)
|
|
41
41
|
for match in matches:
|
|
42
42
|
if match:
|
|
43
|
-
if not _get_tag_pattern(name=r".*", value=r".*").match(
|
|
44
|
-
match.group(0)
|
|
45
|
-
):
|
|
43
|
+
if not _get_tag_pattern(name=r".*", value=r".*").match(match.group(0)):
|
|
46
44
|
yield LinterError(
|
|
47
45
|
f"{match.group(0)}: does not conform to"
|
|
48
46
|
' script_tag(name:"<name>", value:<value>);',
|
|
@@ -44,18 +44,14 @@ class CheckScriptTagWhitespaces(FileContentPlugin):
|
|
|
44
44
|
if nasl_file.suffix == ".inc":
|
|
45
45
|
return
|
|
46
46
|
|
|
47
|
-
tag_matches = _get_tag_pattern(name=r".+?", flags=re.S).finditer(
|
|
48
|
-
file_content
|
|
49
|
-
)
|
|
47
|
+
tag_matches = _get_tag_pattern(name=r".+?", flags=re.S).finditer(file_content)
|
|
50
48
|
|
|
51
|
-
name_matches = _get_special_script_tag_pattern(
|
|
52
|
-
name=SpecialScriptTag.NAME.value
|
|
53
|
-
).finditer(file_content)
|
|
54
|
-
|
|
55
|
-
xref_matches = get_xref_pattern(name=r".+?", flags=re.S).finditer(
|
|
49
|
+
name_matches = _get_special_script_tag_pattern(name=SpecialScriptTag.NAME.value).finditer(
|
|
56
50
|
file_content
|
|
57
51
|
)
|
|
58
52
|
|
|
53
|
+
xref_matches = get_xref_pattern(name=r".+?", flags=re.S).finditer(file_content)
|
|
54
|
+
|
|
59
55
|
matches = chain(tag_matches, name_matches, xref_matches)
|
|
60
56
|
|
|
61
57
|
for match in matches:
|
|
@@ -63,8 +59,7 @@ class CheckScriptTagWhitespaces(FileContentPlugin):
|
|
|
63
59
|
r".*\s+$", match.group("value"), flags=re.S
|
|
64
60
|
):
|
|
65
61
|
yield LinterError(
|
|
66
|
-
f"{match.group(0)}: value contains a leading or"
|
|
67
|
-
" trailing whitespace character",
|
|
62
|
+
f"{match.group(0)}: value contains a leading or trailing whitespace character",
|
|
68
63
|
file=nasl_file,
|
|
69
64
|
plugin=self.name,
|
|
70
65
|
)
|
|
@@ -69,16 +69,13 @@ class CheckScriptTagsMandatory(FileContentPlugin):
|
|
|
69
69
|
for tag in MANDATORY_TAGS:
|
|
70
70
|
if not get_script_tag_pattern(tag).search(file_content):
|
|
71
71
|
yield LinterError(
|
|
72
|
-
"VT does not contain the following mandatory tag: "
|
|
73
|
-
f"'script_{tag.value}'",
|
|
72
|
+
f"VT does not contain the following mandatory tag: 'script_{tag.value}'",
|
|
74
73
|
file=nasl_file,
|
|
75
74
|
plugin=self.name,
|
|
76
75
|
)
|
|
77
76
|
|
|
78
77
|
for special_tag in MANDATORY_SPECIAL_TAGS:
|
|
79
|
-
if not get_special_script_tag_pattern(special_tag).search(
|
|
80
|
-
file_content
|
|
81
|
-
):
|
|
78
|
+
if not get_special_script_tag_pattern(special_tag).search(file_content):
|
|
82
79
|
yield LinterError(
|
|
83
80
|
"VT does not contain the following mandatory tag: "
|
|
84
81
|
f"'script_{special_tag.value}'",
|