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"