# API Reference — `report/` ## `report/__init__.py` — public exports ```python from report import generate_html_report, generate_sarif, REMEDIATION ``` --- ## `report/html.py` ### `generate_html_report(findings, scan_meta)` ```python def generate_html_report(findings: List[dict], scan_meta: dict) -> str ``` Build a self-contained, print-friendly HTML report string. **Parameters:** | Parameter | Type | Description | |-----------|------|-------------| | `findings` | `List[dict]` | Normalized finding dicts (from `make_finding`) | | `scan_meta` | `dict` | Metadata injected into the report | **`scan_meta` keys:** | Key | Default | Description | |-----|---------|-------------| | `"title"` | `"Security Scan Report"` | `` and `<h1>` | | `"footer"` | `"HF Security Scanner"` | Footer text | | `"repo"` | `""` | Repository URL shown in header | | `"scanned_at"` | auto | ISO timestamp | **Returns:** Complete `<!DOCTYPE html>...` string. **Features:** - Summary cards: severity counts (ERROR / WARNING / INFO), confidence distribution, category split (security / performance). - Top OWASP categories section (top 8 by frequency). - Per-finding cards with: severity badge, confidence badge, category badge, tool/rule badge, OWASP tag(s), message, file:line, and remediation hint. - All user content is HTML-escaped (XSS-safe). - Severity aliases: `HIGH → ERROR`, `MEDIUM → WARNING`, `LOW → INFO`. **Example:** ```python from report import generate_html_report html = generate_html_report(findings, {"title": "My Project Scan", "repo": "github.com/org/repo"}) Path("report.html").write_text(html, encoding="utf-8") ``` --- ### Internal functions #### `_render_finding(f)` ```python def _render_finding(f: dict) -> str ``` Render a single finding dict as an HTML `<div class="finding ...">` block. #### `_aggregate(findings)` ```python def _aggregate(findings: List[dict]) -> dict ``` Compute summary statistics. Returns: ```python { "severity": {"ERROR": int, "WARNING": int, "INFO": int}, "confidence": {"confirmed": int, "likely": int, "possible": int}, "category": {"security": int, "performance": int}, "owasp": {"A01:2021-...": int, ...}, } ``` --- ## `report/sarif.py` ### `generate_sarif(findings, scan_meta)` ```python def generate_sarif(findings: List[dict], scan_meta: dict) -> dict ``` Build a SARIF 2.1.0 document as a Python dict (serialize with `json.dumps`). **Parameters:** | Parameter | Type | Description | |-----------|------|-------------| | `findings` | `List[dict]` | Normalized finding dicts | | `scan_meta` | `dict` | Metadata (same keys as HTML report) | **Returns:** `dict` conforming to `https://json.schemastore.org/sarif-2.1.0.json`. **GitHub Advanced Security compatibility:** - Upload the serialized SARIF file using `github/codeql-action/upload-sarif`. - `properties.security-severity` is a float string (`"9.0"`) enabling GitHub's severity triage. - `partialFingerprints.primaryLocationLineHash` enables GitHub to deduplicate findings across runs. - File paths are normalized to forward-slash, drive letters stripped (`C:\path` → `path`). **Example:** ```python import json from report import generate_sarif sarif = generate_sarif(findings, {"repo": "https://github.com/org/repo"}) Path("results.sarif").write_text(json.dumps(sarif, indent=2), encoding="utf-8") ``` ### Severity → SARIF level mapping | Severity | Confidence | SARIF `level` | `security-severity` | |----------|-----------|--------------|---------------------| | ERROR | confirmed | `error` | 9.0 | | ERROR | likely | `error` | 7.5 | | ERROR | possible | `warning` | 5.5 | | HIGH | confirmed | `error` | 8.5 | | WARNING | confirmed | `warning` | 4.5 | | WARNING | likely | `warning` | 4.0 | | WARNING | possible | `warning` | 3.0 | | INFO | confirmed | `note` | 2.5 | | INFO | likely | `note` | 2.0 | | INFO | possible | `note` | 1.5 | ### Internal functions #### `_fingerprint(finding)` ```python def _fingerprint(finding: dict) -> str ``` SHA-256 fingerprint of `tool:rule:file:line:message` (first 16 hex chars). Used for `partialFingerprints.primaryLocationLineHash`. #### `_build_rules_catalog(findings)` ```python def _build_rules_catalog(findings: List[dict]) -> List[dict] ``` Build the `tool.driver.rules[]` catalog — one entry per unique `rule` ID, with `shortDescription`, `helpUri` (OWASP link), and `security-severity`. #### `_result_for_finding(finding)` ```python def _result_for_finding(finding: dict) -> dict ``` Convert one finding dict to a SARIF `result` object. Handles: - Windows path normalization (strips drive letters). - Invalid / non-positive line numbers (normalized to `1`). #### `_help_uri(owasp)` ```python def _help_uri(owasp: Any) -> str ``` Return the first matching OWASP help URL for the given OWASP tag list. Falls back to `_TOOL_URI` if no match. --- ## `report/remediation.py` ### `REMEDIATION` ```python REMEDIATION: dict[str, str] ``` A mapping from rule ID / finding type to a short plain-English fix hint. Used by `make_finding()` in `core/models.py` — if `remediation=None` is passed, the registry is consulted. **To add a hint:** ```python # report/remediation.py REMEDIATION = { "B602": "Avoid shell=True; use subprocess.run() with a list.", "MY-RULE": "Replace foo() with safe_foo().", ... } ``` --- ## `report/styles.py` ### `REPORT_CSS` Embedded CSS string for the HTML report. Imported by `report/html.py`. ### `FP_GUIDE_HTML` HTML fragment with a false-positive triage guide appended to every report.