troubadix 25.12.4__py3-none-any.whl → 26.1.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 -7
- 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 +1 -2
- troubadix/plugins/double_end_points.py +2 -7
- troubadix/plugins/duplicate_oid.py +1 -3
- troubadix/plugins/forking_nasl_functions.py +1 -4
- troubadix/plugins/get_kb_on_services.py +2 -4
- troubadix/plugins/grammar.py +6 -16
- troubadix/plugins/http_links_in_tags.py +1 -3
- troubadix/plugins/illegal_characters.py +5 -13
- 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 -6
- troubadix/plugins/newlines.py +1 -2
- troubadix/plugins/overlong_description_lines.py +2 -6
- troubadix/plugins/prod_svc_detect_in_vulnvt.py +1 -4
- 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 +4 -8
- 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 +6 -17
- troubadix/plugins/severity_date.py +3 -9
- troubadix/plugins/severity_format.py +1 -3
- troubadix/plugins/severity_origin.py +1 -3
- troubadix/plugins/solution_text.py +6 -10
- troubadix/plugins/solution_type.py +1 -2
- troubadix/plugins/spaces_before_dots.py +2 -8
- 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 +6 -19
- 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 +3 -9
- troubadix/standalone_plugins/changed_cves.py +4 -12
- troubadix/standalone_plugins/changed_oid.py +2 -6
- 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 +2 -5
- 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 -32
- troubadix/standalone_plugins/version_updated.py +4 -12
- troubadix/troubadix.py +1 -4
- {troubadix-25.12.4.dist-info → troubadix-26.1.0.dist-info}/METADATA +1 -1
- troubadix-26.1.0.dist-info/RECORD +116 -0
- troubadix-25.12.4.dist-info/RECORD +0 -116
- {troubadix-25.12.4.dist-info → troubadix-26.1.0.dist-info}/WHEEL +0 -0
- {troubadix-25.12.4.dist-info → troubadix-26.1.0.dist-info}/entry_points.txt +0 -0
- {troubadix-25.12.4.dist-info → troubadix-26.1.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
|
)
|
|
@@ -58,8 +58,7 @@ class CheckDeprecatedFunctions(FilePlugin):
|
|
|
58
58
|
for description, pattern in deprecated_functions.items():
|
|
59
59
|
if re.search(pattern, self.context.file_content, re.MULTILINE):
|
|
60
60
|
yield LinterError(
|
|
61
|
-
"Found a deprecated function call / description item: "
|
|
62
|
-
f"{description}",
|
|
61
|
+
"Found a deprecated function call / description item: " f"{description}",
|
|
63
62
|
file=self.context.nasl_file,
|
|
64
63
|
plugin=self.name,
|
|
65
64
|
)
|
|
@@ -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")
|
|
@@ -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,8 +135,7 @@ 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|" r"request)s)|"
|
|
147
139
|
# e.g. "these flaw "
|
|
148
140
|
r"these\s+(vulnerability|(flaw|error|problem|issue|feature|file|"
|
|
149
141
|
r"request)\s+)|"
|
|
@@ -234,9 +226,7 @@ class CheckGrammar(FilePlugin):
|
|
|
234
226
|
# more strict with e.g. leading or trailing newlines.
|
|
235
227
|
full_line = match.group(0)
|
|
236
228
|
|
|
237
|
-
if handle_linguistic_checks(
|
|
238
|
-
str(self.context.nasl_file), full_line, exceptions
|
|
239
|
-
):
|
|
229
|
+
if handle_linguistic_checks(str(self.context.nasl_file), full_line, exceptions):
|
|
240
230
|
continue
|
|
241
231
|
|
|
242
232
|
stripped_line = full_line.strip()
|
|
@@ -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,13 +98,9 @@ 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:
|
|
@@ -122,9 +116,7 @@ class CheckIllegalCharacters(FilePlugin):
|
|
|
122
116
|
if not self.new_file_content:
|
|
123
117
|
return
|
|
124
118
|
|
|
125
|
-
self.context.nasl_file.write_text(
|
|
126
|
-
self.new_file_content, encoding=CURRENT_ENCODING
|
|
127
|
-
)
|
|
119
|
+
self.context.nasl_file.write_text(self.new_file_content, encoding=CURRENT_ENCODING)
|
|
128
120
|
|
|
129
121
|
yield LinterFix(
|
|
130
122
|
"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,9 +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]:
|
|
26
|
+
def check_lines(self, nasl_file: Path, lines: Iterable[str]) -> Iterator[LinterResult]:
|
|
31
27
|
|
|
32
28
|
if self.context.nasl_file.suffix == ".inc":
|
|
33
29
|
return
|
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" f" with {len(line)} characters. " f"Max 100",
|
|
93
89
|
plugin=self.name,
|
|
94
90
|
file=nasl_file,
|
|
95
91
|
line=i,
|
|
@@ -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 "
|
|
@@ -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
|
+
"VT does not contain the following recommended call: " f"'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
|
+
"Invalid or misspelled script family " f"'{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:
|
|
@@ -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
|
+
"VT does not contain the following mandatory tag: " f"'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}'",
|
|
@@ -84,9 +84,7 @@ class CheckScriptVersionAndLastModificationTags(FileContentPlugin):
|
|
|
84
84
|
self.old_script_version_value = match_script_version_any.group("value")
|
|
85
85
|
|
|
86
86
|
# script_version("2019-03-21T12:19:01+0000");")
|
|
87
|
-
version_pattern = get_special_script_tag_pattern(
|
|
88
|
-
SpecialScriptTag.VERSION
|
|
89
|
-
)
|
|
87
|
+
version_pattern = get_special_script_tag_pattern(SpecialScriptTag.VERSION)
|
|
90
88
|
version_match = version_pattern.search(file_content)
|
|
91
89
|
|
|
92
90
|
if not version_match:
|
|
@@ -122,22 +120,17 @@ class CheckScriptVersionAndLastModificationTags(FileContentPlugin):
|
|
|
122
120
|
return
|
|
123
121
|
|
|
124
122
|
self.old_last_modification = match_last_modification_any_value.group(0)
|
|
125
|
-
self.old_last_modification_value = (
|
|
126
|
-
match_last_modification_any_value.group("value")
|
|
127
|
-
)
|
|
123
|
+
self.old_last_modification_value = match_last_modification_any_value.group("value")
|
|
128
124
|
|
|
129
125
|
# script_tag(name:"last_modification",
|
|
130
126
|
# value:"2019-03-21 12:19:01 +0000 (Thu, 21 Mar 2019)");
|
|
131
|
-
last_modification_pattern = get_script_tag_pattern(
|
|
132
|
-
ScriptTag.LAST_MODIFICATION
|
|
133
|
-
)
|
|
127
|
+
last_modification_pattern = get_script_tag_pattern(ScriptTag.LAST_MODIFICATION)
|
|
134
128
|
match_last_modified = last_modification_pattern.search(file_content)
|
|
135
129
|
|
|
136
130
|
if not match_last_modified:
|
|
137
131
|
self.fix_last_modification_and_version = True
|
|
138
132
|
yield LinterError(
|
|
139
|
-
"VT is is using a wrong syntax for script_tag("
|
|
140
|
-
'name:"last_modification".',
|
|
133
|
+
"VT is is using a wrong syntax for script_tag(" 'name:"last_modification".',
|
|
141
134
|
file=nasl_file,
|
|
142
135
|
plugin=self.name,
|
|
143
136
|
)
|
|
@@ -198,18 +191,14 @@ class CheckScriptVersionAndLastModificationTags(FileContentPlugin):
|
|
|
198
191
|
|
|
199
192
|
# get that last modification date formatted correctly:
|
|
200
193
|
# "2021-03-24 10:08:26 +0000 (Wed, 24 Mar 2021)"
|
|
201
|
-
correctly_formatted_last_modification = (
|
|
202
|
-
f"{now:%Y-%m-%d %H:%M:%S %z (%a, %d %b %Y)}"
|
|
203
|
-
)
|
|
194
|
+
correctly_formatted_last_modification = f"{now:%Y-%m-%d %H:%M:%S %z (%a, %d %b %Y)}"
|
|
204
195
|
|
|
205
196
|
file_content = file_content.replace(
|
|
206
197
|
self.old_last_modification,
|
|
207
198
|
tag_template.format(date=correctly_formatted_last_modification),
|
|
208
199
|
)
|
|
209
200
|
|
|
210
|
-
self.context.nasl_file.write_text(
|
|
211
|
-
file_content, encoding=CURRENT_ENCODING
|
|
212
|
-
)
|
|
201
|
+
self.context.nasl_file.write_text(file_content, encoding=CURRENT_ENCODING)
|
|
213
202
|
|
|
214
203
|
yield LinterFix(
|
|
215
204
|
f"Replaced last_modification {self.old_last_modification_value} "
|
|
@@ -41,9 +41,7 @@ class CheckScriptXrefForm(FileContentPlugin):
|
|
|
41
41
|
if matches:
|
|
42
42
|
for match in matches:
|
|
43
43
|
if match:
|
|
44
|
-
if not get_xref_pattern(name=r".*", value=r".*").match(
|
|
45
|
-
match.group(0)
|
|
46
|
-
):
|
|
44
|
+
if not get_xref_pattern(name=r".*", value=r".*").match(match.group(0)):
|
|
47
45
|
yield LinterError(
|
|
48
46
|
f"{match.group(0)}: does not conform to"
|
|
49
47
|
' script_xref(name:"<name>", value:<value>);',
|
|
@@ -30,10 +30,8 @@ ALLOWED_URLS = [
|
|
|
30
30
|
+ "fbd2dac042934e49288b476d5f6a649e5da2@<announce.tomcat.apache.org>",
|
|
31
31
|
"https://m0ze.ru/vulnerability/[2021-05-26]-[WordPress]-[C"
|
|
32
32
|
+ "WE-79]-WP-Reset-WordPress-Plugin-v1.86.txt",
|
|
33
|
-
"http://yehg.net/lab/pr0js/advisories/joomla/core/[joomla_"
|
|
34
|
-
+ "
|
|
35
|
-
"http://yehg.net/lab/pr0js/advisories/eclipse/[eclipse_hel"
|
|
36
|
-
+ "p_server]_cross_site_scripting",
|
|
33
|
+
"http://yehg.net/lab/pr0js/advisories/joomla/core/[joomla_" + "1.0.x~15]_cross_site_scripting",
|
|
34
|
+
"http://yehg.net/lab/pr0js/advisories/eclipse/[eclipse_hel" + "p_server]_cross_site_scripting",
|
|
37
35
|
"http://core.yehg.net/lab/pr0js/advisories/dll_hijacking/["
|
|
38
36
|
+ "flash_player]_10.1.x_insecure_dll_hijacking_(dwmapi.dll)",
|
|
39
37
|
"https://lists.apache.org/thread.html/773c93c2d8a6a52bbe9"
|
|
@@ -62,9 +60,7 @@ class CheckScriptXrefUrl(FileContentPlugin):
|
|
|
62
60
|
if nasl_file.suffix == ".inc":
|
|
63
61
|
return
|
|
64
62
|
|
|
65
|
-
matches = get_xref_pattern(name="URL", value=r".+?").finditer(
|
|
66
|
-
file_content
|
|
67
|
-
)
|
|
63
|
+
matches = get_xref_pattern(name="URL", value=r".+?").finditer(file_content)
|
|
68
64
|
for match in matches:
|
|
69
65
|
if match:
|
|
70
66
|
url_value = match.group("value")
|