1010 Generator ,
1111 Iterable ,
1212)
13- from dataclasses import (
14- asdict ,
15- dataclass ,
16- )
13+ from dataclasses import dataclass
1714from enum import Enum
1815from functools import partial
1916from inspect import cleandoc
2017from pathlib import Path
2118
2219import typer
2320
21+ from exasol .toolbox .security import (
22+ GitHubVulnerabilityIssue ,
23+ VulnerabilityIssue ,
24+ )
25+
2426stdout = print
2527stderr = partial (print , file = sys .stderr )
2628
2729
28- # Note: In the long term we may want to adapt the official CVE json schema
29- # https://github.com/CVEProject/cve-schema/blob/master/schema/v5.0/CVE_JSON_5.0_schema.json
30- @dataclass (frozen = True )
31- class Issue :
32- cve : str
33- cwe : str
34- description : str
35- coordinates : str
36- references : tuple
37-
38-
39- def _issues (input ) -> Generator [Issue ]:
40- lines = (l for l in input if l .strip () != "" )
41- for line in lines :
42- obj = json .loads (line )
43- yield Issue (** obj )
44-
45-
46- def _issues_as_json_str (issues ):
47- for issue in issues :
48- issue = asdict (issue )
49- yield json .dumps (issue )
50-
51-
5230def gh_security_issues () -> Generator [tuple [str , str ]]:
5331 """
5432 Yields issue-id, cve-id pairs for all (closed, open) issues associated with CVEs
@@ -87,14 +65,14 @@ def gh_security_issues() -> Generator[tuple[str, str]]:
8765 return issues
8866
8967
90- def from_maven (report : str ) -> Iterable [Issue ]:
68+ def from_maven (report : str ) -> Iterable [VulnerabilityIssue ]:
9169 # Note: Consider adding warnings if there is the same cve with multiple coordinates
9270 report = json .loads (report )
9371 dependencies = report .get ("vulnerable" , {}) # type: ignore
9472 for dependency_name , dependency in dependencies .items (): # type: ignore
9573 for v in dependency ["vulnerabilities" ]: # type: ignore
9674 references = [v ["reference" ]] + v ["externalReferences" ]
97- yield Issue (
75+ yield VulnerabilityIssue (
9876 cve = v ["cve" ],
9977 cwe = v ["cwe" ],
10078 description = v ["description" ],
@@ -145,10 +123,10 @@ def identify_pypi_references(
145123 )
146124
147125
148- def from_pip_audit (report : str ) -> Iterable [Issue ]:
126+ def from_pip_audit (report : str ) -> Iterable [VulnerabilityIssue ]:
149127 """
150128 Transforms the JSON output from `nox -s dependency:audit` into an iterable of
151- `security.Issue ` objects.
129+ `VulnerabilityIssue ` objects.
152130
153131 This does not gracefully handle scenarios where:
154132 - a CVE is not initially associated with the vulnerability; however, the assumption
@@ -175,7 +153,7 @@ def from_pip_audit(report: str) -> Iterable[Issue]:
175153 references = refs , package_name = package
176154 )
177155 if cves :
178- yield Issue (
156+ yield VulnerabilityIssue (
179157 cve = sorted (cves )[0 ],
180158 cwe = "None" if not cwes else ", " .join (cwes ),
181159 description = v ["description" ],
@@ -241,11 +219,11 @@ def _row(issue):
241219 return template .format (header = _header (), rows = "\n " .join (_row (i ) for i in issues ))
242220
243221
244- def security_issue_title (issue : Issue ) -> str :
222+ def security_issue_title (issue : VulnerabilityIssue ) -> str :
245223 return f"🔐 { issue .cve } : { issue .coordinates } "
246224
247225
248- def security_issue_body (issue : Issue ) -> str :
226+ def security_issue_body (issue : VulnerabilityIssue ) -> str :
249227 def as_markdown_listing (elements : Iterable [str ]):
250228 return "\n " .join (f"- { element } " for element in elements )
251229
@@ -269,7 +247,9 @@ def as_markdown_listing(elements: Iterable[str]):
269247 )
270248
271249
272- def create_security_issue (issue : Issue , project : str | None = None ) -> tuple [str , str ]:
250+ def create_security_issue (
251+ issue : VulnerabilityIssue , project : str | None = None
252+ ) -> tuple [str , str ]:
273253 # fmt: off
274254 command = [
275255 "gh" , "issue" , "create" ,
@@ -322,14 +302,14 @@ def convert(
322302
323303 def _maven (infile ):
324304 issues = from_maven (infile .read ())
325- for issue in _issues_as_json_str ( issues ) :
326- stdout (issue )
305+ for issue in issues :
306+ stdout (issue . json_str )
327307 raise typer .Exit (code = 0 )
328308
329309 def _pip_audit (infile ):
330310 issues = from_pip_audit (infile .read ())
331- for issue in _issues_as_json_str ( issues ) :
332- stdout (issue )
311+ for issue in issues :
312+ stdout (issue . json_str )
333313 raise typer .Exit (code = 0 )
334314
335315 actions = {Format .Maven : _maven , Format .PipAudit : _pip_audit }
@@ -364,10 +344,12 @@ def _github(infile):
364344 for issue in to_be_filtered :
365345 stderr (f"{ issue } " )
366346 filtered_issues = [
367- issue for issue in _issues (infile ) if issue .cve not in to_be_filtered
347+ issue
348+ for issue in VulnerabilityIssue .extract_from_jsonl (infile )
349+ if issue .cve not in to_be_filtered
368350 ]
369- for issue in _issues_as_json_str ( filtered_issues ) :
370- stdout (issue )
351+ for issue in filtered_issues :
352+ stdout (issue . json_str )
371353 raise typer .Exit (code = 0 )
372354
373355 def _pass_through (infile ):
@@ -398,10 +380,13 @@ def create(
398380 Output:
399381 { "cve": "<cve-id>", "cwe": "<cwe-id>", "description": "<multiline string>", "coordinates": "<string>", "references": ["<url>", "<url>", ...], "issue_url": "<url>" }
400382 """
401- for issue in _issues (input_file ):
383+ for issue in VulnerabilityIssue . extract_from_jsonl (input_file ):
402384 std_err , issue_url = create_security_issue (issue , project )
403385 stderr (std_err )
404- stdout (format_jsonl (issue_url , issue ))
386+ ghvi = GitHubVulnerabilityIssue .from_vulnerability_issue (
387+ issue = issue , issue_url = issue_url
388+ )
389+ stdout (ghvi .json_str )
405390
406391
407392class PPrintFormats (str , Enum ):
@@ -421,11 +406,5 @@ def json_issue_to_markdown(
421406 print (issues_to_markdown (issues ))
422407
423408
424- def format_jsonl (issue_url : str , issue : Issue ) -> str :
425- issue_json = asdict (issue )
426- issue_json ["issue_url" ] = issue_url .strip ()
427- return json .dumps (issue_json )
428-
429-
430409if __name__ == "__main__" :
431410 CLI ()
0 commit comments