Render a vuln list into the user-facing guidance block. Shared by analyze_code_security, agentic_review, and the late-dedup paths in the Stop / commit-review handlers so that filtering vulns AFTER the LLM returns can rebuild an accurate message instead of emitting stale guidance tha
(vulns: List[Dict[str, Any]])
| 598 | |
| 599 | |
| 600 | def _format_vulns_guidance(vulns: List[Dict[str, Any]]) -> Optional[str]: |
| 601 | """Render a vuln list into the user-facing guidance block. |
| 602 | |
| 603 | Shared by analyze_code_security, agentic_review, and the late-dedup paths |
| 604 | in the Stop / commit-review handlers so that filtering vulns AFTER the LLM |
| 605 | returns can rebuild an accurate message instead of emitting stale guidance |
| 606 | that still lists dropped findings. |
| 607 | """ |
| 608 | if not vulns: |
| 609 | return None |
| 610 | severity_order = {"critical": 0, "high": 1, "medium": 2} |
| 611 | vulns = sorted(vulns, key=lambda v: severity_order.get(v.get("severity", "medium"), 2)) |
| 612 | by_file: Dict[str, list] = {} |
| 613 | for v in vulns: |
| 614 | by_file.setdefault(v.get("filePath", "unknown"), []).append(v) |
| 615 | lines = [ |
| 616 | "Security Review: Potential vulnerabilities detected", |
| 617 | "", |
| 618 | f"Affected files: {', '.join(by_file)}", |
| 619 | "The following issues were flagged by automated security review. Address each, or briefly note why it doesn't apply. Valid reasons to proceed without changes: the user explicitly asked for this and you've already surfaced the security tradeoffs, or the pattern isn't actually exploitable in this context. Do not dismiss findings solely because the service is internal-only — internal services are common SSRF/IDOR targets:", |
| 620 | "", |
| 621 | ] |
| 622 | n = 1 |
| 623 | for fp, vs in by_file.items(): |
| 624 | lines.append(f" {fp}:") |
| 625 | for v in vs: |
| 626 | sev = (v.get("severity") or "medium").upper() |
| 627 | lines.append(f" {n}. [{sev}] [{v.get('category', 'Unknown')}] {v.get('vulnerableCode', 'N/A')}") |
| 628 | lines.append(f" Suggested fix: {v.get('fix', 'N/A')}") |
| 629 | lines.append("") |
| 630 | n += 1 |
| 631 | return "\n".join(lines) |
| 632 | |
| 633 | |
| 634 | # CC truncates the rewakeSummary override at 300 chars. Cap a little under so |
no outgoing calls
no test coverage detected