Download backend/alert_parser.py from ADI576/SecBrief: direct link, hf CLI and curl.
- Browser
- Download file 3.98 kB
-
https://huggingface.co/spaces/ADI576/SecBrief/resolve/main/backend/alert_parser.py
- Command line
-
hf download hf://spaces/ADI576/SecBrief/backend/alert_parser.py
-
curl -L -o alert_parser.py https://huggingface.co/spaces/ADI576/SecBrief/resolve/main/backend/alert_parser.py
3.98 kB
| """Parse SARIF, npm audit JSON, and other scanner formats into normalized alert text.""" | |
| from __future__ import annotations | |
| import json | |
| import re | |
| from typing import Any | |
| def detect_format(text: str, filename: str = "") -> str: | |
| name = filename.lower() | |
| stripped = text.strip() | |
| if name.endswith(".sarif") or name.endswith(".json"): | |
| if '"runs"' in stripped and '"results"' in stripped: | |
| return "sarif" | |
| if '"vulnerabilities"' in stripped or '"metadata"' in stripped and '"vulnerabilities"' in stripped: | |
| return "npm_audit" | |
| if stripped.startswith("{"): | |
| try: | |
| data = json.loads(stripped) | |
| if isinstance(data, dict): | |
| if "runs" in data: | |
| return "sarif" | |
| if "vulnerabilities" in data or data.get("auditReportVersion"): | |
| return "npm_audit" | |
| except json.JSONDecodeError: | |
| pass | |
| return "text" | |
| def parse_upload(text: str, filename: str = "") -> dict[str, Any]: | |
| fmt = detect_format(text, filename) | |
| if fmt == "sarif": | |
| return _parse_sarif(text, filename) | |
| if fmt == "npm_audit": | |
| return _parse_npm_audit(text, filename) | |
| return { | |
| "format": "text", | |
| "filename": filename, | |
| "finding_count": 1, | |
| "alert_text": text.strip(), | |
| "title": "Uploaded security report", | |
| } | |
| def _parse_sarif(raw: str, filename: str) -> dict[str, Any]: | |
| data = json.loads(raw) | |
| lines: list[str] = ["SARIF security report", "=" * 40, ""] | |
| count = 0 | |
| for run in data.get("runs", []): | |
| tool = run.get("tool", {}).get("driver", {}) | |
| tool_name = tool.get("name", "scanner") | |
| lines.append(f"Tool: {tool_name}") | |
| for res in run.get("results", [])[:40]: | |
| count += 1 | |
| rule = res.get("ruleId", "unknown") | |
| level = res.get("level", "warning") | |
| msg = res.get("message", {}) | |
| text = msg.get("text") if isinstance(msg, dict) else str(msg) | |
| locs = res.get("locations", []) | |
| path = "" | |
| if locs: | |
| phys = locs[0].get("physicalLocation", {}).get("artifactLocation", {}) | |
| path = phys.get("uri", "") | |
| lines.append(f"\n[{count}] {level.upper()} — {rule}") | |
| if path: | |
| lines.append(f" Location: {path}") | |
| lines.append(f" {text}") | |
| lines.append("") | |
| alert = "\n".join(lines) | |
| return { | |
| "format": "sarif", | |
| "filename": filename, | |
| "finding_count": count, | |
| "alert_text": alert, | |
| "title": f"SARIF report ({count} finding(s))", | |
| } | |
| def _parse_npm_audit(raw: str, filename: str) -> dict[str, Any]: | |
| data = json.loads(raw) | |
| vulns = data.get("vulnerabilities") or {} | |
| lines = ["npm audit report", "=" * 40, ""] | |
| count = 0 | |
| for name, v in list(vulns.items())[:50]: | |
| count += 1 | |
| sev = v.get("severity", "unknown") | |
| via = v.get("via", []) | |
| title = name | |
| if via and isinstance(via[0], dict): | |
| title = via[0].get("title", name) | |
| fix = v.get("fixAvailable") | |
| fix_str = "fix available" if fix else "no automatic fix" | |
| lines.append(f"{name} — {sev} — {title} ({fix_str})") | |
| if count == 0 and data.get("metadata", {}).get("vulnerabilities"): | |
| meta = data["metadata"]["vulnerabilities"] | |
| lines.append( | |
| f"Summary: {meta.get('high', 0)} high, {meta.get('moderate', 0)} moderate, " | |
| f"{meta.get('low', 0)} low" | |
| ) | |
| count = sum(meta.values()) if isinstance(meta, dict) else 1 | |
| alert = "\n".join(lines) | |
| return { | |
| "format": "npm_audit", | |
| "filename": filename, | |
| "finding_count": max(count, 1), | |
| "alert_text": alert, | |
| "title": f"npm audit ({count} package(s))", | |
| } | |
| def extract_cve_ids(text: str) -> list[str]: | |
| return list(dict.fromkeys(re.findall(r"CVE-\d{4}-\d+", text, re.I))) | |