← All guides

SARIF: a common language for findings

Cross-cuttingDraugr: available today

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:

  • 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, GitHub code scanning, Azure DevOps, 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#

  • Not every tool emits it well. Some produce technically-valid-but-thin SARIF; quality varies.
  • Uploading to code scanning needs GitHub Advanced Security on private repos (it's free for public ones).
  • Merging still needs judgment, dedup across tools that use different rule IDs for the same issue isn't automatic.
How Draugr fits. SARIF is Draugr's backbone: every control, whichever tool backs it, normalizes to SARIF, so results merge and deduplicate into one verdict and push straight into GitHub code scanning and similar dashboards. It's what lets Draugr orchestrate many scanners without N×M glue. See controls & scanners in the docs.

Keep learning#