Coverage for lintro / parsers / cargo_audit / cargo_audit_issue.py: 95%

19 statements  

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

1"""Issue model for cargo-audit output.""" 

2 

3from dataclasses import dataclass, field 

4from typing import ClassVar 

5 

6from lintro.parsers.base_issue import BaseIssue 

7 

8 

9@dataclass 

10class CargoAuditIssue(BaseIssue): 

11 """Represents a security vulnerability found by cargo-audit. 

12 

13 Attributes: 

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

15 advisory_id: RustSec advisory ID (e.g., RUSTSEC-2021-0124). 

16 package_name: Name of the vulnerable crate. 

17 package_version: Version of the vulnerable crate. 

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

19 title: Short title of the vulnerability. 

20 description: Detailed description of the vulnerability. 

21 url: URL with more information about the advisory. 

22 """ 

23 

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

25 **BaseIssue.DISPLAY_FIELD_MAP, 

26 "code": "advisory_id", 

27 "severity": "severity", 

28 "message": "message", 

29 } 

30 

31 advisory_id: str = field(default="") 

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

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

34 severity: str = field(default="UNKNOWN") 

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

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

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

38 

39 def __post_init__(self) -> None: 

40 """Initialize the inherited fields.""" 

41 # Set file to Cargo.lock since that's what cargo-audit scans 

42 if not self.file: 

43 self.file = "Cargo.lock" 

44 # Build the message from components 

45 self.message = self._get_message() 

46 

47 def _get_message(self) -> str: 

48 """Get the formatted issue message. 

49 

50 Returns: 

51 str: Formatted issue message. 

52 """ 

53 return ( 

54 f"[{self.advisory_id}] {self.package_name}@{self.package_version}: " 

55 f"{self.title}" 

56 )