4.7 KiB
Here’s a quick, practical path to make your scanner’s findings show up in GitHub’s Code scanning UI with almost no integration work: emit SARIF 2.1.0 and upload it.
What SARIF is (and what GitHub expects)
- SARIF = Static Analysis Results Interchange Format, a JSON standard for static-analysis results. GitHub Code Scanning accepts a subset of SARIF 2.1.0 and turns it into alerts in the Security tab. (GitHub Docs)
Three upload options (pick one)
- GitHub Actions: add a step that uploads your SARIF file(s).
# .github/workflows/upload-sarif.yml
name: Upload SARIF
on:
push:
schedule: [{cron: "0 3 * * 1"}] # optional weekly recrawl
jobs:
sarif:
runs-on: ubuntu-latest
permissions:
security-events: write # required to publish code scanning alerts
contents: read
steps:
- uses: actions/checkout@v4
- name: Run your scanner
run: ./your_scanner --format sarif --out results.sarif
- name: Upload SARIF to Code Scanning
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
category: your-scanner
This uses GitHub’s official upload-sarif action and is the easiest route. (GitHub Docs)
-
REST API: gzip + base64 your SARIF and POST to
code-scanning/sarifs(needssecurity_eventsscope for private repos). Useful if you run scans outside Actions. (GitHub Docs) -
CodeQL CLI:
codeql github upload-results --sarif-file results.sarif(also needs proper token). Handy if you’re already using the CLI in your CI. (GitHub Docs)
Minimal SARIF you should emit
At minimum, include:
version: "2.1.0"- one
runwith yourtool.driver(name, version) results[]with each finding’sruleId,message.text, and at least onelocation(file/region) so GitHub can anchor it to code. (Empty or missing locations often breaks uploads.) (GitHub Docs)
Skeleton:
{
"version": "2.1.0",
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"runs": [{
"tool": { "driver": { "name": "StellaOps Scanner", "version": "1.0.0" } },
"results": [{
"ruleId": "STELLA001",
"message": { "text": "Vulnerability XYZ in package foo@1.2.3" },
"locations": [{
"physicalLocation": {
"artifactLocation": { "uri": "src/app/foo.js" },
"region": { "startLine": 42 }
}
}]
}]
}]
}
(Full schema: OASIS SARIF 2.1.0.) (OASIS Open)
Gotchas (save yourself time)
- One tool/category per run: GitHub is deprecating combining multiple runs with the same tool+category in a single upload; by June 2025 such uploads will fail. Keep runs distinct or separate files. (The GitHub Blog)
- Partial fingerprints: If you don’t provide them, the upload action can compute them (prevents duplicate alerts) when source is present. (GitHub Docs)
- Permissions: in Actions, grant
security-events: write. For API/CLI, use tokens with the right scopes. (GitHub Docs) - PRs from forks: public API uploads have restrictions; the
upload-sarifaction is the usual workaround in PR contexts. (GitHub)
Why this helps your rollout
- Zero custom UI: GitHub draws findings, file annotations, and PR decorations for you. (GitHub Docs)
- Fits any CI: Emit SARIF once, then upload via Actions, REST, or CLI—works for GitHub-hosted or external runners. (GitHub Docs)
If you want, I can tailor a ready-to-drop workflow for one of your Stella Ops repos (mono-repo vs multi-repo, language mix, and desired categories).