Skip to main content
Glama
formatters.py9.32 kB
"""Format output for optimal LLM comprehension.""" import logging from typing import Optional from ..models import ASVSRequirement, FixSuggestion, ScanResult, ScanSummary, SeverityLevel logger = logging.getLogger(__name__) def format_security_requirements( requirements: list[ASVSRequirement], context: Optional[str] = None, include_examples: bool = True, ) -> str: """ Format ASVS requirements in a clear, actionable way for LLMs. Args: requirements: List of ASVS requirements context: Optional context about why these requirements are relevant include_examples: Whether to include code examples Returns: Formatted string optimized for LLM consumption """ if not requirements: return "No relevant ASVS requirements found." # Sort by level (Level 1 first) then by ID sorted_reqs = sorted(requirements, key=lambda r: (r.level, r.id)) output = ["# OWASP ASVS Security Requirements\n"] if context: output.append(f"**Context:** {context}\n") output.append(f"**Total Requirements:** {len(requirements)}\n") # Group by level by_level: dict[int, list[ASVSRequirement]] = {} for req in sorted_reqs: if req.level not in by_level: by_level[req.level] = [] by_level[req.level].append(req) for level in sorted([1, 2, 3]): if level not in by_level: continue level_reqs = by_level[level] output.append(f"\n## Level {level} Requirements ({len(level_reqs)})") output.append( f"*Level {level}: {'Baseline security' if level == 1 else 'Standard security' if level == 2 else 'High security'}*\n" ) for req in level_reqs: output.append(f"### {req.id}: {req.category}") output.append(f"**Requirement:** {req.requirement}\n") if req.cwe: output.append(f"**CWE Mapping:** {req.cwe}") output.append(f"**Description:**") output.append(req.description) output.append(f"\n**Implementation Guide:**") output.append(req.implementation_guide) if include_examples and req.code_examples: output.append(f"\n**Code Examples:**") for i, example in enumerate(req.code_examples, 1): output.append(f"```") output.append(example.strip()) output.append(f"```") output.append("\n---\n") return "\n".join(output) def format_scan_results( results: list[ScanResult], show_all: bool = True, ) -> str: """ Format scan results with clear prioritization and actionable guidance. Args: results: List of scan results show_all: Whether to show all findings or only critical/high Returns: Formatted string optimized for LLM consumption """ if not results: return "✅ **SCAN PASSED**\n\nNo security vulnerabilities detected." # Generate summary summary = _generate_summary(results) output = [] # Executive summary if summary.passed: output.append("✅ **SCAN PASSED** (with informational findings)") else: output.append("❌ **SCAN FAILED**") output.append(f"\n**Total Findings:** {summary.total_findings}") if summary.critical > 0: output.append(f"- 🔴 **CRITICAL:** {summary.critical}") if summary.high > 0: output.append(f"- 🟠 **HIGH:** {summary.high}") if summary.medium > 0: output.append(f"- 🟡 **MEDIUM:** {summary.medium}") if summary.low > 0: output.append(f"- 🔵 **LOW:** {summary.low}") if summary.info > 0: output.append(f"- ⚪ **INFO:** {summary.info}") if summary.asvs_requirements_violated: output.append( f"\n**ASVS Requirements Violated:** {', '.join(summary.asvs_requirements_violated)}" ) output.append("\n---\n") # Sort by severity severity_order = { SeverityLevel.CRITICAL: 0, SeverityLevel.HIGH: 1, SeverityLevel.MEDIUM: 2, SeverityLevel.LOW: 3, SeverityLevel.INFO: 4, } sorted_results = sorted(results, key=lambda r: severity_order.get(r.severity, 5)) # Filter if needed if not show_all: sorted_results = [ r for r in sorted_results if r.severity in [SeverityLevel.CRITICAL, SeverityLevel.HIGH] ] # Detailed findings output.append("## Detailed Findings\n") for i, result in enumerate(sorted_results, 1): severity_icon = _get_severity_icon(result.severity) output.append(f"### {i}. {severity_icon} {result.vulnerability_type}") output.append(f"**Severity:** {result.severity.value}") if result.asvs_requirements: output.append(f"**ASVS Requirements:** {', '.join(result.asvs_requirements)}") output.append(f"\n**Issue:**") output.append(result.message) if result.location.filename: location_parts = [result.location.filename] if result.location.line: location_parts.append(f"line {result.location.line}") output.append(f"\n**Location:** {':'.join(location_parts)}") if result.location.code_snippet: output.append(f"\n**Vulnerable Code:**") output.append("```") output.append(result.location.code_snippet.strip()) output.append("```") if result.attack_vector: output.append(f"\n**Attack Vector:**") output.append(result.attack_vector) output.append(f"\n**Remediation:**") output.append(result.remediation) output.append(f"\n**Detected by:** {result.scanner}") output.append("\n---\n") return "\n".join(output) def format_fix_suggestion(fix: FixSuggestion) -> str: """ Format fix suggestion with side-by-side comparison. Args: fix: Fix suggestion Returns: Formatted string optimized for LLM consumption """ output = ["# Security Fix Suggestion\n"] if fix.asvs_requirements: output.append(f"**ASVS Requirements Addressed:** {', '.join(fix.asvs_requirements)}\n") output.append("## ❌ Vulnerable Code") output.append("```") output.append(fix.vulnerable_code.strip()) output.append("```\n") output.append("## ✅ Secure Code") output.append("```") output.append(fix.secure_code.strip()) output.append("```\n") output.append("## 📝 Explanation") output.append(fix.explanation) if fix.security_benefits: output.append("\n## 🛡️ Security Benefits") for benefit in fix.security_benefits: output.append(f"- {benefit}") if fix.additional_considerations: output.append("\n## ⚠️ Additional Considerations") output.append(fix.additional_considerations) return "\n".join(output) def _generate_summary(results: list[ScanResult]) -> ScanSummary: """Generate summary statistics from scan results.""" summary = ScanSummary( total_findings=len(results), critical=0, high=0, medium=0, low=0, info=0, asvs_requirements_violated=[], passed=True, ) asvs_set: set[str] = set() for result in results: # Count by severity if result.severity == SeverityLevel.CRITICAL: summary.critical += 1 summary.passed = False elif result.severity == SeverityLevel.HIGH: summary.high += 1 summary.passed = False elif result.severity == SeverityLevel.MEDIUM: summary.medium += 1 elif result.severity == SeverityLevel.LOW: summary.low += 1 elif result.severity == SeverityLevel.INFO: summary.info += 1 # Collect ASVS IDs asvs_set.update(result.asvs_requirements) summary.asvs_requirements_violated = sorted(asvs_set) return summary def _get_severity_icon(severity: SeverityLevel) -> str: """Get emoji icon for severity level.""" icons = { SeverityLevel.CRITICAL: "🔴", SeverityLevel.HIGH: "🟠", SeverityLevel.MEDIUM: "🟡", SeverityLevel.LOW: "🔵", SeverityLevel.INFO: "⚪", } return icons.get(severity, "⚫") def format_requirement_summary(requirements: list[ASVSRequirement]) -> str: """ Format a brief summary of requirements (for large lists). Args: requirements: List of ASVS requirements Returns: Brief summary string """ if not requirements: return "No requirements found." by_category: dict[str, int] = {} by_level: dict[int, int] = {} for req in requirements: by_category[req.category] = by_category.get(req.category, 0) + 1 by_level[req.level] = by_level.get(req.level, 0) + 1 output = [f"Found {len(requirements)} ASVS requirements:\n"] output.append("**By Level:**") for level in sorted(by_level.keys()): output.append(f"- Level {level}: {by_level[level]}") output.append("\n**By Category:**") for category in sorted(by_category.keys()): output.append(f"- {category}: {by_category[category]}") return "\n".join(output)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/harn1shmodi/vsguard-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server