Coverage for lintro / parsers / osv_scanner / osv_scanner_issue.py: 100%

23 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-04-03 18:53 +0000

1"""Issue model for OSV-Scanner output.""" 

2 

3from dataclasses import dataclass, field 

4from typing import ClassVar 

5 

6from lintro.enums.severity_level import SeverityLevel 

7from lintro.parsers.base_issue import BaseIssue 

8 

9 

10@dataclass 

11class OsvScannerIssue(BaseIssue): 

12 """Represents a vulnerability found by OSV-Scanner. 

13 

14 Attributes: 

15 DISPLAY_FIELD_MAP: Mapping of display field names to attribute names. 

16 DEFAULT_SEVERITY: Fallback severity (ERROR for security vulnerabilities). 

17 vuln_id: OSV vulnerability ID (e.g., GHSA-xxxx, CVE-xxxx, PYSEC-xxxx). 

18 severity: Severity level (CRITICAL, HIGH, MEDIUM, LOW). 

19 package_name: Name of the affected package. 

20 package_version: Installed version of the affected package. 

21 package_ecosystem: Ecosystem of the package (PyPI, npm, Go, etc.). 

22 fixed_version: Version that fixes the vulnerability, if available. 

23 """ 

24 

25 DISPLAY_FIELD_MAP: ClassVar[dict[str, str]] = { 

26 **BaseIssue.DISPLAY_FIELD_MAP, 

27 "code": "vuln_id", 

28 } 

29 

30 DEFAULT_SEVERITY: ClassVar[SeverityLevel] = SeverityLevel.ERROR 

31 

32 vuln_id: str = field(default="") 

33 severity: str = field(default="MEDIUM") 

34 package_name: str = field(default="") 

35 package_version: str = field(default="") 

36 package_ecosystem: str = field(default="") 

37 fixed_version: str = field(default="") 

38 

39 def __post_init__(self) -> None: 

40 """Initialize the inherited fields with formatted message.""" 

41 if not self.file: 

42 self.file = "lockfile" 

43 self.message = self._get_message() 

44 

45 def _get_message(self) -> str: 

46 """Get the formatted issue message. 

47 

48 Returns: 

49 Formatted issue message with vulnerability context. 

50 """ 

51 parts = f"[{self.vuln_id}] {self.package_name}@{self.package_version}" 

52 if self.fixed_version: 

53 parts += f" (fix: {self.fixed_version})" 

54 return parts