ds-analysis-lib 6.0.0a2__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.
- analysis_lib/__init__.py +183 -0
- analysis_lib/config.py +1489 -0
- analysis_lib/csaf.py +707 -0
- analysis_lib/normalize.py +334 -0
- analysis_lib/output.py +1002 -0
- analysis_lib/reachability.py +258 -0
- analysis_lib/search.py +194 -0
- analysis_lib/utils.py +2091 -0
- analysis_lib/vdr.py +211 -0
- ds_analysis_lib-6.0.0a2.dist-info/METADATA +31 -0
- ds_analysis_lib-6.0.0a2.dist-info/RECORD +13 -0
- ds_analysis_lib-6.0.0a2.dist-info/WHEEL +5 -0
- ds_analysis_lib-6.0.0a2.dist-info/top_level.txt +1 -0
analysis_lib/__init__.py
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from importlib.metadata import distribution
|
|
5
|
+
from logging import Logger
|
|
6
|
+
from typing import Dict, List, Optional
|
|
7
|
+
import fnmatch
|
|
8
|
+
|
|
9
|
+
from rich.console import Console
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_all_bom_files(from_dir):
|
|
13
|
+
"""
|
|
14
|
+
Collect all BOM JSON files under `from_dir`,
|
|
15
|
+
excluding any files matching '*.vdr.json'.
|
|
16
|
+
"""
|
|
17
|
+
base = Path(from_dir)
|
|
18
|
+
include_patterns = ["*bom*.json", "*.cdx.json"]
|
|
19
|
+
exclude_pattern = "*.vdr.json"
|
|
20
|
+
|
|
21
|
+
files = set()
|
|
22
|
+
for pattern in include_patterns:
|
|
23
|
+
for p in base.rglob(pattern):
|
|
24
|
+
if not fnmatch.fnmatch(p.name, exclude_pattern):
|
|
25
|
+
files.add(str(p.resolve()))
|
|
26
|
+
|
|
27
|
+
return sorted(files)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class VdrAnalysisKV:
|
|
32
|
+
project_type: str
|
|
33
|
+
init_results: List
|
|
34
|
+
pkg_aliases: Optional[Dict]
|
|
35
|
+
purl_aliases: Optional[Dict]
|
|
36
|
+
suggest_mode: bool
|
|
37
|
+
scoped_pkgs: Dict
|
|
38
|
+
no_vuln_table: bool
|
|
39
|
+
bom_file: Optional[str] = None
|
|
40
|
+
bom_dir: Optional[str] = None
|
|
41
|
+
pkg_list: Optional[List[Dict]] = None
|
|
42
|
+
direct_purls: Optional[Dict] = None
|
|
43
|
+
reached_purls: Optional[Dict] = None
|
|
44
|
+
reached_services: Optional[Dict] = None
|
|
45
|
+
endpoint_reached_purls: Optional[Dict] = None
|
|
46
|
+
console: Optional[Console] = None
|
|
47
|
+
logger: Optional[Logger] = None
|
|
48
|
+
prebuild_purls: Optional[Dict] = None
|
|
49
|
+
build_purls: Optional[Dict] = None
|
|
50
|
+
postbuild_purls: Optional[Dict] = None
|
|
51
|
+
operations_refs: Optional[Dict] = None
|
|
52
|
+
decommission_refs: Optional[Dict] = None
|
|
53
|
+
fuzzy_search: bool = False
|
|
54
|
+
search_order: Optional[str] = None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass
|
|
58
|
+
class VDRResult:
|
|
59
|
+
"""
|
|
60
|
+
Data class representing the result of VDR analysis.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
success: bool = False
|
|
64
|
+
pkg_vulnerabilities: Optional[List[Dict]] = None
|
|
65
|
+
prioritized_pkg_vuln_trees: Optional[Dict] = None
|
|
66
|
+
prioritized_prebuild_vuln_trees: Optional[List[Dict]] = None
|
|
67
|
+
prioritized_build_vuln_trees: Optional[List[Dict]] = None
|
|
68
|
+
prioritized_postbuild_vuln_trees: Optional[List[Dict]] = None
|
|
69
|
+
prioritized_operations_vuln_trees: Optional[List[Dict]] = None
|
|
70
|
+
prioritized_decommission_vuln_trees: Optional[List[Dict]] = None
|
|
71
|
+
reached_purls: Optional[Dict[str, int]] = None
|
|
72
|
+
reached_services: Optional[Dict[str, int]] = None
|
|
73
|
+
endpoint_reached_purls: Optional[Dict[str, int]] = None
|
|
74
|
+
purl_identities: Optional[Dict[str, List]] = None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class Counts:
|
|
78
|
+
fp_count = 0
|
|
79
|
+
pkg_attention_count = 0
|
|
80
|
+
critical_count = 0
|
|
81
|
+
malicious_count = 0
|
|
82
|
+
has_poc_count = 0
|
|
83
|
+
has_reachable_poc_count = 0
|
|
84
|
+
has_exploit_count = 0
|
|
85
|
+
has_reachable_exploit_count = 0
|
|
86
|
+
fix_version_count = 0
|
|
87
|
+
wont_fix_version_count = 0
|
|
88
|
+
distro_packages_count = 0
|
|
89
|
+
has_os_packages = False
|
|
90
|
+
has_redhat_packages = False
|
|
91
|
+
has_ubuntu_packages = False
|
|
92
|
+
ids_seen = {}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class XBOMAnalyzer(ABC):
|
|
96
|
+
"""
|
|
97
|
+
Base class for analyzing xBOM
|
|
98
|
+
|
|
99
|
+
Attributes:
|
|
100
|
+
vdr_options (VdrAnalysisKV): VDR options
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
def __init__(self, vdr_options: VdrAnalysisKV) -> None:
|
|
104
|
+
self.vdr_options = vdr_options
|
|
105
|
+
|
|
106
|
+
@abstractmethod
|
|
107
|
+
def process(self) -> VDRResult:
|
|
108
|
+
"""
|
|
109
|
+
Perform the analysis.
|
|
110
|
+
Must be implemented by subclasses.
|
|
111
|
+
"""
|
|
112
|
+
raise NotImplementedError("Subclasses must implement this method.")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@dataclass
|
|
116
|
+
class ReachabilityAnalysisKV:
|
|
117
|
+
project_types: List[str]
|
|
118
|
+
src_dir: str
|
|
119
|
+
bom_dir: Optional[str]
|
|
120
|
+
bom_files: Optional[List[str]] = None
|
|
121
|
+
slices_files: Optional[List[str]] = None
|
|
122
|
+
openapi_spec_files: Optional[List[str]] = None
|
|
123
|
+
clean_up: bool = False
|
|
124
|
+
export_graph_dir: Optional[str] = None
|
|
125
|
+
detect_endpoints: bool = True
|
|
126
|
+
detect_crypto_libs: bool = True
|
|
127
|
+
require_multi_usage: bool = False
|
|
128
|
+
source_tags: Optional[List[str]] = None
|
|
129
|
+
sink_tags: Optional[List[str]] = None
|
|
130
|
+
|
|
131
|
+
def __post_init__(self):
|
|
132
|
+
# Collect bom files
|
|
133
|
+
if not self.bom_files and self.bom_dir:
|
|
134
|
+
self.bom_files = get_all_bom_files(self.bom_dir)
|
|
135
|
+
# Collect available slices files
|
|
136
|
+
if not self.slices_files and self.bom_dir:
|
|
137
|
+
self.slices_files = sorted(
|
|
138
|
+
str(p.resolve()) for p in Path(self.bom_dir).rglob("*slices.json")
|
|
139
|
+
)
|
|
140
|
+
# Collect the openapi spec files
|
|
141
|
+
if not self.openapi_spec_files:
|
|
142
|
+
search_dir = Path(self.bom_dir) if self.bom_dir else Path(self.src_dir)
|
|
143
|
+
self.openapi_spec_files = sorted(
|
|
144
|
+
str(p.resolve()) for p in search_dir.glob("*openapi*.json")
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@dataclass
|
|
149
|
+
class ReachabilityResult:
|
|
150
|
+
success: bool
|
|
151
|
+
direct_purls: Optional[Dict[str, int]] = None
|
|
152
|
+
reached_purls: Optional[Dict[str, int]] = None
|
|
153
|
+
reached_services: Optional[Dict[str, int]] = None
|
|
154
|
+
endpoint_reached_purls: Optional[Dict[str, int]] = None
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class ReachabilityAnalyzer(ABC):
|
|
158
|
+
"""
|
|
159
|
+
Base class for performing reachability analysis
|
|
160
|
+
|
|
161
|
+
Attributes:
|
|
162
|
+
analysis_options (ReachabilityAnalysisKV): Analysis options
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
def __init__(self, analysis_options: Optional[ReachabilityAnalysisKV]) -> None:
|
|
166
|
+
self.analysis_options = analysis_options
|
|
167
|
+
|
|
168
|
+
@abstractmethod
|
|
169
|
+
def process(self) -> ReachabilityResult:
|
|
170
|
+
"""
|
|
171
|
+
Perform the analysis.
|
|
172
|
+
Must be implemented by subclasses.
|
|
173
|
+
"""
|
|
174
|
+
raise NotImplementedError("Subclasses must implement this method.")
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def get_version():
|
|
178
|
+
"""
|
|
179
|
+
Returns the version of depscan
|
|
180
|
+
"""
|
|
181
|
+
return (
|
|
182
|
+
distribution("ds-analysis-lib").version or distribution("owasp-depscan").version
|
|
183
|
+
)
|