` |
| `"footer"` | `"HF Security Scanner"` | Footer text |
| `"repo"` | `""` | Repository URL shown in header |
| `"scanned_at"` | auto | ISO timestamp |
**Returns:** Complete `...` 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 `
` 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.