SARIF: a common language for findings
In plain terms
Every security tool wants to report its findings in its own format, one emits JSON shaped one way, another XML, another a bespoke schema. SARIF (Static Analysis Results Interchange Format) is the industry standard that fixes this: a single JSON format, standardized by OASIS (v2.1.0), that any tool can produce and any tool can consume.
Think of it as a shared language. Once every scanner speaks SARIF, their results become interoperable.
Why it matters
Without a common format, every integration is bespoke: N tools times M dashboards equals N×M adapters to build and maintain. With SARIF, a finding from any scanner can be:
| Once every scanner speaks it, a finding can be | |
|---|---|
| Merged | with findings from every other scanner, into one view |
| Deduplicated | the same issue found by two tools collapses into one |
| Displayed | in tools that already understand SARIF, including GitHub code scanning, Azure DevOps and VS Code, with no custom glue |
Not every platform reads it. GitLab's Vulnerability Report takes GitLab's own schema, so Draugr renders that too and the findings land in the same place. The interchange layer is what makes the second format a rendering rather than a second integration.
It's the quiet piece of plumbing that makes "one security report" possible instead of ten disconnected dashboards.
Where it fits
SARIF is an interchange layer, not a control. Your scanners produce it; your platforms and pipelines consume it. Most major OSS scanners, Trivy, Semgrep, Gitleaks, CodeQL, can emit SARIF natively, which is exactly why it's become the default lingua franca.
What's in it
A SARIF file describes the tool that ran, a list of rules it checked, and the results, each with a rule ID, a severity level, a message, and a location (file + line, or a URL). Optional extensions carry things like a numeric security-severity score or suppression info for accepted findings.
Stripped to its essentials, a report with a single finding looks like this:
{
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "ExampleScanner",
"rules": [
{ "id": "no-eval", "shortDescription": { "text": "Avoid eval()" } }
]
}
},
"results": [
{
"ruleId": "no-eval",
"level": "error",
"message": { "text": "Use of eval() on untrusted input." },
"locations": [
{
"physicalLocation": {
"artifactLocation": { "uri": "src/handler.js" },
"region": { "startLine": 42 }
}
}
]
}
]
}
]
}
Read it top-down: which tool ran (tool.driver), what it checks for (rules), and what
it found, a result pointing rule no-eval at src/handler.js line 42, flagged as an error.
Every scanner that speaks SARIF produces this same shape, which is exactly what lets findings from
different tools be merged into one report.
Common pitfalls
| The pitfall | What it looks like |
|---|---|
| Not every tool emits it well | Some produce technically-valid-but-thin SARIF; quality varies. |
| Uploading to code scanning needs GitHub Code Security | On private repositories. Public ones get it free. |
| Merging still needs judgment | Deduplicating across tools that use different rule IDs for the same issue is not automatic. |
Keep learning
- The security controls landscape, the tools SARIF unifies
- Shift-left & DevSecOps, where SARIF gets published in CI