start

Use cases

Recipes for PR gates, SBOMs, triage, and license and offline scans.

Recipes for the jobs people actually use Bomly for. Each one is a goal, the command that does it, what you get back, and where to go deeper. New to Bomly? Start with Getting Started first.

Gate a pull request on new vulnerabilities

Goal: fail a PR when it introduces a high-severity vulnerability, without nagging about pre-existing ones.

bomly diff --base main --head HEAD --enrich --audit --fail-on high

diff classifies findings as introduced / resolved / persisted and only --fail-on matches against the introduced set, so a clean PR passes even on a repo with known debt. Exit code 2 means a new high finding; see Exit codes.

→ Turnkey version for GitHub PRs: the Bomly Guard action (setup).

Generate and publish an SBOM

Goal: produce SPDX and CycloneDX SBOMs as build artifacts.

bomly scan -o spdx=sbom.spdx.json -o cyclonedx=sbom.cdx.json

Both files are written in one pass from the same resolved graph. Use --format spdx (or cyclonedx) to stream a single SBOM to stdout instead. Details: SBOM formats.

Triage vulnerabilities by reachability

Goal: cut a long advisory list down to the ones your code actually calls.

bomly scan --enrich --audit --analyze --fail-on high --fail-on reachable

--analyze annotates each advisory with a reachability status; combining --fail-on high --fail-on reachable fails only on advisories that are both high severity and reachable. Reachability is experimental and tier-dependent — an unknown status is not "safe." Read Reachability before relying on this gate.

Enforce a license policy

Goal: block dependencies under licenses you can't ship.

# Allowlist: permit only these, fail on anything else
bomly scan --enrich --audit \
  --allow-license MIT --allow-license Apache-2.0 --allow-license BSD-3-Clause \
  --fail-on any

Licenses are matched as SPDX expressions. Use --deny-license to block specific licenses instead of allowlisting, and --license-exempt-package to waive one package. See the license auditor.

Catch typosquats and banned packages

Goal: flag dependency names that impersonate packages you trust, or that you've banned outright.

bomly scan --audit \
  --protected-package react --protected-package lodash \
  --typosquat-threshold 0.85 \
  --deny-package event-stream \
  --fail-on any

This check is name-based and needs no enrichment, so it runs fully offline. See the package auditor.

Scan offline / air-gapped

Goal: analyze dependencies with zero outbound network calls.

bomly scan                         # native detectors + lockfiles, no network
bomly scan --sbom --path sbom.json # audit an SBOM you already have

Without --enrich, matchers make zero outbound HTTP calls. Note that some build-tool detectors (Go, Maven, Gradle) may fetch packages during normal resolution — pre-warm the local cache or commit a lockfile to stay fully offline. See Detectors → Network behavior.

Scan and audit a container image

Goal: find what's inside an image and gate on it.

# Inventory an image (native lockfile detectors in layers + Syft for OS packages)
bomly scan --container ghcr.io/example/app:latest

# Audit an image and fail on high-severity vulnerabilities
bomly scan --container ghcr.io/example/app:latest --enrich --audit --fail-on high

# Generate an SBOM from an image
bomly scan --container ghcr.io/example/app:latest -o spdx=image.spdx.json

# Pin by digest for a reproducible scan
bomly scan --container ghcr.io/example/app@sha256:<digest> --enrich --audit

Bomly pulls the image using your host's registry credentials — the same ones docker/podman use — so private images work once you've authenticated (docker login ghcr.io). Native detectors still parse lockfiles found in layers; everything else falls through to Syft. See Scan targets for the full container behavior and exit codes.

Gate a base-image upgrade in CI

      - name: Install Bomly
        run: curl -sSfL https://github.com/bomly-dev/bomly-cli/releases/latest/download/bomly_linux_amd64.tar.gz | tar -xz -C /usr/local/bin bomly
      - name: Audit the built image
        run: bomly scan --container ${{ env.IMAGE }}:${{ github.sha }} --enrich --audit --fail-on high --format sarif > image.sarif

Exit code 2 fails the job on a policy violation; upload image.sarif to the Security tab as in CI Integration.

Diff two releases

Goal: see what changed in your dependency tree between two versions.

# Between Git refs
bomly diff --base v1.2.0 --head v1.3.0 --enrich --audit

# Between two SBOM files (no checkout needed)
bomly diff --sbom --base old.spdx.json --head new.spdx.json

# Between two tags (or digests) of the same container image
bomly diff --container ghcr.io/example/app --base 1.4.0 --head 1.5.0 --enrich --audit --fail-on high

You get added, removed, and updated dependencies, plus introduced/resolved findings when --audit is set. Great for release notes, upgrade reviews, and catching what a base-image bump dragged in.

Understand why a dependency is there

Goal: find the path that pulled a transitive package into your build.

bomly explain lodash

explain prints the dependency path(s) that introduced the package. Add --audit to see findings in that path's context.

Explore results interactively

Goal: browse a scan without parsing JSON.

bomly scan --enrich --interactive

Opens the terminal UI to navigate packages, findings, and dependency paths. Keybindings: TUI.

See also