Coverage for lintro / parsers / gitleaks / gitleaks_issue.py: 100%
29 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"""Gitleaks issue model for secret detection findings."""
3from __future__ import annotations
5from dataclasses import dataclass, field
6from typing import ClassVar
8from lintro.enums.severity_level import SeverityLevel
9from lintro.parsers.base_issue import BaseIssue
12@dataclass
13class GitleaksIssue(BaseIssue):
14 """Represents a secret detection finding from Gitleaks.
16 Attributes:
17 DISPLAY_FIELD_MAP: Mapping of display field names to attribute names.
18 DEFAULT_SEVERITY: Defaults to ERROR (security tool).
19 rule_id: The rule ID that triggered the detection (e.g., aws-access-key-id).
20 description: Description of the secret type detected.
21 secret: The detected secret value (should be redacted for display).
22 entropy: Shannon entropy of the detected secret.
23 tags: List of tags associated with the rule.
24 fingerprint: Unique identifier for this finding.
25 end_line: End line number of the finding.
26 end_column: End column number of the finding.
27 match: The matched pattern string.
28 commit: Git commit hash if scanning git history.
29 author: Git author if scanning git history.
30 email: Git author email if scanning git history.
31 date: Git commit date if scanning git history.
32 commit_message: Git commit message if scanning git history.
33 """
35 DISPLAY_FIELD_MAP: ClassVar[dict[str, str]] = {
36 **BaseIssue.DISPLAY_FIELD_MAP,
37 "code": "rule_id",
38 # message uses the computed value from __post_init__ (default mapping)
39 }
41 DEFAULT_SEVERITY: ClassVar[SeverityLevel] = SeverityLevel.ERROR
43 rule_id: str = field(default="")
44 description: str = field(default="")
45 secret: str = field(default="")
46 entropy: float = field(default=0.0)
47 tags: list[str] = field(default_factory=list)
48 fingerprint: str = field(default="")
49 end_line: int = field(default=0)
50 end_column: int = field(default=0)
51 match: str = field(default="")
52 commit: str = field(default="")
53 author: str = field(default="")
54 email: str = field(default="")
55 date: str = field(default="")
56 commit_message: str = field(default="")
58 def __post_init__(self) -> None:
59 """Initialize the inherited message field."""
60 self.message = self._get_message()
62 def _get_message(self) -> str:
63 """Get the formatted issue message.
65 Returns:
66 Formatted issue message with redacted secret.
67 """
68 redacted_hint = "[REDACTED]" if self.secret else ""
69 parts = [
70 f"[{self.rule_id}]" if self.rule_id else "",
71 self.description,
72 redacted_hint,
73 ]
74 return " ".join(part for part in parts if part)