Coverage for lintro / parsers / bandit / bandit_issue.py: 100%
21 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"""Bandit issue model for security vulnerabilities."""
3from dataclasses import dataclass, field
4from typing import Any, ClassVar
6from lintro.parsers.base_issue import BaseIssue
9@dataclass
10class BanditIssue(BaseIssue):
11 """Represents a security issue found by Bandit.
13 Attributes:
14 DISPLAY_FIELD_MAP: Mapping of display field names to attribute names.
15 col_offset: int: Column offset of the issue.
16 issue_severity: str: Severity level (LOW, MEDIUM, HIGH).
17 issue_confidence: str: Confidence level (LOW, MEDIUM, HIGH).
18 test_id: str: Bandit test ID (e.g., B602, B301).
19 test_name: str: Name of the test that found the issue.
20 issue_text: str: Description of the security issue.
21 more_info: str: URL with more information about the issue.
22 cwe: dict[str, Any] | None: CWE (Common Weakness Enumeration) information.
23 code_snippet: str: Code snippet containing the issue.
24 line_range: list[int]: Range of lines containing the issue.
25 """
27 DISPLAY_FIELD_MAP: ClassVar[dict[str, str]] = {
28 **BaseIssue.DISPLAY_FIELD_MAP,
29 "code": "test_id",
30 "message": "issue_text",
31 "severity": "issue_severity",
32 }
34 col_offset: int = field(default=0)
35 issue_severity: str = field(default="UNKNOWN")
36 issue_confidence: str = field(default="UNKNOWN")
37 test_id: str = field(default="")
38 test_name: str = field(default="")
39 issue_text: str = field(default="")
40 more_info: str = field(default="")
41 cwe: dict[str, Any] | None = field(default=None)
42 code_snippet: str | None = field(default=None)
43 line_range: list[int] | None = field(default=None)
45 def __post_init__(self) -> None:
46 """Initialize the inherited fields."""
47 # Map col_offset to column for BaseIssue compatibility
48 self.column = self.col_offset
49 # Set the message field to the computed value for general use
50 self.message = self._get_message()
52 def _get_message(self) -> str:
53 """Get the formatted issue message.
55 Returns:
56 str: Formatted issue message.
57 """
58 return (
59 f"[{self.test_id}:{self.test_name}] {self.issue_severity} severity, "
60 f"{self.issue_confidence} confidence: {self.issue_text}"
61 )