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
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Issue model for cargo-audit output."""
3from dataclasses import dataclass, field
4from typing import ClassVar
6from lintro.parsers.base_issue import BaseIssue
9@dataclass
10class CargoAuditIssue(BaseIssue):
11 """Represents a security vulnerability found by cargo-audit.
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 """
24 DISPLAY_FIELD_MAP: ClassVar[dict[str, str]] = {
25 **BaseIssue.DISPLAY_FIELD_MAP,
26 "code": "advisory_id",
27 "severity": "severity",
28 "message": "message",
29 }
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="")
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()
47 def _get_message(self) -> str:
48 """Get the formatted issue message.
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 )