devsecops-engine-tools 1.8.7__py3-none-any.whl → 1.8.9__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.

Potentially problematic release.


This version of devsecops-engine-tools might be problematic. Click here for more details.

Files changed (26) hide show
  1. devsecops_engine_tools/engine_core/src/domain/model/gateway/vulnerability_management_gateway.py +2 -2
  2. devsecops_engine_tools/engine_core/src/domain/model/report.py +23 -2
  3. devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py +47 -10
  4. devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/defect_dojo.py +64 -16
  5. devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_pretty_table/printer_pretty_table.py +5 -4
  6. devsecops_engine_tools/engine_core/src/infrastructure/entry_points/entry_point_core.py +7 -6
  7. devsecops_engine_tools/engine_core/src/infrastructure/helpers/util.py +1 -1
  8. devsecops_engine_tools/engine_risk/src/applications/runner_engine_risk.py +9 -2
  9. devsecops_engine_tools/engine_risk/src/domain/model/gateways/add_epss_gateway.py +7 -0
  10. devsecops_engine_tools/engine_risk/src/domain/usecases/add_data.py +16 -0
  11. devsecops_engine_tools/engine_risk/src/domain/usecases/break_build.py +271 -7
  12. devsecops_engine_tools/engine_risk/src/domain/usecases/get_exclusions.py +69 -0
  13. devsecops_engine_tools/engine_risk/src/domain/usecases/handle_filters.py +17 -11
  14. devsecops_engine_tools/engine_risk/src/infrastructure/driven_adapters/first_csv/__init__.py +0 -0
  15. devsecops_engine_tools/engine_risk/src/infrastructure/driven_adapters/first_csv/first_epss_csv.py +59 -0
  16. devsecops_engine_tools/engine_risk/src/infrastructure/entry_points/entry_point_risk.py +111 -15
  17. devsecops_engine_tools/engine_sca/engine_dependencies/src/infrastructure/driven_adapters/xray_tool/xray_manager_scan.py +17 -5
  18. devsecops_engine_tools/engine_utilities/defect_dojo/domain/models/finding.py +3 -1
  19. devsecops_engine_tools/engine_utilities/defect_dojo/domain/request_objects/finding.py +2 -0
  20. devsecops_engine_tools/engine_utilities/defect_dojo/domain/serializers/finding.py +2 -0
  21. devsecops_engine_tools/version.py +1 -1
  22. {devsecops_engine_tools-1.8.7.dist-info → devsecops_engine_tools-1.8.9.dist-info}/METADATA +10 -2
  23. {devsecops_engine_tools-1.8.7.dist-info → devsecops_engine_tools-1.8.9.dist-info}/RECORD +26 -21
  24. {devsecops_engine_tools-1.8.7.dist-info → devsecops_engine_tools-1.8.9.dist-info}/WHEEL +0 -0
  25. {devsecops_engine_tools-1.8.7.dist-info → devsecops_engine_tools-1.8.9.dist-info}/entry_points.txt +0 -0
  26. {devsecops_engine_tools-1.8.7.dist-info → devsecops_engine_tools-1.8.9.dist-info}/top_level.txt +0 -0
@@ -17,7 +17,7 @@ class VulnerabilityManagementGateway(metaclass=ABCMeta):
17
17
  "get_findings_excepted"
18
18
 
19
19
  @abstractmethod
20
- def get_all_findings(
20
+ def get_all(
21
21
  self, service, dict_args, secret_tool, config_tool
22
22
  ):
23
- "get_report"
23
+ "get all findings and exclusions from vulnerability management platform"
@@ -4,10 +4,31 @@ from dataclasses import dataclass
4
4
  @dataclass
5
5
  class Report:
6
6
  def __init__(self, **kwargs):
7
- self.id = kwargs.get("id", "")
8
- self.date = kwargs.get("date", "")
7
+ self.id = kwargs.get("id", [])
8
+ self.vuln_id_from_tool = kwargs.get("vuln_id_from_tool", "")
9
9
  self.where = kwargs.get("where", "")
10
10
  self.tags = kwargs.get("tags", [])
11
11
  self.severity = kwargs.get("severity", "")
12
+ self.age = kwargs.get("age", "")
12
13
  self.active = kwargs.get("active", "")
13
14
  self.status = kwargs.get("status", "")
15
+ self.risk_status = kwargs.get("risk_status", "")
16
+ self.risk_score = kwargs.get("risk_score", "")
17
+ self.created = kwargs.get("created", "")
18
+ self.publish_date = kwargs.get("publish_date", "")
19
+ self.last_reviewed = kwargs.get("last_reviewed", "")
20
+ self.last_status_update = kwargs.get("last_status_update", "")
21
+ self.accepted_risks = kwargs.get("accepted_risks", "")
22
+ self.transfer_finding = kwargs.get("transfer_finding", "")
23
+ self.epss_score = kwargs.get("epss_score", "")
24
+ self.epss_percentile = kwargs.get("epss_percentile", "")
25
+ self.mitigated = kwargs.get("mitigated", "")
26
+ self.vul_description = kwargs.get("vul_description", "")
27
+ self.risk_accepted = kwargs.get("risk_accepted", "")
28
+ self.false_p = kwargs.get("false_p", "")
29
+ self.service = kwargs.get("service", "")
30
+ self.reason = kwargs.get("reason", "")
31
+ self.component_name = kwargs.get("component_name", "")
32
+ self.component_version = kwargs.get("component_version", "")
33
+ self.file_path = kwargs.get("file_path", "")
34
+ self.endpoints = kwargs.get("endpoints", "")
@@ -16,6 +16,9 @@ from devsecops_engine_tools.engine_risk.src.applications.runner_engine_risk impo
16
16
  from devsecops_engine_tools.engine_core.src.domain.model.customs_exceptions import (
17
17
  ExceptionGettingFindings,
18
18
  )
19
+ from devsecops_engine_tools.engine_core.src.domain.model.input_core import (
20
+ InputCore
21
+ )
19
22
 
20
23
  from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
21
24
  from devsecops_engine_tools.engine_utilities import settings
@@ -36,29 +39,63 @@ class HandleRisk:
36
39
  self.devops_platform_gateway = devops_platform_gateway
37
40
  self.print_table_gateway = print_table_gateway
38
41
 
39
- def get_finding_list(self, dict_args, secret_tool, remote_config):
42
+ def _get_all_from_vm(self, dict_args, secret_tool, remote_config, service):
40
43
  try:
41
- findigs_list = self.vulnerability_management.get_all_findings(
42
- self.devops_platform_gateway.get_variable("pipeline_name"),
44
+ return self.vulnerability_management.get_all(
45
+ service,
43
46
  dict_args,
44
47
  secret_tool,
45
48
  remote_config,
46
49
  )
47
- return findigs_list
48
50
  except ExceptionGettingFindings as e:
49
- logger.error("Error getting finding list in handle risk: {0}".format(str(e)))
50
-
51
+ logger.error(
52
+ "Error getting finding list in handle risk: {0}".format(str(e))
53
+ )
51
54
 
52
55
  def process(self, dict_args: any, remote_config: any):
53
56
  secret_tool = None
54
57
  if dict_args["use_secrets_manager"] == "true":
55
58
  secret_tool = self.secrets_manager_gateway.get_secret(remote_config)
56
59
 
57
- findigs_list = self.get_finding_list(dict_args, secret_tool, remote_config)
60
+ risk_config = self.devops_platform_gateway.get_remote_config(
61
+ dict_args["remote_config_repo"], "engine_risk/ConfigTool.json"
62
+ )
63
+
64
+ service = self.devops_platform_gateway.get_variable("pipeline_name")
65
+ parent_identifier = risk_config["PARENT_ANALYSIS"]["PARENT_IDENTIFIER"]
66
+
67
+ parent_findings = []
68
+ parent_exclusions = []
69
+ if (
70
+ risk_config["PARENT_ANALYSIS"]["ENABLED"].lower() == "true"
71
+ and parent_identifier in service
72
+ ):
73
+ parent_service = service.split(parent_identifier)[0] + parent_identifier
74
+ parent_findings, parent_exclusions = self._get_all_from_vm(
75
+ dict_args, secret_tool, remote_config, parent_service
76
+ )
77
+
78
+ findings, exclusions = self._get_all_from_vm(
79
+ dict_args, secret_tool, remote_config, service
80
+ )
58
81
 
59
- runner_engine_risk(
82
+ findings_list = parent_findings + findings
83
+
84
+ exclusions_list = parent_exclusions + exclusions
85
+
86
+ result = runner_engine_risk(
60
87
  dict_args,
61
- findigs_list,
88
+ findings_list,
89
+ exclusions_list,
62
90
  self.devops_platform_gateway,
63
- self.print_table_gateway
91
+ self.print_table_gateway,
92
+ )
93
+ input_core = InputCore(
94
+ [],
95
+ {},
96
+ "",
97
+ "",
98
+ service,
99
+ self.devops_platform_gateway.get_variable("stage").capitalize(),
64
100
  )
101
+ return result, input_core
@@ -199,7 +199,11 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
199
199
  "Transferred Finding",
200
200
  )
201
201
 
202
- return list(exclusions_risk_accepted) + list(exclusions_false_positive) + list(exclusions_transfer_finding)
202
+ return (
203
+ list(exclusions_risk_accepted)
204
+ + list(exclusions_false_positive)
205
+ + list(exclusions_transfer_finding)
206
+ )
203
207
  except Exception as ex:
204
208
  raise ExceptionFindingsExcepted(
205
209
  "Error getting excepted findings with the following error: {0} ".format(
@@ -207,7 +211,7 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
207
211
  )
208
212
  )
209
213
 
210
- def get_all_findings(self, service, dict_args, secret_tool, config_tool):
214
+ def get_all(self, service, dict_args, secret_tool, config_tool):
211
215
  try:
212
216
  all_findings_query_params = {
213
217
  "limit": config_tool["VULNERABILITY_MANAGER"]["DEFECT_DOJO"][
@@ -225,16 +229,18 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
225
229
  all_findings_query_params,
226
230
  )
227
231
 
228
- maped_list = list(
232
+ all_findings = list(
229
233
  map(
230
- partial(
231
- self._create_report, date_fn=self._format_date_to_dd_format
232
- ),
234
+ partial(self._create_report),
233
235
  findings,
234
236
  )
235
237
  )
236
238
 
237
- return maped_list
239
+ all_exclusions = self._get_report_exclusions(
240
+ all_findings, self._format_date_to_dd_format
241
+ )
242
+
243
+ return all_findings, all_exclusions
238
244
 
239
245
  except Exception as ex:
240
246
  raise ExceptionGettingFindings(
@@ -250,6 +256,29 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
250
256
  config_tool["VULNERABILITY_MANAGER"]["DEFECT_DOJO"]["HOST_DEFECT_DOJO"],
251
257
  )
252
258
 
259
+ def _get_report_exclusions(self, total_findings, date_fn):
260
+ exclusions = []
261
+ for finding in total_findings:
262
+ if finding.risk_accepted:
263
+ exclusions.append(
264
+ self._create_exclusion(
265
+ finding, date_fn, "engine_risk", "Risk Accepted"
266
+ )
267
+ )
268
+ elif finding.false_p:
269
+ exclusions.append(
270
+ self._create_exclusion(
271
+ finding, date_fn, "engine_risk", "False Positive"
272
+ )
273
+ )
274
+ elif finding.risk_status == "Transfer Accepted":
275
+ exclusions.append(
276
+ self._create_exclusion(
277
+ finding, date_fn, "engine_risk", "Transferred Finding"
278
+ )
279
+ )
280
+ return exclusions
281
+
253
282
  def _get_findings_with_exclusions(
254
283
  self, session_manager, service, max_retries, query_params, tool, date_fn, reason
255
284
  ):
@@ -293,24 +322,44 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
293
322
  last_accepted_risk = finding.accepted_risks[-1]
294
323
  create_date = date_fn(last_accepted_risk["created"])
295
324
  expired_date = date_fn(last_accepted_risk["expiration_date"])
296
-
325
+
297
326
  return Exclusions(
298
327
  id=finding.vuln_id_from_tool,
299
328
  where=self._get_where(finding, tool),
300
329
  create_date=create_date,
301
330
  expired_date=expired_date,
331
+ severity=finding.severity,
302
332
  reason=reason,
303
333
  )
304
334
 
305
- def _create_report(self, finding, date_fn):
335
+ def _create_report(self, finding):
306
336
  return Report(
307
- id=finding.vuln_id_from_tool,
308
- date=date_fn(finding.date),
337
+ id=finding.vulnerability_ids,
338
+ vuln_id_from_tool=finding.vuln_id_from_tool,
309
339
  status=finding.display_status,
310
- where=self._get_where_report(finding),
340
+ component_name=finding.component_name,
341
+ component_version=finding.component_version,
342
+ file_path=finding.file_path,
343
+ endpoints=finding.endpoints,
344
+ where=self._get_where(finding, "engine_risk"),
311
345
  tags=finding.tags,
312
346
  severity=finding.severity,
347
+ age=finding.age,
313
348
  active=finding.active,
349
+ risk_status=finding.risk_status,
350
+ created=finding.created,
351
+ publish_date=finding.publish_date,
352
+ last_reviewed=finding.last_reviewed,
353
+ last_status_update=finding.last_status_update,
354
+ accepted_risks=finding.accepted_risks,
355
+ transfer_finding=finding.transfer_finding,
356
+ epss_score=finding.epss_score,
357
+ epss_percentile=finding.epss_percentile,
358
+ mitigated=finding.is_mitigated,
359
+ vul_description=finding.description,
360
+ risk_accepted=finding.risk_accepted,
361
+ false_p=finding.false_p,
362
+ service=finding.service,
314
363
  )
315
364
 
316
365
  def _format_date_to_dd_format(self, date_string):
@@ -320,14 +369,13 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
320
369
  else None
321
370
  )
322
371
 
323
- def _get_where_report(self, finding):
324
- for tag in finding.tags:
325
- return self._get_where(finding, tag)
326
-
327
372
  def _get_where(self, finding, tool):
328
373
  if tool in ["engine_container", "engine_dependencies"]:
329
374
  return finding.component_name + ":" + finding.component_version
330
375
  elif tool == "engine_dast":
331
376
  return finding.endpoints
377
+ elif tool == "engine_risk":
378
+ for tag in finding.tags:
379
+ return self._get_where(finding, tag)
332
380
  else:
333
381
  return finding.file_path
@@ -63,22 +63,23 @@ class PrinterPrettyTable(PrinterTableGateway):
63
63
  print(sorted_table)
64
64
 
65
65
  def print_table_report(self, report_list: "list[Report]"):
66
- headers = ["Severity", "ID", "Tag", "Where"]
66
+ headers = ["Risk Score", "Severity", "ID", "Tags", "Where", "Service"]
67
67
  table = PrettyTable(headers)
68
68
  for report in report_list:
69
69
  row_data = [
70
+ report.risk_score,
70
71
  report.severity.lower(),
71
- report.id,
72
+ report.vuln_id_from_tool if report.vuln_id_from_tool else report.id,
72
73
  report.tags,
73
74
  report.where,
75
+ report.service
74
76
  ]
75
77
  table.add_row(row_data)
76
78
 
77
- severity_order = {"critical": 0, "high": 1, "medium": 2, "low": 3}
78
79
  sorted_table = PrettyTable()
79
80
  sorted_table.field_names = table.field_names
80
81
  sorted_table.add_rows(
81
- sorted(table._rows, key=lambda row: severity_order[row[0]])
82
+ sorted(table._rows, key=lambda row: row[0], reverse=True)
82
83
  )
83
84
 
84
85
  for column in table.field_names:
@@ -30,12 +30,13 @@ def init_engine_core(
30
30
 
31
31
  if config_tool[args["tool"].upper()]["ENABLED"] == "true":
32
32
  if args["tool"] == "engine_risk":
33
- HandleRisk(
33
+ results, input_core = HandleRisk(
34
34
  vulnerability_management_gateway,
35
35
  secrets_manager_gateway,
36
36
  devops_platform_gateway,
37
37
  print_table_gateway,
38
38
  ).process(args, config_tool)
39
+
39
40
  else:
40
41
  findings_list, input_core = HandleScan(
41
42
  vulnerability_management_gateway,
@@ -43,15 +44,15 @@ def init_engine_core(
43
44
  devops_platform_gateway,
44
45
  ).process(args, config_tool)
45
46
 
46
- scan_result = BreakBuild(devops_platform_gateway, print_table_gateway).process(
47
+ results = BreakBuild(devops_platform_gateway, print_table_gateway).process(
47
48
  findings_list,
48
49
  input_core,
49
50
  args
50
51
  )
51
- if args["send_metrics"] == "true":
52
- MetricsManager(devops_platform_gateway, metrics_manager_gateway).process(
53
- config_tool, input_core, args, scan_result
54
- )
52
+ if args["send_metrics"] == "true":
53
+ MetricsManager(devops_platform_gateway, metrics_manager_gateway).process(
54
+ config_tool, input_core, args, results
55
+ )
55
56
  else:
56
57
  print(
57
58
  devops_platform_gateway.message(
@@ -11,5 +11,5 @@ def define_env(variable_env, branch):
11
11
  return (
12
12
  "pdn"
13
13
  if branch in ["trunk", "master"]
14
- else "qa" if branch in "release" else "dev"
14
+ else "qa" if branch=="release" else "dev"
15
15
  )
@@ -1,3 +1,6 @@
1
+ from devsecops_engine_tools.engine_risk.src.infrastructure.driven_adapters.first_csv.first_epss_csv import (
2
+ FirstCsv,
3
+ )
1
4
  from devsecops_engine_tools.engine_risk.src.infrastructure.entry_points.entry_point_risk import (
2
5
  init_engine_risk,
3
6
  )
@@ -10,11 +13,15 @@ logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger()
10
13
 
11
14
 
12
15
  def runner_engine_risk(
13
- dict_args, findings, devops_platform_gateway, print_table_gateway
16
+ dict_args, findings, vm_exclusions, devops_platform_gateway, print_table_gateway
14
17
  ):
15
- init_engine_risk(
18
+ add_epss_gateway = FirstCsv()
19
+
20
+ return init_engine_risk(
21
+ add_epss_gateway,
16
22
  devops_platform_gateway,
17
23
  print_table_gateway,
18
24
  dict_args,
19
25
  findings,
26
+ vm_exclusions,
20
27
  )
@@ -0,0 +1,7 @@
1
+ from abc import ABCMeta, abstractmethod
2
+
3
+
4
+ class AddEpssGateway(metaclass=ABCMeta):
5
+ @abstractmethod
6
+ def add_epss_data(self, findings) -> list:
7
+ "run add epss tool"
@@ -0,0 +1,16 @@
1
+ from devsecops_engine_tools.engine_risk.src.domain.model.gateways.add_epss_gateway import (
2
+ AddEpssGateway,
3
+ )
4
+
5
+
6
+ class AddData:
7
+ def __init__(
8
+ self,
9
+ add_epss_gateway: AddEpssGateway,
10
+ findings,
11
+ ):
12
+ self.add_epss_gateway = add_epss_gateway
13
+ self.findings = findings
14
+
15
+ def process(self):
16
+ return self.add_epss_gateway.add_epss_data(self.findings)
@@ -7,6 +7,12 @@ from devsecops_engine_tools.engine_core.src.domain.model.gateway.printer_table_g
7
7
  from devsecops_engine_tools.engine_core.src.domain.model.report import (
8
8
  Report,
9
9
  )
10
+ from devsecops_engine_tools.engine_core.src.domain.model.exclusions import (
11
+ Exclusions,
12
+ )
13
+
14
+ from collections import Counter
15
+ import copy
10
16
 
11
17
 
12
18
  class BreakBuild:
@@ -14,23 +20,281 @@ class BreakBuild:
14
20
  self,
15
21
  devops_platform_gateway: DevopsPlatformGateway,
16
22
  printer_table_gateway: PrinterTableGateway,
23
+ remote_config: any,
24
+ exclusions: "list[Exclusions]",
25
+ vm_exclusions: "list[Exclusions]",
26
+ report_list: "list[Report]",
27
+ all_report: "list[Report]",
17
28
  ):
18
29
  self.devops_platform_gateway = devops_platform_gateway
19
30
  self.printer_table_gateway = printer_table_gateway
31
+ self.remote_config = remote_config
32
+ self.exclusions = exclusions
33
+ self.vm_exclusions = vm_exclusions
34
+ self.report_list = report_list
35
+ self.all_report = all_report
36
+ self.break_build = False
37
+ self.warning_build = False
38
+ self.report_breaker = []
39
+ self.remediation_rate = 0
40
+ self.blacklisted = 0
41
+ self.max_risk_score = 0
42
+ self.status = "succeeded"
43
+ self.scan_result = {
44
+ "findings_excluded": [],
45
+ "vulnerabilities": {},
46
+ "compliances": {},
47
+ "risk": {},
48
+ }
49
+
50
+ def process(self):
51
+ self._remediation_rate_control(self.all_report)
52
+ new_report_list, applied_exclusions = self._apply_exclusions(self.report_list)
53
+ if self.break_build:
54
+ self.report_breaker.extend(copy.deepcopy(new_report_list))
55
+ self._tag_blacklist_control(new_report_list)
56
+ self._risk_score_control(new_report_list)
57
+ all_exclusions = list(self.vm_exclusions) + list(applied_exclusions)
58
+ self._print_exclusions(self._map_applied_exclusion(all_exclusions))
59
+
60
+ self.max_risk_score = (
61
+ max(report.risk_score for report in new_report_list)
62
+ if new_report_list
63
+ else 0
64
+ )
65
+
66
+ self._breaker()
67
+
68
+ self.scan_result["findings_excluded"] = list(
69
+ map(
70
+ lambda item: {
71
+ "severity": item.severity,
72
+ "id": item.id,
73
+ "category": item.reason,
74
+ },
75
+ all_exclusions,
76
+ )
77
+ )
20
78
 
21
- def process(self, report_list: "list[Report]"):
22
- devops_platform_gateway = self.devops_platform_gateway
23
- printer_table_gateway = self.printer_table_gateway
24
- if len(report_list):
79
+ self.scan_result["risk"] = {
80
+ "risk_control": {
81
+ "remediation_rate": self.remediation_rate,
82
+ "blacklisted": self.blacklisted,
83
+ "max_risk_score": self.max_risk_score,
84
+ },
85
+ "status": self.status,
86
+ "found": list(
87
+ map(
88
+ lambda item: {
89
+ "id": (
90
+ item.vuln_id_from_tool
91
+ if item.vuln_id_from_tool
92
+ else item.id
93
+ ),
94
+ "severity": item.severity,
95
+ "risk_score": item.risk_score,
96
+ "reason": item.reason,
97
+ },
98
+ self.report_breaker,
99
+ )
100
+ ),
101
+ }
102
+
103
+ print(
104
+ self.devops_platform_gateway.message(
105
+ "info",
106
+ self.remote_config["MESSAGE_INFO"],
107
+ )
108
+ )
109
+
110
+ return self.scan_result
111
+
112
+ def _breaker(self):
113
+ if self.break_build:
114
+ print(self.devops_platform_gateway.result_pipeline("failed"))
115
+ self.status = "failed"
116
+ else:
117
+ print(self.devops_platform_gateway.result_pipeline("succeeded"))
118
+
119
+ def _remediation_rate_control(self, all_report: "list[Report]"):
120
+ remote_config = self.remote_config
121
+ remediation_rate_value = self._get_percentage(
122
+ (sum(1 for report in all_report if report.mitigated)) / len(all_report)
123
+ )
124
+ risk_threshold = remote_config["THRESHOLD"]["REMEDIATION_RATE"]
125
+ self.remediation_rate = remediation_rate_value
126
+
127
+ if remediation_rate_value >= (risk_threshold + 5):
128
+ print(
129
+ self.devops_platform_gateway.message(
130
+ "succeeded",
131
+ f"Remediation Rate {remediation_rate_value}% is greater than {risk_threshold}%",
132
+ )
133
+ )
134
+ elif remediation_rate_value >= risk_threshold:
135
+ print(
136
+ self.devops_platform_gateway.message(
137
+ "warning",
138
+ f"Remediation Rate {remediation_rate_value}% is close to {risk_threshold}%",
139
+ )
140
+ )
141
+ self.warning_build = True
142
+ else:
25
143
  print(
26
- "Below are all vulnerabilities from Vulnerability Management Platform"
144
+ self.devops_platform_gateway.message(
145
+ "error",
146
+ f"Remediation Rate {remediation_rate_value}% is less than {risk_threshold}%",
147
+ )
27
148
  )
28
- printer_table_gateway.print_table_report(
149
+ self.break_build = True
150
+
151
+ def _get_percentage(self, decimal):
152
+ return round(decimal * 100, 3)
153
+
154
+ def _get_applied_exclusion(self, report: Report):
155
+ for exclusion in self.exclusions:
156
+ if exclusion.id and (report.id == exclusion.id):
157
+ return exclusion
158
+ elif exclusion.id and (report.vuln_id_from_tool == exclusion.id):
159
+ return exclusion
160
+ return None
161
+
162
+ def _map_applied_exclusion(self, exclusions: "list[Exclusions]"):
163
+ return [
164
+ {
165
+ "severity": exclusion.severity,
166
+ "id": exclusion.id,
167
+ "where": exclusion.where,
168
+ "create_date": exclusion.create_date,
169
+ "expired_date": exclusion.expired_date,
170
+ "reason": exclusion.reason,
171
+ }
172
+ for exclusion in exclusions
173
+ ]
174
+
175
+ def _apply_exclusions(self, report_list: "list[Report]"):
176
+ new_report_list = []
177
+ applied_exclusions = []
178
+ exclusions_ids = {exclusion.id for exclusion in self.exclusions if exclusion.id}
179
+
180
+ for report in report_list:
181
+ if report.vuln_id_from_tool and (
182
+ report.vuln_id_from_tool in exclusions_ids
183
+ ):
184
+ applied_exclusions.append(self._get_applied_exclusion(report))
185
+ elif report.id and (report.id in exclusions_ids):
186
+ applied_exclusions.append(self._get_applied_exclusion(report))
187
+ else:
188
+ report.reason = "Remediation Rate"
189
+ new_report_list.append(report)
190
+
191
+ return new_report_list, applied_exclusions
192
+
193
+ def _tag_blacklist_control(self, report_list: "list[Report]"):
194
+ remote_config = self.remote_config
195
+ if report_list:
196
+ tag_blacklist = set(remote_config["THRESHOLD"]["TAG_BLACKLIST"])
197
+ tag_age_threshold = remote_config["THRESHOLD"]["TAG_MAX_AGE"]
198
+
199
+ filtered_reports_above_threshold = [
200
+ (report, tag)
201
+ for report in report_list
202
+ for tag in report.tags
203
+ if tag in tag_blacklist and report.age >= tag_age_threshold
204
+ ]
205
+
206
+ filtered_reports_below_threshold = [
207
+ (report, tag)
208
+ for report in report_list
209
+ for tag in report.tags
210
+ if tag in tag_blacklist and report.age < tag_age_threshold
211
+ ]
212
+
213
+ for report, tag in filtered_reports_above_threshold:
214
+ report.reason = "Blacklisted"
215
+ print(
216
+ self.devops_platform_gateway.message(
217
+ "error",
218
+ f"Report {report.vuln_id_from_tool if report.vuln_id_from_tool else report.id} with tag {tag} is blacklisted and age {report.age} is above threshold {tag_age_threshold}",
219
+ )
220
+ )
221
+
222
+ for report, tag in filtered_reports_below_threshold:
223
+ print(
224
+ self.devops_platform_gateway.message(
225
+ "warning",
226
+ f"Report {report.vuln_id_from_tool if report.vuln_id_from_tool else report.id} with tag {tag} is blacklisted but age {report.age} is below threshold {tag_age_threshold}",
227
+ )
228
+ )
229
+
230
+ if filtered_reports_above_threshold:
231
+ self.break_build = True
232
+ self.blacklisted = len(filtered_reports_above_threshold)
233
+ self.report_breaker.extend(
234
+ copy.deepcopy(
235
+ [report for report, _ in filtered_reports_above_threshold]
236
+ )
237
+ )
238
+
239
+ def _risk_score_control(self, report_list: "list[Report]"):
240
+ remote_config = self.remote_config
241
+ risk_score_threshold = remote_config["THRESHOLD"]["RISK_SCORE"]
242
+ break_build = False
243
+ if report_list:
244
+ for report in report_list:
245
+ report.risk_score = round(
246
+ remote_config["WEIGHTS"]["severity"].get(report.severity.lower(), 0)
247
+ + remote_config["WEIGHTS"]["epss_score"] * report.epss_score
248
+ + remote_config["WEIGHTS"]["age"] * report.age
249
+ + sum(
250
+ remote_config["WEIGHTS"]["tags"].get(tag, 0)
251
+ for tag in report.tags
252
+ ),
253
+ 4,
254
+ )
255
+ if report.risk_score >= risk_score_threshold:
256
+ break_build = True
257
+ report.reason = "Risk Score"
258
+ self.report_breaker.append(copy.deepcopy(report))
259
+ print(
260
+ "Below are open vulnerabilities from Vulnerability Management Platform"
261
+ )
262
+ self.printer_table_gateway.print_table_report(
29
263
  report_list,
30
264
  )
265
+ if break_build:
266
+ self.break_build = True
267
+ print(
268
+ self.devops_platform_gateway.message(
269
+ "error",
270
+ f"There are findings with risk score greater than {risk_score_threshold}",
271
+ )
272
+ )
273
+ else:
274
+ print(
275
+ self.devops_platform_gateway.message(
276
+ "succeeded",
277
+ f"There are no findings with risk score greater than {risk_score_threshold}",
278
+ )
279
+ )
280
+ print(f"Findings count: {len(report_list)}")
281
+
31
282
  else:
32
283
  print(
33
- devops_platform_gateway.message(
284
+ self.devops_platform_gateway.message(
34
285
  "succeeded", "There are no vulnerabilities"
35
286
  )
36
287
  )
288
+
289
+ def _print_exclusions(self, applied_exclusions: "list[Exclusions]"):
290
+ if applied_exclusions:
291
+ print(
292
+ self.devops_platform_gateway.message(
293
+ "warning", "Bellow are all findings that were excepted"
294
+ )
295
+ )
296
+ self.printer_table_gateway.print_table_exclusions(applied_exclusions)
297
+ for reason, total in Counter(
298
+ map(lambda x: x["reason"], applied_exclusions)
299
+ ).items():
300
+ print("{0} findings count: {1}".format(reason, total))
@@ -0,0 +1,69 @@
1
+ from devsecops_engine_tools.engine_core.src.domain.model.exclusions import (
2
+ Exclusions,
3
+ )
4
+
5
+
6
+ class GetExclusions:
7
+ def __init__(
8
+ self,
9
+ devops_platform_gateway,
10
+ dict_args,
11
+ findings,
12
+ risk_config,
13
+ risk_exclusions,
14
+ pipeline_name,
15
+ ):
16
+ self.devops_platform_gateway = devops_platform_gateway
17
+ self.dict_args = dict_args
18
+ self.findings = findings
19
+ self.risk_config = risk_config
20
+ self.risk_exclusions = risk_exclusions
21
+ self.pipeline_name = pipeline_name
22
+
23
+ def process(self):
24
+ core_config = self.devops_platform_gateway.get_remote_config(
25
+ self.dict_args["remote_config_repo"], "engine_core/ConfigTool.json"
26
+ )
27
+ unique_tags = self._get_unique_tags()
28
+ exclusions = []
29
+ exclusions.extend(self._get_risk_exclusions())
30
+ for key in self.risk_config["EXCLUSIONS_PATHS"].keys():
31
+ if key in unique_tags:
32
+ exclusions.extend(
33
+ self._get_exclusions_by_practice(
34
+ core_config, key, self.risk_config["EXCLUSIONS_PATHS"][key]
35
+ )
36
+ )
37
+
38
+ return exclusions
39
+
40
+ def _get_risk_exclusions(self):
41
+ return self._get_exclusions(self.risk_exclusions, "RISK")
42
+
43
+ def _get_exclusions_by_practice(self, core_config, practice, path):
44
+ exclusions_config = self.devops_platform_gateway.get_remote_config(
45
+ self.dict_args["remote_config_repo"], path
46
+ )
47
+ tool = core_config[practice.upper()]["TOOL"]
48
+ return self._get_exclusions(exclusions_config, tool)
49
+
50
+ def _get_exclusions(self, config, key):
51
+ exclusions = []
52
+ for scope in ["All", self.pipeline_name]:
53
+ if config.get(scope, None) and config[scope].get(key, None):
54
+ exclusions.extend(
55
+ [
56
+ Exclusions(
57
+ **exclusion,
58
+ )
59
+ for exclusion in config[scope][key]
60
+ ]
61
+ )
62
+ return exclusions
63
+
64
+ def _get_unique_tags(self):
65
+ unique_tags = set()
66
+ for finding in self.findings:
67
+ tags = finding.tags
68
+ unique_tags.update(tags)
69
+ return list(unique_tags)
@@ -1,18 +1,24 @@
1
1
  class HandleFilters:
2
- def __init__(
3
- self,
4
- remote_config,
5
- ):
6
- self.remote_config = remote_config
7
-
8
2
  def filter(self, findings):
9
- tag_list = self.remote_config["TAG_FILTER"]
10
- severity_list = ["critical", "high", "medium", "low"]
3
+ active_findings = self._get_active_findings(findings)
4
+ self._get_priority_vulnerability(active_findings)
5
+ return active_findings
6
+
7
+ def _get_active_findings(self, findings):
11
8
  return list(
12
9
  filter(
13
- lambda finding: finding.active
14
- and any(tag in finding.tags for tag in tag_list)
15
- and (finding.severity.lower() in severity_list),
10
+ lambda finding: finding.active,
16
11
  findings,
17
12
  )
18
13
  )
14
+
15
+ def _get_priority_vulnerability(self, findings):
16
+ for finding in findings:
17
+ found_cve = False
18
+ for vul in finding.id:
19
+ if vul["vulnerability_id"].startswith("CVE"):
20
+ finding.id = vul["vulnerability_id"]
21
+ found_cve = True
22
+ break
23
+ if not found_cve and finding.id:
24
+ finding.id = finding.id[0]["vulnerability_id"]
@@ -0,0 +1,59 @@
1
+ from devsecops_engine_tools.engine_risk.src.domain.model.gateways.add_epss_gateway import (
2
+ AddEpssGateway,
3
+ )
4
+
5
+ import requests
6
+ import datetime
7
+ import io
8
+ import gzip
9
+ import csv
10
+
11
+ from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
12
+ from devsecops_engine_tools.engine_utilities import settings
13
+
14
+ logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger()
15
+
16
+
17
+ class FirstCsv(AddEpssGateway):
18
+ def download_epss_data(self):
19
+ base_url = "https://epss.cyentia.com/epss_scores-{}.csv.gz"
20
+ date = datetime.datetime.now()
21
+ attempts = 0
22
+ while attempts < 2:
23
+ formatted_date = date.strftime("%Y-%m-%d")
24
+ url = base_url.format(formatted_date)
25
+ response = requests.get(url)
26
+ if response.status_code == 200:
27
+ with gzip.open(io.BytesIO(response.content), "rt") as f:
28
+ data = f.read()
29
+ logger.info(f"EPSS data downloaded for date: {formatted_date}")
30
+ return data
31
+ else:
32
+ date -= datetime.timedelta(days=1)
33
+ attempts += 1
34
+ print("Could not find EPSS data from de last 2 days. Skipping add EPS data...")
35
+ logger.error(
36
+ "Could not find EPSS data from de last 2 days. Skipping add EPS data..."
37
+ )
38
+ return None
39
+
40
+ def get_epss_dict(self, epss_data):
41
+ epss_dict = {}
42
+ csv_reader = csv.reader(io.StringIO(epss_data))
43
+ for row in csv_reader:
44
+ if len(row) >= 2:
45
+ epss_dict[row[0]] = row[1]
46
+ return epss_dict
47
+
48
+ def add_epss_data(self, findings):
49
+ needs_epss_update = any(
50
+ finding.id[:3] == "CVE" and finding.epss_score == 0 for finding in findings
51
+ )
52
+ if needs_epss_update:
53
+ epss_data = self.download_epss_data()
54
+ if epss_data:
55
+ epss_dict = self.get_epss_dict(epss_data)
56
+ for finding in findings:
57
+ if finding.id[:3] == "CVE" and finding.epss_score == 0:
58
+ finding.epss_score = float(epss_dict.get(finding.id, 0))
59
+ return findings
@@ -4,6 +4,15 @@ from devsecops_engine_tools.engine_risk.src.domain.usecases.handle_filters impor
4
4
  from devsecops_engine_tools.engine_risk.src.domain.usecases.break_build import (
5
5
  BreakBuild,
6
6
  )
7
+ from devsecops_engine_tools.engine_risk.src.domain.usecases.add_data import (
8
+ AddData,
9
+ )
10
+ from devsecops_engine_tools.engine_risk.src.domain.usecases.get_exclusions import (
11
+ GetExclusions,
12
+ )
13
+
14
+
15
+ import re
7
16
 
8
17
  from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
9
18
  from devsecops_engine_tools.engine_utilities import settings
@@ -11,21 +20,108 @@ from devsecops_engine_tools.engine_utilities import settings
11
20
  logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger()
12
21
 
13
22
 
14
- def init_engine_risk(devops_platform_gateway, print_table_gateway, dict_args, findings):
23
+ def init_engine_risk(
24
+ add_epss_gateway,
25
+ devops_platform_gateway,
26
+ print_table_gateway,
27
+ dict_args,
28
+ findings,
29
+ vm_exclusions,
30
+ ):
15
31
  remote_config = devops_platform_gateway.get_remote_config(
16
32
  dict_args["remote_config_repo"], "engine_risk/ConfigTool.json"
17
33
  )
18
- findings_filtered = []
19
- if len(findings):
20
- handle_filters = HandleFilters(
21
- remote_config,
22
- )
23
- findings_filtered = handle_filters.filter(findings)
24
-
25
- BreakBuild(devops_platform_gateway, print_table_gateway).process(
26
- findings_filtered,
27
- )
28
-
29
- else:
30
- print("No Findings found in Vulnerability Management Platform")
31
- logger.info("No Findings found in Vulnerability Management Platform")
34
+ risk_exclusions = devops_platform_gateway.get_remote_config(
35
+ dict_args["remote_config_repo"], "engine_risk/Exclusions.json"
36
+ )
37
+ pipeline_name = devops_platform_gateway.get_variable("pipeline_name")
38
+ if should_skip_analysis(remote_config, pipeline_name, risk_exclusions):
39
+ print("Tool skipped by DevSecOps Policy.")
40
+ logger.info("Tool skipped by DevSecOps Policy.")
41
+ return
42
+
43
+ return process_findings(
44
+ findings,
45
+ vm_exclusions,
46
+ dict_args,
47
+ pipeline_name,
48
+ risk_exclusions,
49
+ remote_config,
50
+ add_epss_gateway,
51
+ devops_platform_gateway,
52
+ print_table_gateway,
53
+ )
54
+
55
+
56
+ def should_skip_analysis(remote_config, pipeline_name, exclusions):
57
+ ignore_pattern = remote_config["IGNORE_ANALYSIS_PATTERN"]
58
+ return re.match(ignore_pattern, pipeline_name, re.IGNORECASE) or (
59
+ pipeline_name in exclusions and exclusions[pipeline_name].get("SKIP_TOOL", 0)
60
+ )
61
+
62
+
63
+ def process_findings(
64
+ findings,
65
+ vm_exclusions,
66
+ dict_args,
67
+ pipeline_name,
68
+ risk_exclusions,
69
+ remote_config,
70
+ add_epss_gateway,
71
+ devops_platform_gateway,
72
+ print_table_gateway,
73
+ ):
74
+ if not findings:
75
+ print("No findings found in Vulnerability Management Platform")
76
+ logger.info("No findings found in Vulnerability Management Platform")
77
+ return
78
+
79
+ handle_filters = HandleFilters()
80
+
81
+ return process_active_findings(
82
+ handle_filters.filter(findings),
83
+ findings,
84
+ vm_exclusions,
85
+ devops_platform_gateway,
86
+ dict_args,
87
+ remote_config,
88
+ risk_exclusions,
89
+ pipeline_name,
90
+ add_epss_gateway,
91
+ print_table_gateway,
92
+ )
93
+
94
+
95
+ def process_active_findings(
96
+ active_findings,
97
+ total_findings,
98
+ vm_exclusions,
99
+ devops_platform_gateway,
100
+ dict_args,
101
+ remote_config,
102
+ risk_exclusions,
103
+ pipeline_name,
104
+ add_epss_gateway,
105
+ print_table_gateway,
106
+ ):
107
+ data_added = AddData(add_epss_gateway, active_findings).process()
108
+ get_exclusions = GetExclusions(
109
+ devops_platform_gateway,
110
+ dict_args,
111
+ data_added,
112
+ remote_config,
113
+ risk_exclusions,
114
+ pipeline_name,
115
+ )
116
+ exclusions = get_exclusions.process()
117
+ break_build = BreakBuild(
118
+ devops_platform_gateway,
119
+ print_table_gateway,
120
+ remote_config,
121
+ exclusions,
122
+ vm_exclusions,
123
+ data_added,
124
+ total_findings,
125
+ )
126
+
127
+ return break_build.process()
@@ -204,14 +204,26 @@ class XrayScan(ToolGateway):
204
204
  result = subprocess.run(
205
205
  command, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
206
206
  )
207
- if result.stdout:
208
- scan_result = json.loads(result.stdout)
209
- file_result = os.path.join(os.getcwd(), "scan_result.json")
210
- with open(file_result, "w") as file:
211
- json.dump(scan_result, file, indent=4)
207
+ if result.stdout or all(
208
+ word in result.stderr
209
+ for word in ["Technology", "WorkingDirectory", "Descriptors"]
210
+ ):
211
+ if result.stdout:
212
+ scan_result = json.loads(result.stdout)
213
+ else:
214
+ scan_result = {}
215
+ if any(
216
+ word in result.stderr
217
+ for word in ["What went wrong", "Caused by"]
218
+ ):
219
+ logger.error(f"Error executing Xray scan: {result.stderr}")
220
+ return None
212
221
  if result.stdout == "null\n":
213
222
  logger.warning(f"Xray scan returned null: {result.stderr}")
214
223
  return None
224
+ file_result = os.path.join(os.getcwd(), "scan_result.json")
225
+ with open(file_result, "w") as file:
226
+ json.dump(scan_result, file, indent=4)
215
227
  return file_result
216
228
  else:
217
229
  logger.error(f"Error executing Xray scan: {result.stderr}")
@@ -31,6 +31,8 @@ class Finding(FromDictMixin):
31
31
  date: str = ""
32
32
  sla_start_date = None
33
33
  cwe: int = 0
34
+ epss_score: int = 0
35
+ epss_percentile: int = 0
34
36
  cvssv3 = None
35
37
  cvssv3_score = None
36
38
  url: str = ""
@@ -66,6 +68,7 @@ class Finding(FromDictMixin):
66
68
  static_finding: bool = None
67
69
  dynamic_finding: bool = None
68
70
  created: str = ""
71
+ service: str = ""
69
72
  scanner_confidence = None
70
73
  unique_id_from_tool: str = ""
71
74
  vuln_id_from_tool: str = ""
@@ -75,7 +78,6 @@ class Finding(FromDictMixin):
75
78
  sast_source_file_path = None
76
79
  nb_occurences = None
77
80
  publish_date = None
78
- service = None
79
81
  planned_remediation_date = None
80
82
  planned_remediation_version = None
81
83
  effort_for_fixing = None
@@ -7,6 +7,8 @@ class FindingRequest:
7
7
  component_name: str = ""
8
8
  component_version: str = ""
9
9
  created: str = ""
10
+ epss_score: float = 0.0
11
+ epss_percentile: float = 0.0
10
12
  cvssv3: str = ""
11
13
  cvssv3_score: float = 0.0
12
14
  cwe = None
@@ -6,6 +6,8 @@ class FindingSerializer(Schema):
6
6
  component_name = fields.Str(requeride=False)
7
7
  component_version = fields.Str(requeride=False)
8
8
  created = fields.Str(requeride=False)
9
+ epss_score: fields.Int(requeride=False)
10
+ epss_percentile: fields.Int(requeride=False)
9
11
  cvssv3 = fields.Str(requeride=False)
10
12
  cvssv3_score = fields.Int(requeride=False)
11
13
  cwe = fields.List(fields.Int, requeride=False)
@@ -1 +1 @@
1
- version = '1.8.7'
1
+ version = '1.8.9'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: devsecops-engine-tools
3
- Version: 1.8.7
3
+ Version: 1.8.9
4
4
  Summary: Tool for DevSecOps strategy
5
5
  Home-page: https://github.com/bancolombia/devsecops-engine-tools
6
6
  Author: Bancolombia DevSecOps Team
@@ -67,7 +67,7 @@ pip3 install devsecops-engine-tools
67
67
  ### Scan running - flags (CLI)
68
68
 
69
69
  ```bash
70
- devsecops-engine-tools --platform_devops ["local","azure","github"] --remote_config_repo ["remote_config_repo"] --tool ["engine_iac", "engine_dast", "engine_secret", "engine_dependencies", "engine_container"] --folder_path ["Folder path scan engine_iac"] --platform ["k8s","cloudformation","docker", "openapi"] --use_secrets_manager ["false", "true"] --use_vulnerability_management ["false", "true"] --send_metrics ["false", "true"] --token_cmdb ["token_cmdb"] --token_vulnerability_management ["token_vulnerability_management"] --token_engine_container ["token_engine_container"] --token_engine_dependencies ["token_engine_dependencies"] --token_external_checks ["token_external_checks"] --xray_mode ["scan", "audit"] --image_to_scan ["image_to_scan"]
70
+ devsecops-engine-tools --platform_devops ["local","azure","github"] --remote_config_repo ["remote_config_repo"] --tool ["engine_iac", "engine_dast", "engine_secret", "engine_dependencies", "engine_container", "engine_risk"] --folder_path ["Folder path scan engine_iac"] --platform ["k8s","cloudformation","docker", "openapi"] --use_secrets_manager ["false", "true"] --use_vulnerability_management ["false", "true"] --send_metrics ["false", "true"] --token_cmdb ["token_cmdb"] --token_vulnerability_management ["token_vulnerability_management"] --token_engine_container ["token_engine_container"] --token_engine_dependencies ["token_engine_dependencies"] --token_external_checks ["token_external_checks"] --xray_mode ["scan", "audit"] --image_to_scan ["image_to_scan"]
71
71
  ```
72
72
 
73
73
  ### Structure Remote Config
@@ -76,6 +76,9 @@ devsecops-engine-tools --platform_devops ["local","azure","github"] --remote_con
76
76
  📦Remote_Config
77
77
  ┣ 📂engine_core
78
78
  ┃ ┗ 📜ConfigTool.json
79
+ ┣ 📂engine_risk
80
+ ┃ ┗ 📜ConfigTool.json
81
+ ┃ ┗ 📜Exclusions.json
79
82
  ┣ 📂engine_sast
80
83
  ┃ ┗ 📂engine_iac
81
84
  ┃ ┗ 📜ConfigTool.json
@@ -99,6 +102,11 @@ devsecops-engine-tools --platform_devops ["local","azure","github"] --remote_con
99
102
  <th>Module</th>
100
103
  <th>Tool</th>
101
104
  <th>Type</th>
105
+ </tr>
106
+ <tr>
107
+ <td>ENGINE_RISK</td>
108
+ <td><a href="https://defectdojo.com/">DEFECTDOJO</a></td>
109
+ <td>Free</td>
102
110
  </tr>
103
111
  <tr>
104
112
  <td rowspan="3">ENGINE_IAC</td>
@@ -1,5 +1,5 @@
1
1
  devsecops_engine_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- devsecops_engine_tools/version.py,sha256=CSY3U1mG4ZdGkeFALSRBoT3T-otyCaGlpwqlMkcKaLc,18
2
+ devsecops_engine_tools/version.py,sha256=mG55fPFXaVtS3iXQqmRMOEqiEwf4trMhP86SS7-Dino,17
3
3
  devsecops_engine_tools/engine_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  devsecops_engine_tools/engine_core/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  devsecops_engine_tools/engine_core/src/applications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -14,7 +14,7 @@ devsecops_engine_tools/engine_core/src/domain/model/finding.py,sha256=MntDksQuPt
14
14
  devsecops_engine_tools/engine_core/src/domain/model/input_core.py,sha256=hc1WMzCwsGxnrlvvk84S5iNYJRDQWbaQP9MwR3N7tVM,422
15
15
  devsecops_engine_tools/engine_core/src/domain/model/level_compliance.py,sha256=ntn_UWqHc6sT5g_LozBdjdewTQxFsp7Kt8M0xqw-k_o,98
16
16
  devsecops_engine_tools/engine_core/src/domain/model/level_vulnerability.py,sha256=0sySEnFNkS2Y8uF5GUVAYehXw-i2OglUClkVobnSTPc,257
17
- devsecops_engine_tools/engine_core/src/domain/model/report.py,sha256=eJ4r39OBgB-leNImTVV2fHuublFnpmCMHcvKWvL-hxs,410
17
+ devsecops_engine_tools/engine_core/src/domain/model/report.py,sha256=SGo9bxNGVO5ymjjuFlG3Tz1X9uh2JawNaQYyHHN_NL8,1640
18
18
  devsecops_engine_tools/engine_core/src/domain/model/threshold.py,sha256=AQu4NnYBvbUbzW_IkuCVF0_i535O4LeE3ZvBIZ7s9ZM,445
19
19
  devsecops_engine_tools/engine_core/src/domain/model/vulnerability_management.py,sha256=5RcMHpeqznrTOpkjLuqekA_Bqf2Qr-w6OZ5Eoi3b-bs,465
20
20
  devsecops_engine_tools/engine_core/src/domain/model/gateway/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -22,10 +22,10 @@ devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gate
22
22
  devsecops_engine_tools/engine_core/src/domain/model/gateway/metrics_manager_gateway.py,sha256=u_ivbmCyymw0Je7gRFg0uD9iDmZfTbteH5UwcgP0JAs,191
23
23
  devsecops_engine_tools/engine_core/src/domain/model/gateway/printer_table_gateway.py,sha256=ROBsh7Lyu62a5RqZ4KgGQcwrBzbHRwxAJ9Rj3LoupQc,602
24
24
  devsecops_engine_tools/engine_core/src/domain/model/gateway/secrets_manager_gateway.py,sha256=CTwUIvUWF0NSSzdCqASUFst6KUysW53NV9eatjLGdl8,170
25
- devsecops_engine_tools/engine_core/src/domain/model/gateway/vulnerability_management_gateway.py,sha256=sn9bEDfaNtRmHHtn49eSVg_JO7Zr2OVyj350KzyGiXo,667
25
+ devsecops_engine_tools/engine_core/src/domain/model/gateway/vulnerability_management_gateway.py,sha256=r3b9zKi0XwKfWTIF7E8Qc6ChbrCUSjh-u-0mKBjxTLA,718
26
26
  devsecops_engine_tools/engine_core/src/domain/usecases/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  devsecops_engine_tools/engine_core/src/domain/usecases/break_build.py,sha256=FCe7Yw42eK0u71sLivQvAF-bMwZqj4aGFdBTjy7LsVI,15955
28
- devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py,sha256=EBLEzm-p_lEeB7T8iarn2Fc4_6hY0XAIT1AJATd2JUM,2473
28
+ devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py,sha256=aJ0LuJCuQhp_ZT9Ctx5kdc4jIhmMoKemAZm9POp--Ig,3688
29
29
  devsecops_engine_tools/engine_core/src/domain/usecases/handle_scan.py,sha256=ee9ULqKGYfaxBUO8RNq-Znh4dbojghIauH4YIjYx9QU,6730
30
30
  devsecops_engine_tools/engine_core/src/domain/usecases/metrics_manager.py,sha256=Xi0iNnPrFgqd2cBdAA5E_tgouhxs-BTo016aolnGgv8,2413
31
31
  devsecops_engine_tools/engine_core/src/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -36,18 +36,18 @@ devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/aws/secret
36
36
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
37
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azure_devops.py,sha256=blI4ZrquRE4y6DJ7N2YRx1nL0wrAXvdpx0fLSUf5qwA,4831
38
38
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/defect_dojo.py,sha256=KcQJvVqJ9RUJA-o5-d6DF2l5AmXNCvZJfj7swzkC_v4,13484
39
+ devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/defect_dojo.py,sha256=TN5te3osSAeURx3bcnyRQSJVH8P_PoQ0IhaER_9kWS0,15398
40
40
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
41
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/github_actions.py,sha256=pxlgjhX4-Dssn-XHKK8AdCOj6Ry6VcQtoDf5q8CxTks,3731
42
42
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_pretty_table/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
- devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_pretty_table/printer_pretty_table.py,sha256=O1waYz_6ElcOkU3Nb4suJs2ZJIo0YLoFuNXi9-j-wSs,3811
43
+ devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_pretty_table/printer_pretty_table.py,sha256=oEhsYOS5dmTtNOzpWNurWgLxth6vBhWVvVlKul9Heys,3884
44
44
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/runtime_local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
45
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/runtime_local/runtime_local.py,sha256=2-BRh0BVuJp-IYpX5ah5uv3Tf0txm4y-tIwdo4fPH6Q,2463
46
46
  devsecops_engine_tools/engine_core/src/infrastructure/entry_points/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
- devsecops_engine_tools/engine_core/src/infrastructure/entry_points/entry_point_core.py,sha256=v8D9F_MvS2_zQqciDXUEaCHx6oK60ESpSdh-SDz851Y,2082
47
+ devsecops_engine_tools/engine_core/src/infrastructure/entry_points/entry_point_core.py,sha256=k6WLcv2NQj-OzV8lqmXef-Nyi9MLTzKWSWSM3qPFjvc,2081
48
48
  devsecops_engine_tools/engine_core/src/infrastructure/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
49
  devsecops_engine_tools/engine_core/src/infrastructure/helpers/aws.py,sha256=wfy_PosHS0rrvkdiUYczxIcc8ZNwfqzWwqVxrmRTCBI,264
50
- devsecops_engine_tools/engine_core/src/infrastructure/helpers/util.py,sha256=DTruKscu64gBk-0F-xwKcqKu6_Y8HhqemSpBJxd2BTY,382
50
+ devsecops_engine_tools/engine_core/src/infrastructure/helpers/util.py,sha256=lDtaozInb5m2R8Y-oGQasroksCRw_N_Ltz7gLkSguX8,380
51
51
  devsecops_engine_tools/engine_dast/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
52
  devsecops_engine_tools/engine_dast/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
53
  devsecops_engine_tools/engine_dast/src/applications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -63,19 +63,24 @@ devsecops_engine_tools/engine_dast/src/infrastructure/helpers/__init__.py,sha256
63
63
  devsecops_engine_tools/engine_risk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
64
  devsecops_engine_tools/engine_risk/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
65
  devsecops_engine_tools/engine_risk/src/applications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
- devsecops_engine_tools/engine_risk/src/applications/runner_engine_risk.py,sha256=1_9kBIxFAXAHLIcA8HK9CQrbXZgyANAR-JlDzck8G4w,558
66
+ devsecops_engine_tools/engine_risk/src/applications/runner_engine_risk.py,sha256=slE5CxJ-I2-FW9I9MKSOhjeCdBQEzGKXdFfXJd7XPQ8,789
67
67
  devsecops_engine_tools/engine_risk/src/deployment/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
68
  devsecops_engine_tools/engine_risk/src/deployment/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
69
  devsecops_engine_tools/engine_risk/src/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
70
  devsecops_engine_tools/engine_risk/src/domain/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
71
  devsecops_engine_tools/engine_risk/src/domain/model/gateways/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
+ devsecops_engine_tools/engine_risk/src/domain/model/gateways/add_epss_gateway.py,sha256=cTm4QSxiaUt7ETCdXWZxKEus8pmEDA3e9k5b39SLDDE,178
72
73
  devsecops_engine_tools/engine_risk/src/domain/usecases/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
- devsecops_engine_tools/engine_risk/src/domain/usecases/break_build.py,sha256=G0uFO59UJspQnq3Np2M5PiXTxWDZUgJqfkVyxcuk3jI,1225
74
- devsecops_engine_tools/engine_risk/src/domain/usecases/handle_filters.py,sha256=ModR0sg9QNACrZl4SKNre07t4J_nK1TO1vzZw1tN1GM,541
74
+ devsecops_engine_tools/engine_risk/src/domain/usecases/add_data.py,sha256=4wqDj-q7hJfJscvrbMDcy7tONqxdxl-CSl_TWTRUGKA,402
75
+ devsecops_engine_tools/engine_risk/src/domain/usecases/break_build.py,sha256=5iGoHwyTPGaYEad598xmCcx_HzKx1IEPVLCQOnhgubE,11377
76
+ devsecops_engine_tools/engine_risk/src/domain/usecases/get_exclusions.py,sha256=4wOIBwVVQDg5zUgijrFUeOcIyIbOvv32WR8a93nlEb4,2314
77
+ devsecops_engine_tools/engine_risk/src/domain/usecases/handle_filters.py,sha256=w18CVVSs0mkfLYo7f-wZJv1afoPWzEU-IBKUzk7LMYI,832
75
78
  devsecops_engine_tools/engine_risk/src/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
76
79
  devsecops_engine_tools/engine_risk/src/infrastructure/driven_adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
+ devsecops_engine_tools/engine_risk/src/infrastructure/driven_adapters/first_csv/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
+ devsecops_engine_tools/engine_risk/src/infrastructure/driven_adapters/first_csv/first_epss_csv.py,sha256=pWaRmIwVyiB5mlmWySHIx-DUgN9vtKQc-MqyRNVlTJo,2150
77
82
  devsecops_engine_tools/engine_risk/src/infrastructure/entry_points/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
78
- devsecops_engine_tools/engine_risk/src/infrastructure/entry_points/entry_point_risk.py,sha256=9clAw0ccvz7o8n6E-Uxtn_UKC-cVa_jp_JzIXnoYcmE,1107
83
+ devsecops_engine_tools/engine_risk/src/infrastructure/entry_points/entry_point_risk.py,sha256=HlWPr8Mg7kjnDGDmYqJRk-dJk-V8qDhtB08uUXBPVdw,3399
79
84
  devsecops_engine_tools/engine_risk/src/infrastructure/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
85
  devsecops_engine_tools/engine_sast/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
86
  devsecops_engine_tools/engine_sast/engine_iac/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -181,7 +186,7 @@ devsecops_engine_tools/engine_sca/engine_dependencies/src/infrastructure/__init_
181
186
  devsecops_engine_tools/engine_sca/engine_dependencies/src/infrastructure/driven_adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
182
187
  devsecops_engine_tools/engine_sca/engine_dependencies/src/infrastructure/driven_adapters/xray_tool/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
183
188
  devsecops_engine_tools/engine_sca/engine_dependencies/src/infrastructure/driven_adapters/xray_tool/xray_deserialize_output.py,sha256=Vm0pj1i6a34xXouXUU95Y04hzR--9tcMQuycR7IMUnQ,2221
184
- devsecops_engine_tools/engine_sca/engine_dependencies/src/infrastructure/driven_adapters/xray_tool/xray_manager_scan.py,sha256=1_jT819e8HKH-qirKtqvgyKAi16Pu0YW7OEkEqWoM_M,10052
189
+ devsecops_engine_tools/engine_sca/engine_dependencies/src/infrastructure/driven_adapters/xray_tool/xray_manager_scan.py,sha256=y3W4gpyAEHZoHEZaMaeFPfJ3zmNBc2TUcYhYCSosi1E,10525
185
190
  devsecops_engine_tools/engine_sca/engine_dependencies/src/infrastructure/entry_points/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
186
191
  devsecops_engine_tools/engine_sca/engine_dependencies/src/infrastructure/entry_points/entry_point_tool.py,sha256=NBzg9VoGIqHeXuhDR4vBgwPMFnkjzJssBddPo1R23R0,2524
187
192
  devsecops_engine_tools/engine_sca/engine_dependencies/src/infrastructure/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -203,17 +208,17 @@ devsecops_engine_tools/engine_utilities/defect_dojo/domain/__init__.py,sha256=47
203
208
  devsecops_engine_tools/engine_utilities/defect_dojo/domain/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
204
209
  devsecops_engine_tools/engine_utilities/defect_dojo/domain/models/cmdb.py,sha256=7EAzKzBJaDqP4Q57cyu_nCpl9WqcTZFjXydkYCh8h-k,320
205
210
  devsecops_engine_tools/engine_utilities/defect_dojo/domain/models/engagement.py,sha256=x0mkWoLv8rRHZTh7hhI1aZb2g9XFJ-Gz_gC-f-rZdWM,1372
206
- devsecops_engine_tools/engine_utilities/defect_dojo/domain/models/finding.py,sha256=z_fH5_dgdPNhmp3CtZ0IY7NnkASa1rng_FOiN6BR17Q,3145
211
+ devsecops_engine_tools/engine_utilities/defect_dojo/domain/models/finding.py,sha256=0Xj7BOlC30LCdBjIkviB2QmmdSj0GlDvT1-TbnaT8nE,3201
207
212
  devsecops_engine_tools/engine_utilities/defect_dojo/domain/models/product.py,sha256=KL5ue6icA8HH1xKkmAJzElAat3OOYU3_lt3xuNfo7Mc,1272
208
213
  devsecops_engine_tools/engine_utilities/defect_dojo/domain/models/product_list.py,sha256=ExoZSaOLRVioy85EMyDSl2ktSw8f1gp30mxacQCpP74,426
209
214
  devsecops_engine_tools/engine_utilities/defect_dojo/domain/models/product_type.py,sha256=2KVfRB0qgPO7osY4PBEQSOBOqRnZs0UzUZkS1guisBQ,524
210
215
  devsecops_engine_tools/engine_utilities/defect_dojo/domain/models/product_type_list.py,sha256=N5m4fHCqdlZs3EM7oaAMYvbzIebkOKzqpZZVn6wpcJQ,464
211
216
  devsecops_engine_tools/engine_utilities/defect_dojo/domain/models/scan_configuration.py,sha256=-uVxaTkxnDmUUGQUdN9x_VKR8KJUagJKnGR6B1emoEU,577
212
217
  devsecops_engine_tools/engine_utilities/defect_dojo/domain/request_objects/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
213
- devsecops_engine_tools/engine_utilities/defect_dojo/domain/request_objects/finding.py,sha256=VriR9km0yYP9tYt6BjLC7EZrQIQsaNZUN45OpWv8fzk,2558
218
+ devsecops_engine_tools/engine_utilities/defect_dojo/domain/request_objects/finding.py,sha256=RinG3ISc-u_3VXVqntwdcQvZoQdmHPCvDHWSvnkCkcU,2619
214
219
  devsecops_engine_tools/engine_utilities/defect_dojo/domain/request_objects/import_scan.py,sha256=Y1ewQ-9wM287MSEraT4myG1RDl4LjmeqansR3-Exn7U,4974
215
220
  devsecops_engine_tools/engine_utilities/defect_dojo/domain/serializers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
216
- devsecops_engine_tools/engine_utilities/defect_dojo/domain/serializers/finding.py,sha256=oo5AJYNtGHO0Gy76dHrLBlsZy_HRpifLOi7rzNLTJc0,5140
221
+ devsecops_engine_tools/engine_utilities/defect_dojo/domain/serializers/finding.py,sha256=HNkA_sHSMfQKAcZht-rRPdwm0eHYK2wxM6u61_bl2uE,5233
217
222
  devsecops_engine_tools/engine_utilities/defect_dojo/domain/serializers/import_scan.py,sha256=VyV1LzeJDk51RYXz8EiweLHccpsuwTY3hTkAnkscX2E,7211
218
223
  devsecops_engine_tools/engine_utilities/defect_dojo/domain/user_case/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
219
224
  devsecops_engine_tools/engine_utilities/defect_dojo/domain/user_case/cmdb.py,sha256=BUOdvP39bEMQ6Unr2hB28eljVGU2Uv8dDEkzRyEJgyQ,2650
@@ -249,8 +254,8 @@ devsecops_engine_tools/engine_utilities/utils/logger_info.py,sha256=4Mz8Bwlm9Mku
249
254
  devsecops_engine_tools/engine_utilities/utils/name_conversion.py,sha256=ADJrRGaxYSDe0ZRh6VHRf53H4sXPcb-vNP_i81PUn3I,307
250
255
  devsecops_engine_tools/engine_utilities/utils/printers.py,sha256=amYAr9YQfYgR6jK9a2l26z3oovFPQ3FAKmhq6BKhEBA,623
251
256
  devsecops_engine_tools/engine_utilities/utils/session_manager.py,sha256=yNtlT-8Legz1sHbGPH8LNYjL-LgDUE0zXG2rYjiab7U,290
252
- devsecops_engine_tools-1.8.7.dist-info/METADATA,sha256=_n4iDlB6FQUsRY4jARO-Fv6r0BRq0Q64IwbkLUKzCSM,10221
253
- devsecops_engine_tools-1.8.7.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
254
- devsecops_engine_tools-1.8.7.dist-info/entry_points.txt,sha256=9IjXF_7Zpgowq_SY6OSmsA9vZze18a8_AeHwkQVrgKk,131
255
- devsecops_engine_tools-1.8.7.dist-info/top_level.txt,sha256=ge6y0X_xBAU1aG3EMWFtl9djbVyg5BxuSp2r2Lg6EQU,23
256
- devsecops_engine_tools-1.8.7.dist-info/RECORD,,
257
+ devsecops_engine_tools-1.8.9.dist-info/METADATA,sha256=n177JIC-KVUixW88Z2FPhidKmLaAFUPa0Eq09G2FNUA,10443
258
+ devsecops_engine_tools-1.8.9.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
259
+ devsecops_engine_tools-1.8.9.dist-info/entry_points.txt,sha256=9IjXF_7Zpgowq_SY6OSmsA9vZze18a8_AeHwkQVrgKk,131
260
+ devsecops_engine_tools-1.8.9.dist-info/top_level.txt,sha256=ge6y0X_xBAU1aG3EMWFtl9djbVyg5BxuSp2r2Lg6EQU,23
261
+ devsecops_engine_tools-1.8.9.dist-info/RECORD,,