58 lines
2.2 KiB
Python
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"
|