MCPcopy
hub / github.com/anthropics/claude-code / analyze_code_security

Function analyze_code_security

plugins/security-guidance/hooks/llm.py:710–979  ·  view source on GitHub ↗

Use Haiku to perform a security review of code. files: list of (file_path, content_or_diff) tuples is_diff: if True, the content is a unified diff rather than full file contents previous_findings: list of category strings from earlier stop hook firings this turn, used to pro

(files: List[Tuple[str, str]], is_diff: bool = False, previous_findings: Optional[List[str]] = None)

Source from the content-addressed store, hash-verified

708
709
710def analyze_code_security(files: List[Tuple[str, str]], is_diff: bool = False, previous_findings: Optional[List[str]] = None) -> Tuple[Optional[str], List[Dict[str, Any]]]:
711 """
712 Use Haiku to perform a security review of code.
713 files: list of (file_path, content_or_diff) tuples
714 is_diff: if True, the content is a unified diff rather than full file contents
715 previous_findings: list of category strings from earlier stop hook firings this turn,
716 used to prompt the reviewer to verify those issues were actually fixed.
717 Returns (formatted guidance string or None, list of vuln dicts with severity/category).
718 """
719 if not HAS_API_CREDENTIALS or not files:
720 return None, []
721
722 # Build language context from file extensions
723 lang_hints = {
724 ".go": "Go", ".java": "Java/Spring Boot", ".py": "Python",
725 ".rb": "Ruby", ".php": "PHP", ".rs": "Rust",
726 ".ts": "TypeScript", ".js": "JavaScript", ".jsx": "JavaScript/React",
727 ".tsx": "TypeScript/React", ".ejs": "EJS templates",
728 ".html": "HTML/templates", ".properties": "Java properties",
729 ".yaml": "YAML config", ".yml": "YAML config",
730 }
731 languages = set()
732 for fp, _ in files:
733 ext = os.path.splitext(fp)[1].lower()
734 if ext in lang_hints:
735 languages.add(lang_hints[ext])
736 language = ", ".join(sorted(languages)) if languages else "server-side"
737
738 files = _cap_files_for_prompt(files)
739
740 # Build the files section
741 files_section = []
742 for fp, content in files:
743 ext = os.path.splitext(fp)[1].lower()
744 label = "DIFF" if is_diff else "FILE"
745 files_section.append(f"=== {label}: {fp} ===\n```{ext.lstrip('.')}\n{content}\n```")
746 files_text = "\n\n".join(files_section)
747
748 content_desc = "diff" if is_diff else "code"
749
750 if is_diff:
751 diff_instruction = """Note: You are reviewing a unified diff. Unmarked lines (starting with a space) are UNCHANGED context — they were already in the file before this session. Lines starting with + are ADDITIONS made in this session. Lines starting with - are REMOVALS.
752
753CRITICAL: ONLY flag vulnerabilities that are NEWLY INTRODUCED in + lines. Do NOT flag:
754- Issues in unmarked context lines (space-prefixed = pre-existing code). Even if a context line contains SECRET_KEY = 'hardcoded', DEBUG=True, hardcoded passwords, SQL injection, or any other vulnerability — it is PRE-EXISTING and must be ignored.
755- Issues where the SAME pattern existed in the removed (-) lines and was re-added in + lines (this means the code was rewritten/reformatted but the pattern is pre-existing)
756- Pre-existing patterns that Claude simply preserved when rewriting a file
757- Any vulnerability whose vulnerable code snippet appears in context (space-prefixed) lines
758- Vulnerabilities in the ORIGINAL/STARTER code that the developer was given to work with. If a file was fully rewritten (all lines show as - then +), compare the + content against the - content. Only flag NEWLY INTRODUCED patterns that did NOT exist in the - lines.
759- Issues OUTSIDE THE SCOPE of what the developer was asked to do. If the task was "add logging middleware" and the starter code has a hardcoded SECRET_KEY, that is pre-existing and out of scope — do NOT flag it.
760
761A vulnerability is ONLY new if the + lines introduce a pattern that did NOT exist anywhere in the - lines or context lines of the same file.
762
763EXCEPTION — data flow to pre-existing sinks: If + lines route user-controlled data to a PRE-EXISTING dangerous sink (like `new Function()`, `eval()`, `exec()`, or shell string interpolation in context lines), this IS a new vulnerability. The sink was already there, but the new code created a new attack path to it. Flag this as a new vulnerability in the + lines."""
764 else:
765 diff_instruction = ""
766
767 structured_prev = [f for f in (previous_findings or []) if isinstance(f, dict)]

Callers 4

_fallbackFunction · 0.90
handle_stop_hookFunction · 0.90

Calls 4

debug_logFunction · 0.90
_cap_files_for_promptFunction · 0.85
_call_claude_dual_orFunction · 0.85
_format_vulns_guidanceFunction · 0.85

Tested by

no test coverage detected