src/pqc_lint/reporters/sarif.py
| 1 | """SARIF 2.1.0 reporter - compatible with GitHub code scanning.""" |
| 2 | |
| 3 | from __future__ import annotations |
| 4 | |
| 5 | import json |
| 6 | |
| 7 | from pqc_lint.findings import ScanReport, Severity |
| 8 | from pqc_lint.reporters.base import Reporter |
| 9 | from pqc_lint.rules import RULES |
| 10 | |
| 11 | _SEVERITY_TO_SARIF_LEVEL = { |
| 12 | Severity.CRITICAL: "error", |
| 13 | Severity.HIGH: "error", |
| 14 | Severity.MEDIUM: "warning", |
| 15 | Severity.LOW: "note", |
| 16 | Severity.INFO: "none", |
| 17 | } |
| 18 | |
| 19 | |
| 20 | class SarifReporter(Reporter): |
| 21 | format_name = "sarif" |
| 22 | |
| 23 | def render(self, report: ScanReport) -> str: |
| 24 | rules_payload = [] |
| 25 | for r in RULES: |
| 26 | rules_payload.append({ |
| 27 | "id": r.id, |
| 28 | "name": r.title.replace(" ", ""), |
| 29 | "shortDescription": {"text": r.title}, |
| 30 | "fullDescription": {"text": r.message}, |
| 31 | "helpUri": "https://quantamrkt.com/tools/pqc-lint-action", |
| 32 | "help": {"text": r.suggestion or r.message}, |
| 33 | "defaultConfiguration": { |
| 34 | "level": _SEVERITY_TO_SARIF_LEVEL[r.severity], |
| 35 | }, |
| 36 | "properties": { |
| 37 | "tags": ["security", "post-quantum", "cryptography"], |
| 38 | "cwe": r.cwe or "", |
| 39 | "precision": "high", |
| 40 | "classical_primitive": r.classical_primitive, |
| 41 | }, |
| 42 | }) |
| 43 | |
| 44 | results = [] |
| 45 | for f in report.findings: |
| 46 | results.append({ |
| 47 | "ruleId": f.rule_id, |
| 48 | "level": _SEVERITY_TO_SARIF_LEVEL[f.severity], |
| 49 | "message": {"text": f"{f.message} Suggestion: {f.suggestion}"}, |
| 50 | "locations": [{ |
| 51 | "physicalLocation": { |
| 52 | "artifactLocation": {"uri": f.file}, |
| 53 | "region": { |
| 54 | "startLine": f.line, |
| 55 | "startColumn": f.column, |
| 56 | "snippet": {"text": f.snippet or ""}, |
| 57 | }, |
| 58 | }, |
| 59 | }], |
| 60 | "properties": { |
| 61 | "severity": f.severity.value, |
| 62 | "cwe": f.cwe or "", |
| 63 | "suggestion": f.suggestion, |
| 64 | }, |
| 65 | }) |
| 66 | |
| 67 | sarif = { |
| 68 | "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", |
| 69 | "version": "2.1.0", |
| 70 | "runs": [{ |
| 71 | "tool": { |
| 72 | "driver": { |
| 73 | "name": "pqc-lint", |
| 74 | "version": "0.1.0", |
| 75 | "informationUri": "https://quantamrkt.com/tools/pqc-lint-action", |
| 76 | "rules": rules_payload, |
| 77 | }, |
| 78 | }, |
| 79 | "results": results, |
| 80 | "columnKind": "utf16CodeUnits", |
| 81 | }], |
| 82 | } |
| 83 | return json.dumps(sarif, indent=2) |
| 84 | |