Files
advanced-artifactual-intell…/src/aaisa/reporters.py
T

58 lines
2.2 KiB
Python

from __future__ import annotations
import json
from .models import ScanReport, Severity
def json_report(report: ScanReport) -> str:
return json.dumps(report.to_dict(), indent=2, sort_keys=True) + "\n"
def sarif_report(report: ScanReport) -> str:
rules: dict[str, dict[str, object]] = {}
results: list[dict[str, object]] = []
levels = {
Severity.INFO: "note",
Severity.LOW: "note",
Severity.MEDIUM: "warning",
Severity.HIGH: "error",
Severity.CRITICAL: "error",
}
for finding in report.findings:
rules.setdefault(finding.rule_id, {
"id": finding.rule_id,
"name": finding.title,
"shortDescription": {"text": finding.title},
"help": {"text": finding.remediation or "Review the finding and its evidence."},
"properties": {"tags": list(finding.tags), "security-severity": str(int(finding.severity))},
})
region: dict[str, int] = {}
if finding.line is not None:
region["startLine"] = finding.line
if finding.column is not None:
region["startColumn"] = finding.column
location: dict[str, object] = {"physicalLocation": {"artifactLocation": {"uri": finding.artifact_path}}}
if region:
location["physicalLocation"]["region"] = region # type: ignore[index]
result: dict[str, object] = {
"ruleId": finding.rule_id,
"level": levels[finding.severity],
"message": {"text": finding.message},
"locations": [location],
"partialFingerprints": {"aaisa/v1": finding.fingerprint()},
}
if finding.evidence:
result["properties"] = {"evidence": finding.evidence, "severity": finding.severity.label()}
results.append(result)
payload = {
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [{
"tool": {"driver": {"name": "AAISA", "version": report.tool_version, "rules": list(rules.values())}},
"results": results,
"invocations": [{"executionSuccessful": not report.errors}],
}],
}
return json.dumps(payload, indent=2, sort_keys=True) + "\n"