"""Adapter: Invoke-ScriptAnalyzer JSON normalized to Finding[]. Shared by both PowerShell tools — PSScriptAnalyzer's built-in rules and the InjectionHunter custom rule pack — because both are Invoke-ScriptAnalyzer runs and emit the same DiagnosticRecord shape. """ from __future__ import annotations import json import os from scripts.manifest import Finding _SEVERITY = { "ParseError": "critical", "Error": "high", "Warning": "medium", "Information": "low", } _INJECTION_FLOOR = "high" def parse_psscriptanalyzer_output( stdout: str, repo_root: str, tool: str = "psscriptanalyzer", ) -> list[Finding]: try: payload = json.loads(stdout) except json.JSONDecodeError: return [] if isinstance(payload, dict): payload = [payload] if not isinstance(payload, list): return [] out: list[Finding] = [] for item in payload: if not isinstance(item, dict): continue path = item.get("ScriptPath") or item.get("ScriptName") or "" rel = os.path.relpath(path, repo_root) if path.startswith(repo_root) else path line = item.get("Line") or 0 severity = _SEVERITY.get(item.get("Severity", ""), "medium") if tool == "injectionhunter": severity = _INJECTION_FLOOR out.append(Finding( tool=tool, rule_id=item.get("RuleName", "unknown"), severity=severity, file=rel, line=line, end_line=item.get("EndLine") or line, message=item.get("Message", ""), )) return out