troubadix 25.3.4__py3-none-any.whl → 25.4.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/codespell/codespell.additions +2 -0
- troubadix/codespell/codespell.exclude +2 -0
- troubadix/plugins/grammar.py +5 -0
- troubadix/standalone_plugins/dependency_graph/checks.py +20 -23
- troubadix/standalone_plugins/dependency_graph/cli.py +7 -14
- troubadix/standalone_plugins/dependency_graph/dependency_graph.py +13 -37
- troubadix/standalone_plugins/dependency_graph/models.py +15 -9
- {troubadix-25.3.4.dist-info → troubadix-25.4.0.dist-info}/METADATA +1 -1
- {troubadix-25.3.4.dist-info → troubadix-25.4.0.dist-info}/RECORD +13 -13
- {troubadix-25.3.4.dist-info → troubadix-25.4.0.dist-info}/WHEEL +1 -1
- {troubadix-25.3.4.dist-info → troubadix-25.4.0.dist-info}/LICENSE +0 -0
- {troubadix-25.3.4.dist-info → troubadix-25.4.0.dist-info}/entry_points.txt +0 -0
troubadix/__version__.py
CHANGED
|
@@ -815,6 +815,8 @@ ofproto/bond: fix interal flow leak of tcp-balance bond
|
|
|
815
815
|
of user-supplied input processed by Steam In-Home Streaming (IHS) Discovery
|
|
816
816
|
of Wiesemann & Theis GmbH W&T OPC Server for Windows.");
|
|
817
817
|
Ohter bug fixes:
|
|
818
|
+
"olt",
|
|
819
|
+
"olt/pages",
|
|
818
820
|
# on e.g. newer releases of the NAM appliance we're even getting an 403/forbidden
|
|
819
821
|
opc_req_header = raw_string("HEL", # Message Type (Hello)
|
|
820
822
|
opening a specially crafted CAF audio file, an attacker could execute
|
troubadix/plugins/grammar.py
CHANGED
|
@@ -174,6 +174,11 @@ def get_grammer_pattern() -> re.Pattern:
|
|
|
174
174
|
# server-site template injection -> server-side template injection
|
|
175
175
|
r"cross[\s-]+side[\s-]+(request[\s-]+forgery|scripting)|"
|
|
176
176
|
r"server[\s-]+site[\s-]+(request[\s-]+forgery|template)[\s-]+injection|"
|
|
177
|
+
# nb: Next two could happen when copy'n'paste some text parts around
|
|
178
|
+
# like e.g.:
|
|
179
|
+
# is prone to a to a remote denial-of-service vulnerability
|
|
180
|
+
# CVE-2022-31702: Command injection in the in the vRNI REST API
|
|
181
|
+
r"in the in the|to an? to a|"
|
|
177
182
|
# e.g. "is prone to a security bypass vulnerabilities"
|
|
178
183
|
r"is\s+prone\s+to\s+an?\s+[^\s]+\s+([^\s]+\s+)?vulnerabilities" r").*",
|
|
179
184
|
re.IGNORECASE,
|
|
@@ -17,12 +17,10 @@ def check_duplicates(scripts: list[Script]) -> Result:
|
|
|
17
17
|
for script in scripts:
|
|
18
18
|
counter = Counter(dep.name for dep in script.dependencies)
|
|
19
19
|
duplicates = [dep for dep, count in counter.items() if count > 1]
|
|
20
|
-
|
|
21
20
|
if duplicates:
|
|
22
|
-
|
|
23
|
-
warnings.append(msg)
|
|
21
|
+
warnings.append(f"in {script.name}: {', '.join(duplicates)}")
|
|
24
22
|
|
|
25
|
-
return Result(name="
|
|
23
|
+
return Result(name="duplicate dependency", warnings=warnings)
|
|
26
24
|
|
|
27
25
|
|
|
28
26
|
def check_missing_dependencies(
|
|
@@ -34,20 +32,22 @@ def check_missing_dependencies(
|
|
|
34
32
|
logs the scripts dependending on the missing script
|
|
35
33
|
"""
|
|
36
34
|
errors = []
|
|
37
|
-
|
|
35
|
+
dependency_names = {
|
|
38
36
|
dep.name for script in scripts for dep in script.dependencies
|
|
39
37
|
}
|
|
40
38
|
script_names = {script.name for script in scripts}
|
|
41
|
-
missing_dependencies =
|
|
39
|
+
missing_dependencies = dependency_names - script_names
|
|
42
40
|
|
|
43
41
|
for missing in missing_dependencies:
|
|
44
42
|
depending_scripts = graph.predecessors(missing)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
errors.append(
|
|
44
|
+
f"{missing}:"
|
|
45
|
+
+ "".join(
|
|
46
|
+
f"\n - used by: {script}" for script in depending_scripts
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
49
|
|
|
50
|
-
return Result(name="
|
|
50
|
+
return Result(name="missing dependency", errors=errors)
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
def check_cycles(graph) -> Result:
|
|
@@ -59,8 +59,8 @@ def check_cycles(graph) -> Result:
|
|
|
59
59
|
|
|
60
60
|
cycles = nx.simple_cycles(graph)
|
|
61
61
|
|
|
62
|
-
errors = [
|
|
63
|
-
return Result(name="
|
|
62
|
+
errors = [str(cycle) for cycle in cycles]
|
|
63
|
+
return Result(name="cyclic dependency", errors=errors)
|
|
64
64
|
|
|
65
65
|
|
|
66
66
|
def cross_feed_dependencies(
|
|
@@ -86,22 +86,19 @@ def check_cross_feed_dependencies(graph) -> Result:
|
|
|
86
86
|
and if they are correctly contained within a is_enterprise_feed check.
|
|
87
87
|
"""
|
|
88
88
|
gated_cfd = cross_feed_dependencies(graph, is_enterprise_checked=True)
|
|
89
|
-
|
|
90
|
-
f"
|
|
91
|
-
f"depends on {dependency}(enterprise feed)"
|
|
89
|
+
infos = [
|
|
90
|
+
f"{dependent}(community feed) depends on {dependency}(enterprise feed)"
|
|
92
91
|
for dependent, dependency in gated_cfd
|
|
93
92
|
]
|
|
94
93
|
|
|
95
94
|
ungated_cfd = cross_feed_dependencies(graph, is_enterprise_checked=False)
|
|
96
95
|
errors = [
|
|
97
|
-
f"
|
|
98
|
-
f"depends on {dependency}(enterprise feed)
|
|
96
|
+
f"incorrect feed check in {dependent}(community feed) "
|
|
97
|
+
f"which depends on {dependency}(enterprise feed)"
|
|
99
98
|
for dependent, dependency in ungated_cfd
|
|
100
99
|
]
|
|
101
100
|
|
|
102
|
-
return Result(
|
|
103
|
-
name="check_cross_feed_dependencies", warnings=warnings, errors=errors
|
|
104
|
-
)
|
|
101
|
+
return Result(name="cross-feed dependency", infos=infos, errors=errors)
|
|
105
102
|
|
|
106
103
|
|
|
107
104
|
def check_category_order(graph) -> Result:
|
|
@@ -116,7 +113,7 @@ def check_category_order(graph) -> Result:
|
|
|
116
113
|
f"{dependent} depends on {dependency} which has a lower category order"
|
|
117
114
|
for dependent, dependency in problematic_edges
|
|
118
115
|
]
|
|
119
|
-
return Result(name="
|
|
116
|
+
return Result(name="category order", errors=errors)
|
|
120
117
|
|
|
121
118
|
|
|
122
119
|
def check_deprecated_dependencies(graph) -> Result:
|
|
@@ -125,4 +122,4 @@ def check_deprecated_dependencies(graph) -> Result:
|
|
|
125
122
|
for dependent, dependency in graph.edges()
|
|
126
123
|
if graph.nodes[dependency].get("deprecated", False)
|
|
127
124
|
]
|
|
128
|
-
return Result(name="
|
|
125
|
+
return Result(name="deprecated dependency", errors=errors)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
|
-
from argparse import ArgumentParser,
|
|
6
|
+
from argparse import ArgumentParser, Namespace
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
|
|
9
9
|
from troubadix.argparser import directory_type_existing
|
|
@@ -11,13 +11,6 @@ from troubadix.argparser import directory_type_existing
|
|
|
11
11
|
from .models import Feed
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
def feed_type(value: str) -> Feed:
|
|
15
|
-
try:
|
|
16
|
-
return Feed[value.upper()]
|
|
17
|
-
except KeyError:
|
|
18
|
-
raise ArgumentTypeError(f"Invalid Feed value: '{value}'")
|
|
19
|
-
|
|
20
|
-
|
|
21
14
|
def parse_args() -> Namespace:
|
|
22
15
|
parser = ArgumentParser(
|
|
23
16
|
description="Tool for analysing the dependencies in the NASL repository.",
|
|
@@ -31,18 +24,18 @@ def parse_args() -> Namespace:
|
|
|
31
24
|
parser.add_argument(
|
|
32
25
|
"-f",
|
|
33
26
|
"--feed",
|
|
34
|
-
type=
|
|
27
|
+
type=Feed,
|
|
35
28
|
choices=Feed,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
help="feed",
|
|
29
|
+
default=Feed.COMMON,
|
|
30
|
+
help="Feed selection",
|
|
39
31
|
)
|
|
40
32
|
parser.add_argument(
|
|
41
33
|
"--log",
|
|
34
|
+
type=str.upper,
|
|
42
35
|
default="WARNING",
|
|
43
|
-
|
|
36
|
+
choices=["INFO", "WARNING", "ERROR"],
|
|
37
|
+
help="Set the logging level (default: WARNING)",
|
|
44
38
|
)
|
|
45
|
-
parser.add_argument("-v", "--verbose", action="count", default=0)
|
|
46
39
|
|
|
47
40
|
args = parser.parse_args()
|
|
48
41
|
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
import logging
|
|
6
6
|
import re
|
|
7
7
|
import sys
|
|
8
|
-
from functools import reduce
|
|
9
8
|
from pathlib import Path
|
|
10
9
|
|
|
11
10
|
import networkx as nx
|
|
@@ -47,46 +46,23 @@ ENTERPRISE_FEED_CHECK_PATTERN = re.compile(
|
|
|
47
46
|
|
|
48
47
|
|
|
49
48
|
class Reporter:
|
|
50
|
-
def __init__(self
|
|
51
|
-
self.
|
|
49
|
+
def __init__(self) -> None:
|
|
50
|
+
self.logger = logging.getLogger(__name__)
|
|
52
51
|
|
|
53
52
|
def report(self, results: list[Result]):
|
|
54
53
|
for result in results:
|
|
55
|
-
|
|
56
|
-
self.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if self.verbosity >= 2:
|
|
62
|
-
self.print_divider("=")
|
|
63
|
-
|
|
64
|
-
def print_divider(self, char="-", length=40):
|
|
65
|
-
print(char * length)
|
|
66
|
-
|
|
67
|
-
def print_statistic(self, result: Result):
|
|
68
|
-
print(
|
|
69
|
-
f"{result.name} - warnings: {len(result.warnings)}, errors: {len(result.errors)}"
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
def print_warnings(self, result: Result):
|
|
73
|
-
for warning in result.warnings:
|
|
74
|
-
print(f"warning: {warning}")
|
|
54
|
+
for error in result.errors:
|
|
55
|
+
self.logger.error(f"{result.name}: {error}")
|
|
56
|
+
for warning in result.warnings:
|
|
57
|
+
self.logger.warning(f"{result.name}: {warning}")
|
|
58
|
+
for info in result.infos:
|
|
59
|
+
self.logger.info(f"{result.name}: {info}")
|
|
75
60
|
|
|
76
|
-
def print_errors(self, result: Result):
|
|
77
|
-
for error in result.errors:
|
|
78
|
-
print(f"error: {error}")
|
|
79
61
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
feed
|
|
83
|
-
|
|
84
|
-
if feed & Feed.COMMON:
|
|
85
|
-
scripts.extend(get_scripts(root / "common"))
|
|
86
|
-
if feed & Feed.FEED_21_04:
|
|
87
|
-
scripts.extend(get_scripts(root / "21.04"))
|
|
88
|
-
if feed & Feed.FEED_22_04:
|
|
89
|
-
scripts.extend(get_scripts(root / "22.04"))
|
|
62
|
+
def get_feed(root: Path, feed: Feed) -> list[Script]:
|
|
63
|
+
scripts = get_scripts(root / "common") # Always include common
|
|
64
|
+
if feed != Feed.COMMON: # Add version-specific scripts if not just common
|
|
65
|
+
scripts.extend(get_scripts(root / feed.value))
|
|
90
66
|
|
|
91
67
|
return scripts
|
|
92
68
|
|
|
@@ -197,7 +173,7 @@ def main():
|
|
|
197
173
|
check_category_order(graph),
|
|
198
174
|
check_deprecated_dependencies(graph),
|
|
199
175
|
]
|
|
200
|
-
reporter = Reporter(
|
|
176
|
+
reporter = Reporter()
|
|
201
177
|
reporter.report(results)
|
|
202
178
|
|
|
203
179
|
if any(result.errors for result in results):
|
|
@@ -2,18 +2,19 @@
|
|
|
2
2
|
# SPDX-FileCopyrightText: 2025 Greenbone AG
|
|
3
3
|
|
|
4
4
|
from dataclasses import dataclass, field
|
|
5
|
-
from enum import
|
|
5
|
+
from enum import Enum
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class Feed(
|
|
9
|
-
COMMON =
|
|
10
|
-
FEED_21_04 =
|
|
11
|
-
FEED_22_04 =
|
|
12
|
-
FULL = COMMON | FEED_21_04 | FEED_22_04
|
|
8
|
+
class Feed(str, Enum):
|
|
9
|
+
COMMON = "common"
|
|
10
|
+
FEED_21_04 = "21.04"
|
|
11
|
+
FEED_22_04 = "22.04"
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
|
|
14
|
+
class OutputLevel(Enum):
|
|
15
|
+
ERROR = 1
|
|
16
|
+
WARNING = 2
|
|
17
|
+
INFO = 3
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
@dataclass
|
|
@@ -35,6 +36,11 @@ class Script:
|
|
|
35
36
|
|
|
36
37
|
@dataclass
|
|
37
38
|
class Result:
|
|
39
|
+
"""Holds the results of a single check.
|
|
40
|
+
A check can report a combination of errors, warnings and infos
|
|
41
|
+
"""
|
|
42
|
+
|
|
38
43
|
name: str
|
|
39
44
|
warnings: list[str] = field(default_factory=list)
|
|
40
45
|
errors: list[str] = field(default_factory=list)
|
|
46
|
+
infos: list[str] = field(default_factory=list)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
troubadix/__init__.py,sha256=K7sIXXDrC7YRb7BvIpdQ6ZfG_QkT0qUH_wAlHROVRfM,716
|
|
2
|
-
troubadix/__version__.py,sha256=
|
|
2
|
+
troubadix/__version__.py,sha256=tBwIKM3lj8Q-OeDPH_A20MFR1-rIB7BcVcpYNmTniHU,103
|
|
3
3
|
troubadix/argparser.py,sha256=-H07Jhqh68_M4Mbjq9qJjTr3MShy_N2pxl2qHA6cfRU,7481
|
|
4
|
-
troubadix/codespell/codespell.additions,sha256=
|
|
5
|
-
troubadix/codespell/codespell.exclude,sha256=
|
|
4
|
+
troubadix/codespell/codespell.additions,sha256=E62zoHJavUhcbMoyBqO2rOUe3OqIXikh7uAiGmNs5uw,524
|
|
5
|
+
troubadix/codespell/codespell.exclude,sha256=8blBv8KRrKU4KQhneHOPth1tSCYdrEoOCI5kYRfhOEA,147451
|
|
6
6
|
troubadix/codespell/codespell.ignore,sha256=2CP8u6O2VENcDpt2FfEDNmfa1Eh3D80yeYHT54GM1X4,1512
|
|
7
7
|
troubadix/helper/__init__.py,sha256=tp2fPLzwGEA_2eiJbvuePiY6rjYSFxx7VUsCV4fSwvw,1110
|
|
8
8
|
troubadix/helper/helper.py,sha256=GXapYLii2rLKwkX2ok31YoAdUSizBnyPjWz-aPP6HM8,3105
|
|
@@ -26,7 +26,7 @@ troubadix/plugins/duplicated_script_tags.py,sha256=UPBR2jbU15JLKJlVk1e2GFREH5Wj5
|
|
|
26
26
|
troubadix/plugins/encoding.py,sha256=zNzqNpP39TUwOklnc8OJ3OIUelAN_hvnuBYoa3Pz764,2104
|
|
27
27
|
troubadix/plugins/forking_nasl_functions.py,sha256=pYUebqPBWuqfLmnRYJgpGnrmx4YbnKIiRG8cmsIgmq4,6014
|
|
28
28
|
troubadix/plugins/get_kb_on_services.py,sha256=oFmcjiF7ZD3x5tEbJEoZNn80y1qUzNgeSZNsogSqaZ0,3401
|
|
29
|
-
troubadix/plugins/grammar.py,sha256=
|
|
29
|
+
troubadix/plugins/grammar.py,sha256=iEDFtQX-t1oLFeXiOTHM0NBHeY3X9WZrp1SNZPQT8vw,9411
|
|
30
30
|
troubadix/plugins/http_links_in_tags.py,sha256=yKT5SgLo__TJKAfudfIHkoMF0g9VtOP4VI77dANj014,7221
|
|
31
31
|
troubadix/plugins/illegal_characters.py,sha256=B6q_RU85AxCjLry56Oc-RhMSpnJU8mTrxclRzi1FVFU,4406
|
|
32
32
|
troubadix/plugins/log_messages.py,sha256=COrnp3bXMG8PRIAD2x5Ka9hk-jI16We9ifXj6JBZI0c,2960
|
|
@@ -88,18 +88,18 @@ troubadix/standalone_plugins/changed_packages/marker/marker.py,sha256=7uZXR2Ds_8
|
|
|
88
88
|
troubadix/standalone_plugins/changed_packages/package.py,sha256=Pcr2tcwiPTzD3jB0iteqA7-TajL-dl5Onh1dvC_H9xk,2743
|
|
89
89
|
troubadix/standalone_plugins/common.py,sha256=PkScV-lisNY4WyrzwjV3dK1DF26hJv5JXTcREblJ0v0,1028
|
|
90
90
|
troubadix/standalone_plugins/dependency_graph/__init__.py,sha256=SQSaQXWmpq5-5ozpqMgvnvoYTK8oj64A5kie1m_5bWQ,88
|
|
91
|
-
troubadix/standalone_plugins/dependency_graph/checks.py,sha256=
|
|
92
|
-
troubadix/standalone_plugins/dependency_graph/cli.py,sha256=
|
|
93
|
-
troubadix/standalone_plugins/dependency_graph/dependency_graph.py,sha256=
|
|
94
|
-
troubadix/standalone_plugins/dependency_graph/models.py,sha256=
|
|
91
|
+
troubadix/standalone_plugins/dependency_graph/checks.py,sha256=O4KyiVKpKxrgdmADXiduKY794nZndyy7epilbbY7JLo,4074
|
|
92
|
+
troubadix/standalone_plugins/dependency_graph/cli.py,sha256=RIyGeSm83XJ88N7Ati6z417hXkMajzzAtqdxnOg-urI,1305
|
|
93
|
+
troubadix/standalone_plugins/dependency_graph/dependency_graph.py,sha256=G_Ilm_EENpVHTw8wItknbfytVPRuTnVN1OoZEYvlTaU,5613
|
|
94
|
+
troubadix/standalone_plugins/dependency_graph/models.py,sha256=7kLrjFRdyReTRTgxte6-3KCBve4evg91AcqkX4I8VJU,1002
|
|
95
95
|
troubadix/standalone_plugins/deprecate_vts.py,sha256=mLt2DV9Y1YAEuh6c4nFweZYIOprsBzO7115dihEn4lA,7602
|
|
96
96
|
troubadix/standalone_plugins/file_extensions.py,sha256=fqswrhCcQqygIszcnobS9hFQmSpv3gDkvlufoaTckBg,2355
|
|
97
97
|
troubadix/standalone_plugins/last_modification.py,sha256=ROzwVzzYilXJ0llVt4Lv0w8b9BJKoahl6YxPDiub614,4338
|
|
98
98
|
troubadix/standalone_plugins/no_solution.py,sha256=p_-az9Igl4GH6HnhLLYbYlWIiEP64OTQLpX-z3JAshs,8760
|
|
99
99
|
troubadix/standalone_plugins/version_updated.py,sha256=6YHF0OjL5NWszQdsSh7XzlSji1e6Uaqwu_Y6m3R0mvI,4203
|
|
100
100
|
troubadix/troubadix.py,sha256=5__Jz3bYSrya4aG6RCBWxqnsDepXfwXZ3v0bjCzEFi0,6039
|
|
101
|
-
troubadix-25.
|
|
102
|
-
troubadix-25.
|
|
103
|
-
troubadix-25.
|
|
104
|
-
troubadix-25.
|
|
105
|
-
troubadix-25.
|
|
101
|
+
troubadix-25.4.0.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
102
|
+
troubadix-25.4.0.dist-info/METADATA,sha256=OGl9HWxYNgk0wTFIU5q5Q2Z6uf4VGcfg-YfSpQT87zo,4462
|
|
103
|
+
troubadix-25.4.0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
|
104
|
+
troubadix-25.4.0.dist-info/entry_points.txt,sha256=SnhEUe4W76P-ADmO9J355gRztTyHU_PTxRewKy3-e5o,832
|
|
105
|
+
troubadix-25.4.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|