SARIF export — pipe compliance findings into security tooling
For: all
Tier: pro+
Time: ~4 min
Why you'd do this
Compliance findings sit naturally alongside security findings in tooling like GitHub Advanced Security, JetBrains Qodana, Sonatype Lift, etc. SARIF is the lingua franca those tools consume. Exporting ComplianceLint findings as SARIF means your team sees Art. 9 risk-management gaps in the same Security tab as their code-scan findings — no new tool to check.
Before you start
- Pro tier or higher (
sarifExportflag intiers.ts). Free / Starter see a 403 from the export endpoint and an upgrade CTA in the dashboard repo header - An API key generated from Settings → API Keys on the dashboard
- Optional but recommended: a GitHub Actions / GitLab CI runner where you'll wire up the SARIF upload step
Step 1
Approach 1 — direct curl (one-shot)
Once you've identified the scan id you want to export (visible on the dashboard scan-detail URL or via cl_sync output):
curl -H "Authorization: Bearer cl_<your_api_key>" \
https://compliancelint.dev/api/v1/sarif/<scan_id> \
-o compliance.sarif
The response is a SARIF 2.1.0 JSON file. Each finding becomes one result with ruleId set to the obligation id (e.g. ART09-OBL-1), level mapped from compliance status (error for NON_COMPLIANT, warning for UNABLE_TO_DETERMINE), and message.text populated with the obligation's human_judgment_needed field.
Step 2
Approach 2 — wire it into GitHub Actions for the Security tab
If your repo is on GitHub with Advanced Security enabled, upload-sarif action publishes the findings to the Security → Code scanning tab on every CI run.
name: ComplianceLint
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
permissions:
security-events: write # required for upload-sarif
contents: read
steps:
- uses: actions/checkout@v4
- name: Fetch compliance SARIF
env:
CL_API_KEY: ${{ secrets.CL_API_KEY }}
CL_SCAN_ID: ${{ vars.CL_LATEST_SCAN_ID }}
run: |
curl -fsSL -H "Authorization: Bearer ${CL_API_KEY}" \
"https://compliancelint.dev/api/v1/sarif/${CL_SCAN_ID}" \
-o compliance.sarif
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: compliance.sarif
category: compliancelint
After the workflow runs, the Security tab populates — see chapter 22 (CI/CD quality gate) for the alternative quality-gate flow that fails the build instead of merely surfacing findings.
Step 3
SARIF rule mapping
ComplianceLint's SARIF emitter maps each finding's obligation_id to a unique SARIF ruleId. The mapping is stable across scans, so GitHub's Code Scanning correctly groups recurring findings.
Status → SARIF level:
| Compliance status | SARIF level | What GitHub shows |
|---|---|---|
| NON_COMPLIANT | error | Red, blocks PR if security-events branch protection requires |
| UNABLE_TO_DETERMINE | warning | Yellow, surfaces but doesn't block |
| COMPLIANT | (omitted) | Not emitted — only gaps appear |
| NOT_APPLICABLE | (omitted) | Not emitted |
Each SARIF result includes the obligation's source_quote field as the rule's fullDescription, so when a developer clicks the finding in the Security tab they see the verbatim regulation text the obligation derives from.
What can go wrong
- Curl returns 403 with
tier_required: pro— Account is below Pro tier. Either upgrade (Settings → Plans), or use the per-finding dashboard view + Compliance Journey PDF as the alternative reporting surface — both are available on lower tiers. - GitHub Actions upload-sarif step fails with
Resource not accessible by integration— The job is missingpermissions: security-events: write. Add the permissions block as shown above. This is per-job — adding it at the workflow level only works in older GitHub Actions versions. - SARIF upload succeeds but no findings appear in the Security tab — GitHub's Code Scanning tab takes 1-3 minutes to ingest. If still missing after 5 minutes, check the workflow log for the upload step's response — it should report
Number of results in SARIF file: N. If N=0, your latest scan had no NON_COMPLIANT or UNABLE_TO_DETERMINE findings (a clean repo).
Related
Last updated: 2026-04-30