sarif-dockerfile-anchor

module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 29, 2026 License: Apache-2.0

README

sarif-dockerfile-anchor

Anchor Microsoft Defender Vulnerability Management (MDVM) container-image SARIF findings to the Dockerfile lines that introduced the vulnerable packages, so GitHub code scanning renders them as pull-request inline annotations and diff gates — the same experience CodeQL gives on source code.

Defender for Cloud's container scan reports every finding at the image reference (for example myregistry.azurecr.io/app line 1). GitHub code scanning can only annotate a pull request on a changed line of a file in the repository, so those findings never appear inline on the PR diff. This tool rewrites each OS-package finding's location to the Dockerfile instruction that introduced the package.

Generalized, reusable port of an internal remap script. Single tool, no extra services; reads the SARIF + a CycloneDX SBOM + your Dockerfile.

How it classifies findings

Finding kind Decided by Anchored to
Injected OS package name appears in the Dockerfile as a <name>_…deb filename or <name>= apt pin the install/download line (any severity)
Base-image OS package OS package not present in the Dockerfile the final-stage FROM line (kept only for --base-severity)
Application / language package SBOM purl type is not an OS/distro type (e.g. pkg:maven/…, pkg:npm/…) left at the image reference (Dependabot / CodeQL territory)
  • OS vs application is decided from the CycloneDX SBOM purl type: the distro/system types deb, rpm, apk, alpm, qpkg, yocto (purl spec) are treated as OS packages; everything else (maven, npm, pypi, golang, nuget, conda, conan, generic, …) is application/language.
  • Base-image findings anchor to the Dockerfile's final-stage FROM (the last FROM), since the scanned image is always built from that stage — no base image needs to be supplied.
  • A stable partialFingerprints (sha1(ruleId + package)) keeps alerts from churning across re-runs.

The original SARIF is never modified: the enriched document is written to stdout (or --output) and a one-line summary goes to stderr.

Install

Download a prebuilt static binary from the releases page, or build from source:

go install github.com/fuj1g0n/sarif-dockerfile-anchor/cmd/sarif-dockerfile-anchor@latest

CLI usage

The input files come from the Defender for Cloud CLI (see Inputs from the Defender CLI):

sarif-dockerfile-anchor \
  --sarif        image.sarif \
  --sbom         sbom.cyclonedx.json \
  --dockerfile   Dockerfile \
  --output       image.enriched.sarif
# summary (injected / base / left-at-image counts) is printed to stderr
Flag Required Default Description
--sarif yes Defender CLI image-scan SARIF
--sbom yes CycloneDX SBOM JSON (OS/app classification via purl)
--dockerfile yes Dockerfile to anchor findings to
--base-severity no high,critical severities of base-image OS findings kept inline
--dockerfile-uri no value of --dockerfile repo-relative URI written into the SARIF; override only when the file read differs from its committed path (e.g. an absolute --dockerfile, or a generated/rendered Dockerfile)
--output no stdout where to write the enriched SARIF
Inputs from the Defender CLI

The Defender for Cloud CLI produces these files (verified with CLI v2.0.3334.114):

# Image scan: writes its scan SARIF to --defender-output (default: defender.sarif
# in the working directory). Give it an explicit name so the SBOM scan below
# cannot overwrite it.
defender scan image "$IMAGE" --defender-output image.sarif

# SBOM scan: --output names the CycloneDX file (default sbom-finding-<timestamp>.json,
# timestamp YYYYMMDD-HHMMSS; --sbom-format default cyclonedx1.6-json).
defender scan sbom "$IMAGE" --output sbom.cyclonedx.json

[!IMPORTANT] defender scan image and defender scan sbom BOTH default their scan SARIF to defender.sarif in the working directory (the --defender-output default). Run in the same directory without distinct names, the SBOM scan (which reports malicious packages — usually none) overwrites the image scan's SARIF with an empty one. Always give the image scan an explicit --defender-output.

[!NOTE] The exported image SARIF holds Critical/High/Medium findings; Low-severity findings are excluded by default in the tested CLI version. All findings are located at the image reference (line 1) — which is exactly what this tool remaps.

GitHub Actions usage

- name: Defender for Cloud image scan + SBOM
  run: |
    # Give the image scan a distinct --defender-output; the SBOM scan's own scan
    # SARIF also defaults to defender.sarif and would otherwise overwrite it.
    ./defender scan image "$IMAGE" --defender-output image.sarif
    ./defender scan sbom  "$IMAGE" --output sbom.cyclonedx.json

- name: Anchor MDVM SARIF to Dockerfile
  id: anchor
  uses: fuj1g0n/sarif-dockerfile-anchor@v1
  with:
    sarif: image.sarif
    sbom: sbom.cyclonedx.json
    dockerfile: Dockerfile
    output: image.enriched.sarif

- name: Upload to code scanning
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: ${{ steps.anchor.outputs.sarif }}
    category: defender-mdvm

The composite action downloads the matching release binary for the runner's OS/architecture; no Python or other runtime is required on the runner.

Development

This repo uses devbox for a reproducible Go toolchain:

devbox run -- go test ./...
devbox run -- go build ./...

License

Apache-2.0

Directories

Path Synopsis
cmd
sarif-dockerfile-anchor command
Command sarif-dockerfile-anchor rewrites Microsoft Defender (MDVM) container-image SARIF so that OS-package findings are anchored to the Dockerfile lines that introduced the packages, enabling GitHub code scanning pull-request inline annotations and diff gates.
Command sarif-dockerfile-anchor rewrites Microsoft Defender (MDVM) container-image SARIF so that OS-package findings are anchored to the Dockerfile lines that introduced the packages, enabling GitHub code scanning pull-request inline annotations and diff gates.
internal
anchor
Package anchor rewrites Microsoft Defender (MDVM) container-scan SARIF result locations so that OS-package findings point at the Dockerfile line that introduced the package, instead of the opaque image reference.
Package anchor rewrites Microsoft Defender (MDVM) container-scan SARIF result locations so that OS-package findings point at the Dockerfile line that introduced the package, instead of the opaque image reference.
cyclonedx
Package cyclonedx provides a minimal reader for CycloneDX SBOM JSON that indexes component names by the ecosystem type encoded in their package URL (purl).
Package cyclonedx provides a minimal reader for CycloneDX SBOM JSON that indexes component names by the ecosystem type encoded in their package URL (purl).
dockerfile
Package dockerfile parses a Dockerfile into lines and answers the two location questions the anchoring logic needs:
Package dockerfile parses a Dockerfile into lines and answers the two location questions the anchoring logic needs:

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL