rossedman/sarifix

Any SARIF scanner,
a verified fixer.

Point sarifix at Trivy, Checkov, golangci-lint or your own tool with one config file. It tracks every finding by a stable fingerprint, and will only ship a fix a rescan proves.

$ go install github.com/rossedman/sarifix/cmd/sarifix@latest
/app
$ sarifix scan --log-level warn
✓ trivy 14 findings → sarif/trivy.sarif
✓ checkov 12 findings → sarif/checkov.sarif
✓ golangci-lint 1 finding → sarif/golangci-lint.sarif
✓ image-migrate 1 finding → sarif/image-migrate.sarif
$ sarifix diff --base 'base/*.sarif' --head 'head/*.sarif' \
--base-root /basic
0 new 0 fixed 28 unchanged
  • 4SARIF producers verified, one hand-written
  • 28 of 28findings still matched after the lines shifted
  • 28load-time checks on sarifix.yaml
  • 7 of 9commands shipped, the rest on the roadmap

The problem

Scanners find it.
Nobody closes the loop.

A scanner reports hundreds of findings, and the numbers only grow. Matching today's report to last week's breaks as soon as someone adds a line above a finding. sarifix gives every finding an identity that survives edits, so you can say what is new, what is fixed and what is unchanged.

  • Works with any tool that writes SARIF 2.1.0
  • Fingerprints ignore line numbers
  • Config errors name the file, the key path and the line
Checkov/CKV_AWS_24finding main.tf

Ensure no security groups allow ingress from 0.0.0.0:0 to port 22

Reported at line 5. Two comment lines were added above it, so it now sits at line 7.
Same finding, same fingerprint: unchangedsarifix diff --unchanged, line 7 in the head scan
= Checkov/CKV_AWS_24 main.tf:7 Ensure no security groups allow ingress from 0.0.0.0:0 to port 22

Core ideas

Three things you
configure once.

Scanners are entries in a YAML file. Identity comes from fingerprints. Trust comes from verification, which arrives with the fixing phases.

Scanners

Shipped

A name, the SARIF tool names to match, and a command. No code change to add a tool.

- name: checkov
  match: ["Checkov"]
  command: ["checkov", "-d", "{dir}",
    "-o", "sarif",
    "--output-file-path", "{outdir}"]

Fingerprints

Shipped

The tool's own hash if it has one, otherwise a hash of tool, rule, path and the flagged code.

partialFingerprints:
  sarifix/v1: fcadca11a498b6d6…

line numbers never count

Verification

Planned, phase 2

A fix ships only if the rescan shows the finding gone, nothing new, and your tests pass.

verify:
  commands: [["make", "test"]]
  require_no_new_findings: true

Why sarifix

Built to be trusted
with your repos.

Scanner-agnostic

Four SARIF producers are tested in the fixture, one of them a 25-line shell script. A new tool is one scanners entry.

Stable identity

Line numbers never count, and edits inside a flagged resource don't change the identity of its other findings.

Errors you can act on

28 load-time checks. Each error names the file, the key path and the line. Exit code 2 means a config error.

Workflows are off limits

.github/workflows/** is always in paths.deny, however you layer your config.

Verified or not shipped

Planned: no change is published unless a rescan and your own tests pass. Nothing is ever auto-merged.

Layered config

Put org defaults under a repo file with --org-config. Scanners and campaigns merge by name; the repo wins.

Quick start

From zero to a scan
in 3 commands.

You need Go 1.27 or newer, and whichever scanners your config calls on your PATH. Release binaries are signed with cosign if you prefer those.

Full getting-started guide
  1. Install

    $ go install github.com/rossedman/sarifix/cmd/sarifix@latest
  2. Check your config

    Start from the example in the repo and validate it.

    $ sarifix config validate --config examples/sarifix.yaml
  3. Scan

    One SARIF file per scanner, each result fingerprinted.

    $ sarifix scan

How it works

One pipeline.
Three stages ship today.

Phases 0 and 1 cover ingest, fingerprinting, the baseline diff, filtering, grouping and the report. The agent, verification and the other publish modes follow in phases 2 to 4.

The sarifix pipeline in eight stages: ingest, fingerprint and baseline shipped in phase 0; filter and group shipped in phase 1; fix and verify are phase 2; publish ships report mode today and the other modes in phases 2 to 4.
Tap to open the full-size diagram

Scan your repo
with sarifix.

Free and open source under the MIT license.