Skip to main content

Guide

Export SARIF from an offline SAST scan

SARIF is the format GitHub, GitLab and most CI security dashboards expect. Here is exactly how StaticCodeAudit generates it, what the file contains, and how to wire it into GitHub Code Scanning — without uploading a single line of source code anywhere.

What SARIF is, in one paragraph

SARIF (Static Analysis Results Interchange Format) is an OASIS standard — currently version 2.1.0 — for representing the output of static analysis tools in a single JSON schema. Instead of every scanner inventing its own report format, tools that speak SARIF plug directly into GitHub Code Scanning, GitLab SAST, Azure DevOps and most security dashboards without a custom parser. It groups findings under a tool.driver.rules array (rule metadata) and a results array (each finding: rule ID, severity, file, line, message).

Generate the report

One flag, run from any CI runner or your own machine:

./staticcodeaudit-linux-x86_64 /path/to/project --sarif --fail-on-high

This writes two files next to your normal HTML report: a SCA-SARIF-<timestamp>.sarif file and the usual SCA-REPORT-<timestamp>.html — the SARIF export is additive, you still get the human-readable report. --fail-on-high is optional but is what makes the step actually block a pipeline: the process exits with code 1 the moment a HIGH-severity finding is present, 0 otherwise.

What the file actually contains

A trimmed real example — one finding, produced by scanning a two-line vulnerable snippet:

{
  "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/sarif-2.1/schema/sarif-schema-2.1.0.json",
  "version": "2.1.0",
  "runs": [{
    "tool": {
      "driver": {
        "name": "StaticCodeAudit",
        "version": "1.0.0",
        "informationUri": "https://codefixture.com",
        "rules": [{
          "id": "hardcoded_secret",
          "name": "Hardcoded secret",
          "fullDescription": { "text": "Plain text secrets in code can be exposed via Git repository." },
          "defaultConfiguration": { "level": "error" }
        }]
      }
    },
    "results": [{
      "ruleId": "hardcoded_secret",
      "level": "error",
      "message": { "text": "Plain text secrets in code can be exposed via Git repository." },
      "locations": [{
        "physicalLocation": {
          "artifactLocation": { "uri": "app.py" },
          "region": { "startLine": 6 }
        }
      }],
      "fixes": [{ "description": { "text": "Use environment variables or system_configs in database." } }]
    }]
  }]
}

Every result carries a file path, a line number, and — where a remediation is known — a fixes entry with a plain-language suggestion. GitHub Code Scanning renders all of this directly on the Security tab, annotated on the exact line in the diff view.

SARIF or SBOM — not both in the same run

StaticCodeAudit also exports a dependency inventory as a CycloneDX 1.5 SBOM (--sbom), but the two exports are mutually exclusive per run — they answer different questions (vulnerabilities found vs. what dependencies exist) and mixing them into one file would blur both. Requesting both at once fails fast:

$ ./staticcodeaudit-linux-x86_64 /path/to/project --sarif --sbom
❌ --sarif and --sbom are mutually exclusive. Use one or the other.

Run the scan twice in CI if you need both artifacts — each run takes well under a second on a small-to-medium codebase. See the SBOM export guide for the dependency-inventory side.

Wiring it into GitHub Code Scanning

GitHub's own upload-sarif action reads any SARIF 2.1.0 file, regardless of which tool produced it. A minimal workflow step:

- name: Run StaticCodeAudit
  run: ./staticcodeaudit-linux-x86_64 /path/to/project --sarif --fail-on-high

- name: Upload SARIF to GitHub Code Scanning
  if: always()
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: docs/audit-reports/*.sarif

if: always() matters here: without it, a HIGH finding (which makes the previous step exit 1) would skip the upload step and you would never see the results in the Security tab — you would only know the pipeline failed, not why.

Availability

SARIF export is included from the Team tier upward (Team, Team Plus, Enterprise); the Solo tier exports HTML only. Full breakdown on the pricing page.

Frequently asked questions

Does generating a SARIF report send anything over the network?

No. The SARIF file is written to local disk next to the HTML report, from data already computed during the local scan. StaticCodeAudit makes zero outbound network calls during a scan, verifiable with a network monitor (tcpdump -i any -n) — generating an extra export format doesn't change that.

Can I use the SARIF file with GitLab or another platform instead of GitHub?

Yes — SARIF 2.1.0 is a generic OASIS standard, not GitHub-specific. GitLab, Azure DevOps and most security dashboards that support "import SARIF" accept the same file unmodified. The example above uses GitHub's upload-sarif action because it is the most common target, not because the file format is tied to it.

Why does --sarif --sbom fail instead of producing both files?

It is an explicit design choice, not a missing feature: a SARIF file describes findings, a CycloneDX SBOM describes a dependency inventory — conflating them into a single export would make both harder to consume correctly downstream. Run the scan twice (or in two parallel CI jobs) if your pipeline needs both artifacts from the same commit.

Does every finding include a fixes suggestion?

Only where StaticCodeAudit has a known remediation pattern for that rule — the example above (hardcoded_secret) does, but not every rule ships one yet. When absent, the results entry still carries the full location and message, just without the fixes field.

See it on your own code

Open the live demo report — no install, no signup — or run the binary against a small project and inspect the SARIF file yourself.

Open the live report Download the demo binary