concepts

Auditors

How Bomly turns vulnerability data into actionable findings.

Auditors evaluate a dependency graph against policy and produce findings. They are how a scan becomes a pass/fail signal in CI.

Auditors run after detectors and matchers. They never make network calls of their own — they only look at the data that detectors put on the graph and matchers attached to it. To audit fresh vulnerability data, combine --enrich with --audit:

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

--audit alone is useful when you have ingested an SBOM that already carries vulnerability data, or when a matcher ran in a previous step.

Built-in auditors

AuditorChecksPolicy flags
vulnerabilityEnriched advisories vs. severity / allowlist policy--fail-on, --allow-vulnerability-id
licensePackage licenses vs. allow/deny SPDX policy--allow-license, --deny-license, --license-exempt-package
packageDenied packages and typosquatted names--deny-package, --deny-group, --protected-package, --typosquat-threshold, --typosquat-mode

Select a subset with the --auditors selector (e.g. --auditors license). See the per-auditor reference for options, examples, and limitations. Auditors are also a plugin extension point — for a worked example of an external auditor, see the Meme Dependency Auditor.

When auditors run

  • bomly scan --audit evaluates the full graph.
  • bomly explain --audit evaluates the dependency-path context for a single package.
  • bomly diff --audit classifies introduced, resolved, and persisted findings between two graphs.

Findings

A finding is Bomly's normalized record of a policy match. Every finding has:

FieldMeaning
IDIdentifier of the underlying signal (e.g. CVE-2024-12345, GHSA-xxxx-yyyy-zzzz)
KindWhat kind of finding (vulnerability, license, lifecycle)
Severitycritical / high / medium / low / unknown
PackageThe package name, version, and PURL it applies to
TitleHuman-readable summary
ReasonsWhy the finding matched policy (e.g. severity threshold, reachable symbol)
SourceWhich matcher produced the underlying data

Text output (--format text, default) groups findings by package and severity. JSON (--json or --format json) exposes the full shape for automation. SARIF 2.1.0 (--format sarif) emits a static-analysis report any tool that consumes SARIF can ingest.

--format sarif requires --audit. A SARIF document only makes sense when there are findings.

Severity grammar

Severity levels in precedence order, lowest to highest:

unknown  <  low  <  medium  <  high  <  critical

The any token matches every severity, including unknown.

--fail-on

--fail-on is the only knob that turns a finding into a non-zero exit code. It accepts one of the severity tokens, or the reachability token reachable:

TokenMatches
anyevery finding
lowfindings with severity ≥ low
mediumfindings with severity ≥ medium
highfindings with severity ≥ high
criticalfindings with severity = critical
reachablefindings where reachability status is reachable (experimental — see REACHABILITY.md)

Repeat the flag to AND constraints together:

# Fail on any high or critical finding
bomly scan --enrich --audit --fail-on high

# Fail only when a high-or-above finding is also reachable
bomly scan --enrich --audit --analyze \
  --fail-on high --fail-on reachable

Tokens are case-insensitive. An invalid token produces an exit-code 4 (invalid input) with the message: unsupported --fail-on value "<x>" (accepted: any, low, medium, high, critical, reachable).

Exit codes from auditors

CodeTrigger
0Scan succeeded; no policy match for --fail-on
2Policy violation — at least one finding matched --fail-on
4Invalid --fail-on value

See EXIT_CODES.md for the full table.

Diff and auditing

bomly diff --audit classifies findings between two graphs into three buckets:

  • Introduced — present in head, absent in base
  • Resolved — present in base, absent in head
  • Persisted — present in both

Combine with --fail-on to fail PRs that introduce new high-severity findings without complaining about pre-existing ones:

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

Configure with a YAML file

Compliance policy is usually the same across every scan, so set it once in a config file instead of repeating CLI flags. All auditor settings live under the policy key:

policy:
  fail_on: [high, reachable]              # severity / reachability gates
  allow_vulnerability_ids: [GHSA-xxxx-yyyy-zzzz]
  allow_licenses: [MIT, Apache-2.0, BSD-3-Clause]
  deny_licenses: [GPL-3.0-only]
  license_exempt_packages: [my-internal-lib]
  deny_packages: [event-stream]
  deny_groups: [com.evil]
  protected_packages: [react, lodash]
  typosquat_threshold: "0.90"
  typosquat_mode: warn                    # warn | fail
  warn_only: false

Bomly merges configuration from these sources, in increasing precedence:

  1. User-level ~/.bomly/config.yaml — your defaults across every project.
  2. Repo-level <project>/.bomly/config.yaml — committed policy shared by the team (the usual home for a compliance policy).
  3. --config <path> — an explicit file.
  4. BOMLY_* environment variables.
  5. CLI flags.

So a checked-in .bomly/config.yaml defines the team policy, and a CLI flag still overrides it for a one-off run. Every key is listed in CONFIG_REFERENCE.md.

See also