Coverage for src/alprina_cli/main_agent.py: 0%
249 statements
« prev ^ index » next coverage.py v7.11.3, created at 2025-11-14 11:27 +0100
« prev ^ index » next coverage.py v7.11.3, created at 2025-11-14 11:27 +0100
1"""
2Main Alprina Agent - The orchestrator that users interact with.
4The Main Agent is aware of all specialized security agents and routes tasks accordingly.
5Users talk to the Main Agent via CLI, which then coordinates with specialized agents.
7Architecture:
8User → CLI → Main Alprina Agent → Security Agents (CodeAgent, Web Scanner, etc.)
9"""
11from typing import Dict, Any, List, Optional
12from loguru import logger
13from datetime import datetime
15from .llm_provider import get_llm_client
16from .security_engine import (
17 run_agent,
18 run_local_scan,
19 run_remote_scan,
20 AGENTS_AVAILABLE
21)
22from .report_generator import generate_security_reports
23from .workflows import (
24 AlprinaWorkflow,
25 WorkflowType,
26 evaluate_scan_quality,
27 evaluate_comprehensive_scan
28)
29from .agent_coordinator import (
30 AgentCoordinator,
31 ChainType,
32 VulnerabilityState,
33 get_coordinator
34)
35import asyncio
38class MainAlprinaAgent:
39 """
40 Main Alprina Agent - The orchestrator that coordinates all security operations.
42 This is the primary agent users interact with. It has knowledge of all specialized
43 security agents and routes tasks to the appropriate agent.
44 """
46 # Registry of all available security agents
47 SECURITY_AGENTS = {
48 "codeagent": {
49 "name": "CodeAgent",
50 "task_type": "code-audit",
51 "description": "Static Application Security Testing (SAST)",
52 "capabilities": [
53 "SQL injection detection",
54 "XSS (Cross-Site Scripting) detection",
55 "CSRF vulnerability detection",
56 "Authentication and authorization flaws",
57 "Hardcoded secrets and credentials",
58 "Insecure cryptography",
59 "Input validation issues",
60 "Dependency vulnerability scanning"
61 ],
62 "languages": ["Python", "JavaScript", "TypeScript", "Java", "Go", "PHP", "Ruby", "Rust", "C/C++", "C#"],
63 "use_cases": [
64 "Scan source code files",
65 "Find hardcoded secrets",
66 "Detect code vulnerabilities",
67 "Audit dependencies"
68 ]
69 },
70 "web_scanner": {
71 "name": "Web Scanner Agent",
72 "task_type": "web-recon",
73 "description": "Web application and API security testing",
74 "capabilities": [
75 "API endpoint security testing",
76 "Authentication bypass detection",
77 "Rate limiting analysis",
78 "CORS misconfiguration detection",
79 "Session management vulnerabilities",
80 "HTTP security headers validation",
81 "SSL/TLS configuration testing"
82 ],
83 "use_cases": [
84 "Scan web applications",
85 "Test API endpoints",
86 "Analyze authentication flows",
87 "Check security headers"
88 ]
89 },
90 "bug_bounty": {
91 "name": "Bug Bounty Agent",
92 "task_type": "vuln-scan",
93 "description": "OWASP Top 10 and business logic vulnerability detection",
94 "capabilities": [
95 "OWASP Top 10 vulnerability detection",
96 "Business logic flaws",
97 "Authorization issues",
98 "Information disclosure",
99 "Server misconfigurations",
100 "Insecure deserialization",
101 "XXE (XML External Entities)",
102 "Path traversal"
103 ],
104 "use_cases": [
105 "Comprehensive vulnerability scanning",
106 "Business logic testing",
107 "Authorization testing",
108 "OWASP compliance checks"
109 ]
110 },
111 "secret_detection": {
112 "name": "Secret Detection Agent",
113 "task_type": "secret-detection",
114 "description": "Credential and secret scanning",
115 "capabilities": [
116 "API keys detection",
117 "Passwords and tokens",
118 "AWS/Cloud credentials",
119 "Database connection strings",
120 "Private keys and certificates",
121 "OAuth tokens",
122 "GitHub/GitLab tokens",
123 "Slack tokens",
124 "Entropy-based analysis"
125 ],
126 "use_cases": [
127 "Find hardcoded secrets",
128 "Scan for exposed credentials",
129 "Detect API keys in code",
130 "Check for password leaks"
131 ]
132 },
133 "config_audit": {
134 "name": "Config Audit Agent",
135 "task_type": "config-audit",
136 "description": "Infrastructure and configuration security",
137 "capabilities": [
138 "Docker security configuration",
139 "Kubernetes manifest auditing",
140 "CI/CD pipeline security",
141 "Environment variable exposure",
142 "Cloud infrastructure misconfigurations",
143 "Terraform/IaC security",
144 "Container security"
145 ],
146 "use_cases": [
147 "Audit Docker configurations",
148 "Scan Kubernetes manifests",
149 "Check CI/CD security",
150 "Review infrastructure as code"
151 ]
152 },
153 # Priority 1: High-Value Security Agents
154 "red_teamer": {
155 "name": "Red Team Agent",
156 "task_type": "offensive-security",
157 "description": "Offensive security testing and attack simulation",
158 "capabilities": [
159 "Attack simulation",
160 "Exploitation techniques",
161 "Penetration testing",
162 "Security bypass detection",
163 "Attack vector identification",
164 "Offensive reconnaissance"
165 ],
166 "use_cases": [
167 "Simulate attacks on applications",
168 "Test defensive measures",
169 "Identify attack vectors",
170 "Validate security controls"
171 ]
172 },
173 "blue_teamer": {
174 "name": "Blue Team Agent",
175 "task_type": "defensive-security",
176 "description": "Defensive security posture assessment",
177 "capabilities": [
178 "Security monitoring",
179 "Defense validation",
180 "Threat detection",
181 "Incident response",
182 "Security control assessment",
183 "Gap analysis"
184 ],
185 "use_cases": [
186 "Assess defensive security posture",
187 "Validate security controls",
188 "Identify defense gaps",
189 "Monitor for threats"
190 ]
191 },
192 "network_analyzer": {
193 "name": "Network Traffic Analyzer",
194 "task_type": "network-analysis",
195 "description": "Network packet and traffic pattern analysis",
196 "capabilities": [
197 "Packet inspection",
198 "Traffic pattern analysis",
199 "Protocol security analysis",
200 "Network anomaly detection",
201 "Unencrypted traffic detection",
202 "Suspicious connection identification"
203 ],
204 "use_cases": [
205 "Analyze network traffic",
206 "Inspect API communications",
207 "Detect suspicious connections",
208 "Validate encryption usage"
209 ]
210 },
211 "reverse_engineer": {
212 "name": "Reverse Engineering Agent",
213 "task_type": "binary-analysis",
214 "description": "Binary analysis and reverse engineering",
215 "capabilities": [
216 "Binary decompilation",
217 "Malware analysis",
218 "Executable security analysis",
219 "Code obfuscation detection",
220 "Backdoor detection",
221 "Suspicious function analysis"
222 ],
223 "use_cases": [
224 "Analyze binary executables",
225 "Reverse engineer compiled code",
226 "Detect malware and backdoors",
227 "Examine obfuscated code"
228 ]
229 },
230 "dfir": {
231 "name": "DFIR Agent",
232 "task_type": "forensics",
233 "description": "Digital forensics and incident response",
234 "capabilities": [
235 "Forensic analysis",
236 "Incident investigation",
237 "Evidence collection",
238 "Timeline reconstruction",
239 "Post-breach analysis",
240 "Log analysis"
241 ],
242 "use_cases": [
243 "Investigate security incidents",
244 "Perform forensic analysis",
245 "Collect incident evidence",
246 "Reconstruct attack timelines"
247 ]
248 },
249 # Priority 2: Specialized Security Agents
250 "android_sast": {
251 "name": "Android SAST Agent",
252 "task_type": "android-scan",
253 "description": "Android application security testing",
254 "capabilities": [
255 "Android permission analysis",
256 "Mobile app vulnerability scanning",
257 "Intent security analysis",
258 "Data storage security",
259 "Network security in mobile apps"
260 ],
261 "use_cases": [
262 "Scan Android applications",
263 "Audit mobile app security",
264 "Check Android permissions",
265 "Analyze mobile data storage"
266 ]
267 },
268 "memory_analysis": {
269 "name": "Memory Analysis Agent",
270 "task_type": "memory-forensics",
271 "description": "Memory forensics and analysis",
272 "capabilities": [
273 "Memory dump analysis",
274 "Process memory inspection",
275 "Memory anomaly detection",
276 "Malware memory artifacts",
277 "Credential extraction from memory"
278 ],
279 "use_cases": [
280 "Analyze memory dumps",
281 "Investigate memory-based attacks",
282 "Extract forensic evidence",
283 "Detect memory anomalies"
284 ]
285 },
286 "wifi_security": {
287 "name": "WiFi Security Tester",
288 "task_type": "wifi-test",
289 "description": "Wireless network security testing",
290 "capabilities": [
291 "WiFi encryption analysis",
292 "Wireless network scanning",
293 "Access point security assessment",
294 "Rogue AP detection",
295 "Weak encryption identification"
296 ],
297 "use_cases": [
298 "Test WiFi security",
299 "Audit wireless networks",
300 "Detect weak encryption",
301 "Identify rogue access points"
302 ]
303 },
304 "replay_attack": {
305 "name": "Replay Attack Agent",
306 "task_type": "replay-check",
307 "description": "Replay attack detection and prevention",
308 "capabilities": [
309 "Session token analysis",
310 "Timestamp validation checking",
311 "Nonce implementation review",
312 "Replay vulnerability detection",
313 "Authentication token security"
314 ],
315 "use_cases": [
316 "Check for replay vulnerabilities",
317 "Validate session security",
318 "Audit token mechanisms",
319 "Test authentication flows"
320 ]
321 },
322 "subghz_sdr": {
323 "name": "Sub-GHz SDR Agent",
324 "task_type": "radio-security",
325 "description": "Software Defined Radio security testing",
326 "capabilities": [
327 "RF signal analysis",
328 "Radio frequency security",
329 "Wireless protocol analysis",
330 "Unencrypted transmission detection",
331 "IoT radio security"
332 ],
333 "use_cases": [
334 "Analyze radio frequency security",
335 "Test IoT device communications",
336 "Audit wireless protocols",
337 "Detect unencrypted RF transmissions"
338 ]
339 },
340 # Priority 3: Utility & Support Agents
341 "retester": {
342 "name": "Retester Agent",
343 "task_type": "retest",
344 "description": "Re-testing previously found vulnerabilities",
345 "capabilities": [
346 "Vulnerability retesting",
347 "Fix validation",
348 "Regression testing",
349 "Historical vulnerability tracking",
350 "Remediation verification"
351 ],
352 "use_cases": [
353 "Retest fixed vulnerabilities",
354 "Validate security patches",
355 "Verify remediation efforts",
356 "Track vulnerability lifecycle"
357 ]
358 },
359 "mail": {
360 "name": "Mail Agent",
361 "task_type": "email-report",
362 "description": "Email notifications for security findings",
363 "capabilities": [
364 "Email report generation",
365 "Team notifications",
366 "Alert distribution",
367 "Scheduled report delivery",
368 "Custom email templates"
369 ],
370 "use_cases": [
371 "Email security reports",
372 "Send alert notifications",
373 "Distribute findings to team",
374 "Schedule automated reports"
375 ]
376 },
377 "guardrails": {
378 "name": "Guardrails Agent",
379 "task_type": "safety-check",
380 "description": "Safety validation before executing scans",
381 "capabilities": [
382 "Pre-scan safety checks",
383 "Destructive operation detection",
384 "Resource usage validation",
385 "Permission verification",
386 "Risk assessment"
387 ],
388 "use_cases": [
389 "Validate scan safety",
390 "Prevent destructive operations",
391 "Check resource limits",
392 "Assess operation risks"
393 ]
394 }
395 }
397 def __init__(self, model: str = "claude-3-5-sonnet-20241022"):
398 """
399 Initialize the Main Alprina Agent.
401 Args:
402 model: LLM model to use for natural language understanding
403 """
404 self.model = model
405 self.llm = get_llm_client(model=model)
406 self.conversation_history = []
408 logger.info("Main Alprina Agent initialized with FULL CAI agent coverage")
409 logger.info(f"Available security agents: {len(self.SECURITY_AGENTS)} (5 core + 13 specialized)")
411 def process_user_request(self, user_message: str, context: Optional[Dict] = None) -> Dict[str, Any]:
412 """
413 Process user request and route to appropriate security agents.
415 This is the main entry point. The Main Agent:
416 1. Understands user's natural language request
417 2. Determines which security agent(s) to use
418 3. Coordinates execution with specialized agents (using workflows)
419 4. Aggregates and returns results
421 Args:
422 user_message: Natural language request from user
423 context: Optional context (scan results, previous findings, etc.)
425 Returns:
426 Dictionary with response and any actions taken
427 """
428 logger.info(f"Main Agent processing: {user_message[:100]}...")
430 # Add to conversation history
431 self.conversation_history.append({
432 "role": "user",
433 "content": user_message,
434 "timestamp": datetime.now().isoformat()
435 })
437 # Analyze user intent
438 intent = self._analyze_intent(user_message, context)
440 # Route to appropriate handler
441 if intent["type"] == "scan_request":
442 # Use async workflow for scan requests
443 response = asyncio.run(self._handle_scan_request_async(intent, user_message))
444 elif intent["type"] == "explain_vulnerability":
445 response = self._handle_explanation_request(intent, user_message)
446 elif intent["type"] == "get_remediation":
447 response = self._handle_remediation_request(intent, user_message)
448 elif intent["type"] == "general_question":
449 response = self._handle_general_question(intent, user_message)
450 elif intent["type"] == "list_capabilities":
451 response = self._handle_capabilities_request()
452 else:
453 response = self._handle_general_question(intent, user_message)
455 # Add response to history
456 self.conversation_history.append({
457 "role": "assistant",
458 "content": response.get("message", ""),
459 "timestamp": datetime.now().isoformat()
460 })
462 return response
464 def _analyze_intent(self, user_message: str, context: Optional[Dict]) -> Dict[str, Any]:
465 """
466 Analyze user's intent using LLM to determine which agent(s) to call.
468 Args:
469 user_message: User's natural language request
470 context: Optional context
472 Returns:
473 Intent analysis with agent routing information
474 """
475 # Build intent analysis prompt
476 prompt = f"""Analyze this user request and determine the intent:
478User: "{user_message}"
480Available Alprina Security Agents:
481{self._format_agents_for_llm()}
483Classify the intent as one of:
4841. "scan_request" - User wants to scan code/web/API
4852. "explain_vulnerability" - User wants explanation of a vulnerability
4863. "get_remediation" - User wants fix instructions
4874. "list_capabilities" - User asks what you can do / help
4885. "general_question" - Security question or advice
490For scan_request, identify:
491- Target (file path, directory, URL, or IP)
492- Which agent(s) to use (codeagent, web_scanner, bug_bounty, secret_detection, config_audit)
493- Scan type (code-audit, web-recon, vuln-scan, secret-detection, config-audit)
495Return JSON format:
496{{
497 "type": "scan_request|explain_vulnerability|get_remediation|list_capabilities|general_question",
498 "agent": "codeagent|web_scanner|bug_bounty|secret_detection|config_audit",
499 "target": "path/url if applicable",
500 "confidence": 0.0-1.0
501}}"""
503 try:
504 # Use LLM to analyze intent
505 response = self.llm.chat(
506 messages=[{"role": "user", "content": prompt}],
507 system_prompt="You are an intent classifier for Alprina security platform. Return only JSON.",
508 max_tokens=500,
509 temperature=0.3
510 )
512 # Parse LLM response
513 import json
514 intent = json.loads(response.strip().strip("```json").strip("```"))
515 return intent
517 except Exception as e:
518 logger.warning(f"Intent analysis failed: {e}, using fallback")
519 return self._fallback_intent_analysis(user_message)
521 def _fallback_intent_analysis(self, user_message: str) -> Dict[str, Any]:
522 """Fallback intent analysis using keyword matching."""
523 message_lower = user_message.lower()
525 # Scan request keywords
526 if any(word in message_lower for word in ["scan", "check", "analyze", "audit", "test"]):
527 # Determine target and agent
528 if any(word in message_lower for word in ["code", "file", "python", "javascript", ".py", ".js"]):
529 return {"type": "scan_request", "agent": "codeagent", "target": None, "confidence": 0.8}
530 elif any(word in message_lower for word in ["web", "api", "http", "url", "domain"]):
531 return {"type": "scan_request", "agent": "web_scanner", "target": None, "confidence": 0.8}
532 elif any(word in message_lower for word in ["secret", "key", "password", "token", "credential"]):
533 return {"type": "scan_request", "agent": "secret_detection", "target": None, "confidence": 0.8}
534 elif any(word in message_lower for word in ["docker", "kubernetes", "config", "k8s", "container"]):
535 return {"type": "scan_request", "agent": "config_audit", "target": None, "confidence": 0.8}
536 else:
537 return {"type": "scan_request", "agent": "codeagent", "target": None, "confidence": 0.6}
539 # Help/capabilities request
540 if any(word in message_lower for word in ["help", "what can you", "capabilities", "what do you"]):
541 return {"type": "list_capabilities", "confidence": 0.9}
543 # Explanation request
544 if any(word in message_lower for word in ["explain", "what is", "tell me about"]):
545 return {"type": "explain_vulnerability", "confidence": 0.7}
547 # Remediation request
548 if any(word in message_lower for word in ["fix", "remediate", "solve", "how to fix"]):
549 return {"type": "get_remediation", "confidence": 0.7}
551 # Default to general question
552 return {"type": "general_question", "confidence": 0.5}
554 async def _handle_scan_request_async(self, intent: Dict, user_message: str) -> Dict[str, Any]:
555 """
556 Handle scan requests using AI SDK workflow patterns.
558 Uses orchestrator-worker pattern with parallel execution and quality control.
560 Args:
561 intent: Intent analysis
562 user_message: Original user message
564 Returns:
565 Scan results and response
566 """
567 agent_id = intent.get("agent", "codeagent")
568 target = intent.get("target")
570 # Extract target from message if not in intent
571 if not target:
572 target = self._extract_target_from_message(user_message)
574 if not target:
575 return {
576 "message": "I'd be happy to run a scan! Could you tell me what you'd like to scan? For example:\n\n- `scan ./src` - Scan a directory\n- `scan app.py` - Scan a file\n- `scan https://api.example.com` - Scan a web endpoint\n- `find secrets in ./` - Search for hardcoded credentials",
577 "type": "clarification_needed"
578 }
580 # Get agent info
581 agent_info = self._get_agent_info(agent_id)
583 logger.info(f"Routing scan to {agent_info['name']} for target: {target} using WORKFLOW orchestration")
585 # Determine if local or remote scan
586 from pathlib import Path
587 is_local = Path(target).exists()
589 try:
590 # Check if this is a comprehensive scan (use multiple agents)
591 is_comprehensive = any(word in user_message.lower() for word in ["comprehensive", "full", "complete", "all agents"])
593 # Check if this is a deep analysis (use sequential workflow)
594 is_deep_analysis = any(word in user_message.lower() for word in ["deep", "thorough", "detailed", "in-depth", "sequential"])
596 # Check if this is a coordinated agent chain
597 is_chain = any(word in user_message.lower() for word in ["chain", "coordinate", "lifecycle", "attack defense", "investigation"])
599 if is_chain:
600 # Use agent coordinator for sophisticated multi-agent chains
601 logger.info("Using AGENT COORDINATOR for chain execution")
603 coordinator = get_coordinator()
605 # Detect chain type from keywords
606 if "attack" in user_message.lower() and "defense" in user_message.lower():
607 chain_type = ChainType.ATTACK_DEFENSE
608 elif "lifecycle" in user_message.lower() or "full" in user_message.lower():
609 chain_type = ChainType.FULL_LIFECYCLE
610 elif "investigation" in user_message.lower() or "forensic" in user_message.lower():
611 chain_type = ChainType.INVESTIGATION
612 elif "validation" in user_message.lower() or "retest" in user_message.lower():
613 chain_type = ChainType.VALIDATION
614 elif "continuous" in user_message.lower() or "monitor" in user_message.lower():
615 chain_type = ChainType.CONTINUOUS
616 else:
617 # Default to attack/defense
618 chain_type = ChainType.ATTACK_DEFENSE
620 # Execute coordinated chain
621 chain_results = await coordinator.execute_chain(
622 chain_type=chain_type,
623 target=target,
624 safe_only=True
625 )
627 results = {
628 "findings": chain_results.get("vulnerabilities", []),
629 "chain_type": chain_results.get("chain_type"),
630 "steps": chain_results.get("steps", []),
631 "total_steps": len(chain_results.get("steps", []))
632 }
634 agents_used = [step["agent"] for step in chain_results.get("steps", [])]
636 elif is_deep_analysis:
637 # Use sequential workflow for deep analysis with context passing
638 logger.info("Using SEQUENTIAL WORKFLOW for deep analysis")
640 workflow = AlprinaWorkflow(WorkflowType.SEQUENTIAL)
642 # Define sequential steps with context passing
643 steps = [
644 {
645 "agent": "codeagent",
646 "task": "code-audit",
647 "params": {"target": target, "safe_only": True}
648 },
649 {
650 "agent": "secret_detection",
651 "task": "secret-detection",
652 "params": {"target": target, "safe_only": True}
653 },
654 {
655 "agent": "main_alprina_agent",
656 "task": "aggregate_results",
657 "params": {"target": target}
658 }
659 ]
661 # Add web scanner if target is URL, otherwise config audit
662 if not is_local:
663 steps.insert(1, {
664 "agent": "web_scanner",
665 "task": "web-recon",
666 "params": {"target": target, "safe_only": True}
667 })
668 else:
669 steps.insert(1, {
670 "agent": "config_audit",
671 "task": "config-audit",
672 "params": {"target": target, "safe_only": True}
673 })
675 # Execute sequential workflow
676 workflow_result = await workflow.execute_sequential(steps)
678 # Extract results from sequential execution
679 all_findings = []
680 for step in workflow_result.steps:
681 step_findings = step.get("output", {}).get("findings", [])
682 all_findings.extend(step_findings)
684 results = {
685 "findings": all_findings,
686 "workflow_type": "sequential",
687 "steps_completed": len(workflow_result.steps)
688 }
690 agents_used = [step["agent"] for step in steps]
692 elif is_comprehensive:
693 # Use parallel workflow for comprehensive scans (2-3x faster!)
694 logger.info("Using PARALLEL WORKFLOW for comprehensive scan")
696 workflow = AlprinaWorkflow(WorkflowType.PARALLEL)
698 # Define tasks for all relevant agents
699 tasks = [
700 {"agent": "codeagent", "task": "code-audit", "params": {"target": target, "safe_only": True}},
701 {"agent": "secret_detection", "task": "secret-detection", "params": {"target": target, "safe_only": True}},
702 ]
704 # Add web scanner if target is URL
705 if not is_local:
706 tasks.append({"agent": "web_scanner", "task": "web-recon", "params": {"target": target, "safe_only": True}})
707 else:
708 # Add config audit for local scans
709 tasks.append({"agent": "config_audit", "task": "config-audit", "params": {"target": target, "safe_only": True}})
711 # Execute all agents in parallel
712 workflow_result = await workflow.execute_parallel(tasks)
714 # Add quality control with evaluator-optimizer
715 logger.info("Applying QUALITY CONTROL with evaluator-optimizer")
716 quality_workflow = AlprinaWorkflow(WorkflowType.EVALUATOR_OPTIMIZER)
718 refined_result = await quality_workflow.execute_evaluator_optimizer(
719 agent="main_alprina_agent",
720 task="aggregate_results",
721 params={"workflow_result": workflow_result.final_output},
722 evaluator_fn=evaluate_comprehensive_scan,
723 max_iterations=2
724 )
726 # Aggregate results from all agents
727 results = self._aggregate_parallel_results(workflow_result.final_output)
728 agents_used = [task["agent"] for task in tasks]
730 else:
731 # Single agent scan with quality control
732 logger.info(f"Using SINGLE AGENT WORKFLOW with quality control: {agent_info['name']}")
734 # Use evaluator-optimizer workflow for quality
735 workflow = AlprinaWorkflow(WorkflowType.EVALUATOR_OPTIMIZER)
737 workflow_result = await workflow.execute_evaluator_optimizer(
738 agent=agent_id,
739 task=agent_info["task_type"],
740 params={"target": target, "safe_only": True},
741 evaluator_fn=evaluate_scan_quality,
742 max_iterations=3
743 )
745 results = workflow_result.final_output
746 agents_used = [agent_info["name"]]
748 # Generate markdown reports if local scan with findings
749 report_path = None
750 if is_local and results.get("findings"):
751 try:
752 report_path = generate_security_reports(results, target)
753 except Exception as e:
754 logger.warning(f"Report generation failed: {e}")
756 # Format response
757 findings_count = len(results.get("findings", []))
759 if is_chain:
760 chain_name = results.get("chain_type", "agent chain").replace("_", " ").title()
761 message = f"✓ **{chain_name} complete** using {len(agents_used)} coordinated agents!\n\n"
762 message += f"**Workflow:** Agent Coordination Chain\n"
763 message += f"**Chain Steps:** {results.get('total_steps', 0)}\n"
764 elif is_deep_analysis:
765 message = f"✓ **Deep analysis complete** using {len(agents_used)} agents sequentially with context passing!\n\n"
766 message += f"**Workflow:** Sequential (each agent builds on previous results)\n"
767 elif is_comprehensive:
768 message = f"✓ **Comprehensive scan complete** using {len(agents_used)} agents in parallel!\n\n"
769 else:
770 message = f"✓ Scan complete using **{agent_info['name']}** with quality control!\n\n"
772 message += f"**Target:** `{target}`\n"
773 message += f"**Findings:** {findings_count} security issues detected\n"
775 if findings_count > 0:
776 # Summarize by severity
777 severity_counts = {}
778 for finding in results["findings"]:
779 sev = finding.get("severity", "UNKNOWN")
780 severity_counts[sev] = severity_counts.get(sev, 0) + 1
782 message += "\n**Severity Breakdown:**\n"
783 for severity in ["CRITICAL", "HIGH", "MEDIUM", "LOW", "INFO"]:
784 count = severity_counts.get(severity, 0)
785 if count > 0:
786 icons = {"CRITICAL": "🔴", "HIGH": "🟠", "MEDIUM": "🟡", "LOW": "🔵", "INFO": "⚪"}
787 message += f" {icons.get(severity, '•')} {severity}: {count}\n"
789 if report_path:
790 message += f"\n📁 **Security reports generated:** `{report_path}/`\n"
791 message += " • SECURITY-REPORT.md\n"
792 message += " • FINDINGS.md\n"
793 message += " • REMEDIATION.md\n"
794 message += " • EXECUTIVE-SUMMARY.md\n"
795 else:
796 message += "\n✅ No security issues found! Your code looks good.\n"
798 message += f"\nNeed help fixing issues? Just ask: *\"How do I fix finding #1?\"*"
800 return {
801 "message": message,
802 "type": "scan_complete",
803 "results": results,
804 "agent_used": ", ".join(agents_used),
805 "report_path": report_path,
806 "workflow_enabled": True
807 }
809 except Exception as e:
810 logger.error(f"Scan failed: {e}")
811 return {
812 "message": f"❌ Scan failed: {str(e)}\n\nPlease check the target path/URL and try again.",
813 "type": "error",
814 "error": str(e)
815 }
817 def _handle_explanation_request(self, intent: Dict, user_message: str) -> Dict[str, Any]:
818 """Handle vulnerability explanation requests."""
819 # Use LLM to generate explanation
820 prompt = f"""User is asking about security concepts or vulnerabilities: "{user_message}"
822Provide a clear, concise explanation covering:
8231. What it is (simple definition)
8242. Why it matters (risk/impact)
8253. Common examples
8264. How to prevent it
828Keep it educational but practical. Use analogies if helpful."""
830 try:
831 explanation = self.llm.chat(
832 messages=[{"role": "user", "content": prompt}],
833 system_prompt=self._get_system_prompt(),
834 max_tokens=1000,
835 temperature=0.7
836 )
838 return {
839 "message": explanation,
840 "type": "explanation"
841 }
842 except Exception as e:
843 logger.error(f"Explanation generation failed: {e}")
844 return {
845 "message": "I can explain security vulnerabilities! Try asking: 'What is SQL injection?' or 'Explain XSS attacks'",
846 "type": "error"
847 }
849 def _handle_remediation_request(self, intent: Dict, user_message: str) -> Dict[str, Any]:
850 """Handle remediation/fix requests."""
851 prompt = f"""User needs help fixing a security issue: "{user_message}"
853Provide step-by-step remediation instructions with:
8541. Code examples (vulnerable vs. secure)
8552. Best practices
8563. Testing/verification steps
858Be specific and actionable."""
860 try:
861 remediation = self.llm.chat(
862 messages=[{"role": "user", "content": prompt}],
863 system_prompt=self._get_system_prompt(),
864 max_tokens=1500,
865 temperature=0.7
866 )
868 return {
869 "message": remediation,
870 "type": "remediation"
871 }
872 except Exception as e:
873 logger.error(f"Remediation generation failed: {e}")
874 return {
875 "message": "I can help you fix security issues! Check the REMEDIATION.md file in your .alprina/ folder for detailed fix instructions.",
876 "type": "error"
877 }
879 def _handle_general_question(self, intent: Dict, user_message: str) -> Dict[str, Any]:
880 """Handle general security questions."""
881 try:
882 response = self.llm.chat(
883 messages=[{"role": "user", "content": user_message}],
884 system_prompt=self._get_system_prompt(),
885 max_tokens=1000,
886 temperature=0.7
887 )
889 return {
890 "message": response,
891 "type": "general"
892 }
893 except Exception as e:
894 logger.error(f"Question handling failed: {e}")
895 return {
896 "message": "I'm here to help with security! Ask me to scan code, explain vulnerabilities, or provide security advice.",
897 "type": "error"
898 }
900 def _handle_capabilities_request(self) -> Dict[str, Any]:
901 """Handle 'What can you do?' requests."""
902 message = """# 👋 Hey! I'm Alprina, your AI security assistant.
904I coordinate with **5 specialized security agents** to help you find and fix vulnerabilities:
906## 🔍 What I Can Do:
908### 1️⃣ **Scan Your Code**
909- "Scan ./src for vulnerabilities"
910- "Check app.py for security issues"
911- "Find hardcoded secrets in my project"
913**Agents:** CodeAgent, Secret Detection Agent
915### 2️⃣ **Test Web Applications & APIs**
916- "Scan https://api.myapp.com"
917- "Check my website for vulnerabilities"
918- "Test my API endpoints"
920**Agent:** Web Scanner Agent
922### 3️⃣ **Comprehensive Security Audits**
923- "Run full security scan on ./project"
924- "Find OWASP Top 10 vulnerabilities"
925- "Check for business logic flaws"
927**Agent:** Bug Bounty Agent
929### 4️⃣ **Audit Infrastructure**
930- "Check my Dockerfile security"
931- "Audit Kubernetes manifests"
932- "Review CI/CD pipeline security"
934**Agent:** Config Audit Agent
936### 5️⃣ **Explain & Fix**
937- "What is SQL injection?"
938- "How do I fix XSS vulnerabilities?"
939- "Explain finding #3"
941## 📁 Automatic Reports
943Every scan generates professional markdown reports in `.alprina/`:
944- SECURITY-REPORT.md
945- FINDINGS.md
946- REMEDIATION.md
947- EXECUTIVE-SUMMARY.md
949## 💬 Just Talk to Me!
951You don't need to memorize commands. Just tell me what you need:
952- "I want to check my code for vulnerabilities"
953- "Help me secure my API"
954- "Find any exposed credentials"
956**Ready to get started?** Try: `scan ./src`
957"""
959 return {
960 "message": message,
961 "type": "capabilities"
962 }
964 def _aggregate_parallel_results(self, parallel_outputs: List[Any]) -> Dict[str, Any]:
965 """
966 Aggregate results from multiple agents running in parallel.
968 Args:
969 parallel_outputs: List of outputs from parallel workflow execution
971 Returns:
972 Aggregated results dictionary
973 """
974 aggregated = {
975 "findings": [],
976 "stats": {
977 "total_agents": len(parallel_outputs),
978 "total_findings": 0,
979 "by_severity": {}
980 }
981 }
983 # Combine findings from all agents
984 for output in parallel_outputs:
985 if isinstance(output, dict) and "findings" in output:
986 aggregated["findings"].extend(output["findings"])
988 # Deduplicate findings based on file + line + type
989 seen = set()
990 unique_findings = []
991 for finding in aggregated["findings"]:
992 key = (
993 finding.get("file", ""),
994 finding.get("line", 0),
995 finding.get("type", ""),
996 finding.get("message", "")
997 )
998 if key not in seen:
999 seen.add(key)
1000 unique_findings.append(finding)
1002 aggregated["findings"] = unique_findings
1003 aggregated["stats"]["total_findings"] = len(unique_findings)
1005 # Count by severity
1006 for finding in unique_findings:
1007 severity = finding.get("severity", "UNKNOWN")
1008 aggregated["stats"]["by_severity"][severity] = aggregated["stats"]["by_severity"].get(severity, 0) + 1
1010 return aggregated
1012 def _extract_target_from_message(self, message: str) -> Optional[str]:
1013 """Extract scan target from natural language message."""
1014 import re
1016 # Look for file paths
1017 path_pattern = r'[./~][\w/.-]+'
1018 paths = re.findall(path_pattern, message)
1019 if paths:
1020 return paths[0]
1022 # Look for URLs
1023 url_pattern = r'https?://[\w.-]+(?:/[\w.-]*)?'
1024 urls = re.findall(url_pattern, message)
1025 if urls:
1026 return urls[0]
1028 # Look for IP addresses
1029 ip_pattern = r'\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b'
1030 ips = re.findall(ip_pattern, message)
1031 if ips:
1032 return ips[0]
1034 return None
1036 def _get_agent_info(self, agent_id: str) -> Dict[str, Any]:
1037 """Get information about a security agent."""
1038 # Map agent IDs to registry keys
1039 agent_map = {
1040 "codeagent": "codeagent",
1041 "web_scanner": "web_scanner",
1042 "bug_bounty": "bug_bounty",
1043 "secret_detection": "secret_detection",
1044 "config_audit": "config_audit"
1045 }
1047 registry_key = agent_map.get(agent_id, "codeagent")
1048 return self.SECURITY_AGENTS[registry_key]
1050 def _format_agents_for_llm(self) -> str:
1051 """Format agent registry for LLM consumption."""
1052 output = ""
1053 for agent_id, agent in self.SECURITY_AGENTS.items():
1054 output += f"\n**{agent['name']}** ({agent_id}):\n"
1055 output += f" Task: {agent['task_type']}\n"
1056 output += f" Use for: {', '.join(agent['use_cases'][:2])}\n"
1057 return output
1059 def _get_system_prompt(self) -> str:
1060 """Get system prompt for the Main Alprina Agent."""
1061 return f"""You are the Main Alprina Agent - the primary AI security assistant that users interact with.
1063You coordinate with {len(self.SECURITY_AGENTS)} specialized security agents:
1065{self._format_agents_for_llm()}
1067## Your Role:
1068- Understand user requests in natural language
1069- Route tasks to appropriate security agents
1070- Provide security advice and education
1071- Generate clear, actionable responses
1073## Communication Style:
1074- Friendly and conversational
1075- Explain security concepts simply
1076- Provide code examples when helpful
1077- Always offer next steps
1079## Remember:
1080- Users talk to YOU (Main Agent)
1081- YOU decide which specialized agent to use
1082- YOU coordinate all security operations
1083- YOU present results in user-friendly format
1085Be helpful, educational, and proactive in making security accessible to all developers!"""
1087 def get_agent_registry(self) -> Dict[str, Any]:
1088 """
1089 Get the complete registry of all security agents.
1091 Returns:
1092 Dictionary of all available security agents
1093 """
1094 return self.SECURITY_AGENTS
1096 def list_agents(self) -> List[Dict[str, Any]]:
1097 """
1098 Get a list of all available security agents.
1100 Returns:
1101 List of agent information dictionaries
1102 """
1103 agents_list = []
1104 for agent_id, agent_info in self.SECURITY_AGENTS.items():
1105 agents_list.append({
1106 "id": agent_id,
1107 "name": agent_info["name"],
1108 "description": agent_info["description"],
1109 "capabilities": agent_info["capabilities"],
1110 "use_cases": agent_info["use_cases"]
1111 })
1112 return agents_list