SARIF: The Universal Translator for Code Scanners
Your security tools all speak different languages. SARIF makes them speak one.
Table of Contents
The Problem
Picture a typical engineering team. They run a linter for code style, a SAST tool for security bugs, a secrets scanner, a container scanner, and maybe an infrastructure-as-code checker.
Five tools. Five output formats. One tool spits out XML, another prints colorful terminal text, a third invents its own JSON structure. Every time you want to see “all the problems in this repo” in one place, someone has to write glue code to parse each format.
Then you swap one tool for a better one, and the glue breaks.
This is the mess SARIF was built to clean up.
What Is SARIF?
SARIF stands for Static Analysis Results Interchange Format. It’s an open standard, based on JSON, that defines one common way for analysis tools to report what they found.
Think of it like a shipping container for code findings. It doesn’t matter what’s inside or which factory packed it. Every container has the same shape, so every crane, truck, and ship in the world can handle it.
A few quick facts:
- It’s an official OASIS standard. Version 2.1.0 became a standard in March 2020 and is the version you’ll see almost everywhere today.
- It was driven largely by Microsoft, with contributions from GitHub (via Semmle), and many other tool vendors.
- Files usually end in
.sarif(or.sarif.json). - Work continues on the next revisions (2.2, with a broader 3.0 on the horizon), but 2.1.0 is what tools support right now.
In one sentence: SARIF is the agreed-upon answer to “How should a tool tell me what’s wrong with my code?”
Why Should You Care?
1. One format, many tools
Your linter, your security scanner, and your dependency checker can all produce SARIF. Anything that reads SARIF can now read all of them. No more custom parsers.
2. Swap tools without breaking your pipeline
Want to replace Scanner A with Scanner B? If both emit SARIF, your dashboards, CI checks, and reports keep working. The format is the contract, not the tool.
3. Findings show up where developers already work
This is the real magic. Platforms like GitHub Code Scanning and Azure DevOps, and editors like VS Code (via the SARIF Viewer extension), understand SARIF natively. Upload a file and the findings appear as annotations right on the lines of code, inside pull requests.
Developers fix what they can see. SARIF puts problems in front of their eyes.
4. Rich, precise information
SARIF isn’t just “error on line 42.” It can carry:
- The exact file, line, and column range
- The rule that was violated, with a description and a help link
- Severity levels
- Code flows (the step-by-step path a tainted input travels through your code)
- Suggested fixes
- Fingerprints to track the same issue across runs, so you know what’s new versus what’s old
5. Better auditing and compliance
A standardized, machine-readable record of every scan is exactly what auditors and security teams love. Archive the files, compare them over time, and prove what was checked.
How Does It Work?
The anatomy of a SARIF file
At its core, a SARIF file is a nested JSON structure. Here’s the mental model:
SARIF log
└── runs[] → one entry per tool execution
├── tool → who ran the scan (name, version, rules)
└── results[] → what it found
├── ruleId → which rule was broken
├── level → error / warning / note
├── message → human-readable explanation
└── locations[] → where in the codeThat’s it. A log contains runs. Each run has a tool and its results.
A real (tiny) example
Here’s a complete, valid SARIF file reporting one hardcoded password:
{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "SuperScanner",
"version": "1.0.0",
"rules": [
{
"id": "SEC001",
"shortDescription": { "text": "Hardcoded password" },
"helpUri": "https://example.com/rules/SEC001"
}
]
}
},
"results": [
{
"ruleId": "SEC001",
"level": "error",
"message": { "text": "Password is hardcoded in source code." },
"locations": [
{
"physicalLocation": {
"artifactLocation": { "uri": "src/config.py" },
"region": { "startLine": 12, "startColumn": 5 }
}
}
]
}
]
}
]
}Read it top to bottom and it tells a clear story: SuperScanner v1.0.0 ran, it checks for hardcoded passwords, and it found one in src/config.py at line 12.
Notice how the rule is defined once in tool.driver.rules and then referenced by ruleId in each result. If a scan finds the same issue 500 times, the rule description isn’t repeated 500 times. Neat and compact.
Step 1: Produce SARIF
Most modern tools already support SARIF output, usually with a single flag:
# Semgrep
semgrep scan --config auto --sarif --output results.sarif
# Trivy (containers, dependencies, IaC)
trivy fs --format sarif --output results.sarif .
# ESLint (with Microsoft's SARIF formatter)
npx eslint . --format @microsoft/eslint-formatter-sarif --output-file results.sarifCodeQL, Checkov, Snyk, and many others offer similar options. Check your tool’s docs for “SARIF” and you’ll likely find it.
Step 2: Consume SARIF
Once you have the file, send it somewhere useful. The most popular destination is GitHub Code Scanning. In a GitHub Actions workflow, it takes just a few lines:
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- name: Run scanner
run: semgrep scan --config auto --sarif --output results.sarif
- name: Upload SARIF to GitHub
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarifNow every finding appears in the repository’s Security tab and as inline comments on pull requests. No custom dashboard required.
Prefer your editor? Install the SARIF Viewer extension in VS Code, open the .sarif file, and click through findings that jump straight to the offending line.
The big picture
Linter ───┐
SAST ─────┤ ┌──► GitHub Code Scanning
Secrets ──┼──► .sarif files ──┼──► VS Code
IaC ──────┤ ├──► Azure DevOps
Deps ─────┘ └──► Your own dashboards / reportsMany producers, one format, many consumers. That’s the whole idea.
Pro Tips
- Validate your files. If you’re generating SARIF yourself, run it through a validator (Microsoft’s SARIF SDK includes a multitool for this). A malformed file often fails silently on upload.
- Use relative paths. Keep
urivalues relative to the repo root so platforms can map findings to the right files. - Include
partialFingerprintsif you build your own tool. They help platforms recognize the same issue across scans, so fixed bugs close and old bugs don’t reappear as “new.” - Mind the size limits. Platforms cap upload sizes and result counts. Very noisy tools may need filtering before upload.
- Combine smartly. You can merge multiple runs into one SARIF file, or upload separate files per tool. Both are valid; pick what keeps your pipeline clean.
Wrapping Up
SARIF doesn’t find bugs. It does something arguably just as valuable: it makes sure that whatever your tools find actually reaches the people who can fix it, in a consistent, portable, and precise way.
- What: A JSON-based open standard for reporting static analysis results.
- Why: To stop the chaos of every tool speaking its own language, and to put findings right where developers work.
- How: Tools emit
.sariffiles, and platforms like GitHub, Azure DevOps, and VS Code display them.
If your team runs more than one code analysis tool, SARIF is the easiest win you’ll get this quarter. Add the flag, upload the file, and watch the findings show up where they matter.