Coverage for src/alprina_cli/mitigation.py: 0%

58 statements  

« prev     ^ index     » next       coverage.py v7.11.3, created at 2025-11-14 11:27 +0100

1""" 

2Mitigation suggestion module for Alprina CLI. 

3Provides AI-powered remediation guidance for security findings. 

4""" 

5 

6from pathlib import Path 

7from typing import Optional 

8from rich.console import Console 

9from rich.panel import Panel 

10from rich.markdown import Markdown 

11 

12from .reporting import load_events 

13from .security_engine import run_agent 

14 

15console = Console() 

16 

17 

18def mitigate_command(finding_id: Optional[str] = None, report_file: Optional[Path] = None): 

19 """ 

20 Provide AI-powered mitigation suggestions for security findings. 

21 

22 Args: 

23 finding_id: Specific finding ID to get mitigation for 

24 report_file: Path to report file to analyze 

25 """ 

26 console.print(Panel("🛠️ Generating mitigation suggestions...", title="Alprina Mitigation")) 

27 

28 # Load findings 

29 if report_file: 

30 findings = _load_findings_from_report(report_file) 

31 else: 

32 findings = _load_findings_from_events() 

33 

34 if not findings: 

35 console.print("[yellow]No findings to mitigate[/yellow]") 

36 return 

37 

38 # Filter to specific finding if requested 

39 if finding_id: 

40 findings = [f for f in findings if f.get("id") == finding_id] 

41 if not findings: 

42 console.print(f"[red]Finding {finding_id} not found[/red]") 

43 return 

44 

45 # Generate mitigations for each finding 

46 for i, finding in enumerate(findings, 1): 

47 console.print(f"\n[bold cyan]Finding {i}/{len(findings)}[/bold cyan]") 

48 _generate_mitigation(finding) 

49 

50 

51def _load_findings_from_events() -> list: 

52 """Load findings from event log.""" 

53 events = load_events() 

54 findings = [] 

55 

56 for event in events: 

57 if event.get("type") in ["scan", "recon"]: 

58 event_findings = event.get("findings", []) 

59 if isinstance(event_findings, list): 

60 findings.extend(event_findings) 

61 

62 return findings 

63 

64 

65def _load_findings_from_report(report_path: Path) -> list: 

66 """Load findings from a report file.""" 

67 import json 

68 

69 try: 

70 with open(report_path, "r") as f: 

71 report = json.load(f) 

72 return report.get("findings", []) 

73 except Exception as e: 

74 console.print(f"[red]Error loading report: {e}[/red]") 

75 return [] 

76 

77 

78def _generate_mitigation(finding: dict): 

79 """ 

80 Generate AI-powered mitigation suggestion for a single finding. 

81 

82 Args: 

83 finding: Finding dictionary with severity, type, description, location 

84 """ 

85 # Display finding info 

86 console.print(Panel( 

87 f"[bold]Severity:[/bold] {finding.get('severity', 'UNKNOWN')}\n" 

88 f"[bold]Type:[/bold] {finding.get('type', 'Unknown')}\n" 

89 f"[bold]Description:[/bold] {finding.get('description', 'N/A')}\n" 

90 f"[bold]Location:[/bold] {finding.get('location', 'N/A')}", 

91 title="Finding Details" 

92 )) 

93 

94 # Use Alprina security agent to generate mitigation 

95 mitigation_prompt = f""" 

96 Security Finding: 

97 - Severity: {finding.get('severity')} 

98 - Type: {finding.get('type')} 

99 - Description: {finding.get('description')} 

100 - Location: {finding.get('location')} 

101 

102 Provide: 

103 1. Risk explanation 

104 2. Step-by-step mitigation instructions 

105 3. Code examples if applicable 

106 4. Prevention best practices 

107 """ 

108 

109 try: 

110 result = run_agent( 

111 task="mitigation", 

112 input_data=mitigation_prompt, 

113 metadata=finding 

114 ) 

115 

116 mitigation_text = result.get("mitigation", "No specific mitigation available") 

117 

118 # Display mitigation as markdown 

119 console.print("\n[bold green]Mitigation Guidance:[/bold green]") 

120 console.print(Markdown(mitigation_text)) 

121 

122 except Exception as e: 

123 console.print(f"[red]Error generating mitigation: {e}[/red]") 

124 

125 # Provide fallback generic guidance 

126 _provide_generic_mitigation(finding) 

127 

128 

129def _provide_generic_mitigation(finding: dict): 

130 """Provide generic mitigation guidance based on finding type.""" 

131 finding_type = finding.get("type", "").lower() 

132 

133 generic_mitigations = { 

134 "hardcoded secret": """ 

135 ### Mitigation Steps: 

136 1. **Remove** the hardcoded secret from the code immediately 

137 2. **Rotate** the exposed credentials/keys 

138 3. **Use environment variables** or a secrets manager (e.g., AWS Secrets Manager, HashiCorp Vault) 

139 4. **Add** sensitive files to `.gitignore` 

140 5. **Audit** git history to ensure secret is not in past commits 

141 

142 ### Prevention: 

143 - Use pre-commit hooks to scan for secrets 

144 - Implement automated secret scanning in CI/CD 

145 - Use tools like `git-secrets` or `trufflehog` 

146 """, 

147 

148 "debug mode": """ 

149 ### Mitigation Steps: 

150 1. **Disable** debug mode in production environments 

151 2. **Use** environment-based configuration (e.g., `DEBUG=False` in production) 

152 3. **Review** all debug-related settings 

153 

154 ### Prevention: 

155 - Use separate config files for dev/staging/production 

156 - Implement configuration validation in deployment pipeline 

157 """, 

158 

159 "environment file": """ 

160 ### Mitigation Steps: 

161 1. **Ensure** `.env` files are in `.gitignore` 

162 2. **Remove** `.env` from git history if committed 

163 3. **Use** `.env.example` template without actual secrets 

164 

165 ### Prevention: 

166 - Never commit `.env` files 

167 - Use environment-specific files (`.env.production`, `.env.development`) 

168 - Document required environment variables 

169 """, 

170 } 

171 

172 mitigation = generic_mitigations.get(finding_type, """ 

173 ### General Security Best Practices: 

174 1. Follow the principle of least privilege 

175 2. Keep dependencies up to date 

176 3. Implement proper input validation 

177 4. Use security linters and scanners 

178 5. Conduct regular security audits 

179 """) 

180 

181 console.print(Markdown(mitigation))