feat(security): export scan results as SARIF 2.1.0 (#652)

Adds a new SarifExporter service that builds a SARIF 2.1.0 document
from the stored scan findings (vulnerabilities, secrets, misconfigs).
Rule IDs are namespaced to avoid collisions in a flat result list.
Suppressions carry through as SARIF suppressions[] entries so GitHub
code scanning and Defender for Cloud see the same accepted status
shown in the UI.

Exposed via GET /api/security/scans/:id/sarif, admin + paid-tier
gated to match the SBOM export precedent. A SARIF button appears
in the scan sheet next to SBOM and CSV for paid tiers.
This commit is contained in:
Anso
2026-04-17 08:17:36 -04:00
committed by GitHub
parent a95bf1ff33
commit 12bbf86dc4
5 changed files with 618 additions and 0 deletions
+32
View File
@@ -27,6 +27,7 @@ The Trivy CLI must be available on the machine running Sencho. Trivy is not bund
| Scan history and comparison | | ✓ | ✓ |
| Secret detection in image filesystems | | ✓ | ✓ |
| Compose file misconfiguration scanning | | ✓ | ✓ |
| SARIF export (code scanning integration) | | ✓ | ✓ |
## On-demand scanning
@@ -77,6 +78,7 @@ From the drawer header you can:
- **Re-scan**: kick off a fresh scan, ignoring the digest cache.
- **Download SBOM**: export a Software Bill of Materials in SPDX JSON or CycloneDX format (Skipper and Admiral).
- **Export CSV**: export the full vulnerability list for offline review.
- **Export SARIF**: download the full scan (vulnerabilities, secrets, and misconfigs) as SARIF 2.1.0 for upload to GitHub code scanning or other SARIF-aware tooling (Skipper and Admiral).
## Post-deploy automated scanning
@@ -209,6 +211,32 @@ From any stack page, click **Scan config** next to the Deploy controls. Sencho r
Config scans are stored in the same history as image scans with an `image_ref` of `stack:<name>`, so they appear on the Scan history page and can be exported as CSV.
## SARIF export
<Note>
SARIF export requires a **Skipper** or **Admiral** license.
</Note>
SARIF (Static Analysis Results Interchange Format) is the standard format supported by GitHub code scanning, Microsoft Defender for Cloud, and most security dashboards. Sencho generates SARIF 2.1.0 documents directly from the stored scan results so the download matches what you see in the drawer (same findings, same suppression state) without re-running Trivy.
From the scan drawer header, click **SARIF** to download the report. The file is named after the image reference with a `.sarif.json` extension.
What the export contains:
- **Vulnerabilities**: one SARIF result per CVE, with `security-severity` scored 9.8 (CRITICAL), 7.5 (HIGH), 5.0 (MEDIUM), 2.5 (LOW), or 0.0 (UNKNOWN). The affected package appears as a logical location (`<pkg>@<version>`).
- **Secrets**: rule IDs are namespaced as `SECRET:<rule>`. Results point at the file and line number where the match was found.
- **Misconfigs**: rule IDs are namespaced as `MISCONFIG:<rule>`. Results point at the Compose file that triggered the check.
- **Suppressions**: CVEs you have suppressed in Sencho are emitted with a SARIF `suppressions` entry of kind `external` and status `accepted`, so code-scanning dashboards can dismiss them with the justification you recorded.
Typical upload flow for GitHub code scanning:
```yaml
- name: Upload SARIF to GitHub
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: sencho-scan.sarif.json
```
## Scan history
Every scan Sencho runs is stored with its full vulnerability detail. Scan records are automatically pruned after 90 days to keep the database compact. The history is used to power:
@@ -299,3 +327,7 @@ The button is only shown when Trivy is available on the stack's node, the curren
### Compose misconfiguration scan returns 404
The scanner needs to locate a Compose file in the stack directory. If the stack was created outside Sencho and the working directory does not contain a file named `compose.yml`, `compose.yaml`, `docker-compose.yml`, or `docker-compose.yaml`, the scan returns 404. Name the file accordingly or keep the stack under Sencho's managed compose directory.
### SARIF download returns 409 "Scan not complete"
SARIF export requires a completed scan. If a scan failed, timed out, or is still running, the button downloads nothing and the server returns a 409. Trigger a fresh scan from the Resources Hub or the stack page, wait for the drawer to populate, then export again.