Search

Search the docs, blog, and marketplace.

How it works

Auditors

How Bomly turns vulnerability data into actionable findings.

Last updated July 30, 2026View source (v0.21.1)

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

The CLI requires --enrich with --audit. Auditors themselves do not make network calls; the selected matchers decide whether enrichment uses the network.

Built-in auditors

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

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 controls vulnerability findings by severity, reachability, or known exploitation. It also provides the diff-only source-change gate for package findings. Other policy flags, such as --deny-package, can create failing findings directly.

It accepts these tokens:

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)
exploitablevulnerability findings marked as known exploited by enrichment data
source-changediffs where a dependency changes from a known source to Git or an arbitrary URL

Repeat vulnerability constraints to AND them together. source-change is an independent package gate, so combining it with vulnerability constraints fails when either the source gate or the complete vulnerability constraint set matches:

Used by itself, source-change leaves vulnerability findings unchanged. It can only match dependency transitions from bomly diff; it has no effect on scan or explain.

# 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

# Fail only on high-or-critical vulnerabilities with known exploitation
bomly scan --enrich --audit \
  --fail-on high --fail-on exploitable

# Fail on high-or-critical vulnerabilities or dependency source changes
bomly diff --base main --head HEAD --enrich --audit \
  --fail-on high --fail-on source-change

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, exploitable, source-change).

Minimal CI policy

Start with one explicit severity gate:

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

This fails on high and critical findings while keeping lower-severity findings visible in the report. Add license, denied-package, protected-package, reachability, or exploitability controls only when your team has defined the corresponding review and exception process. A larger policy is not inherently a safer policy if nobody owns its exceptions.

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

The diff audit only inspects packages the change touched, so findings on unchanged packages never appear — that is how pre-existing debt stays out of PR reviews. Both remaining buckets gate: --fail-on fails on introduced findings and on persisted ones, because a persisted finding means the changed package still ships a known issue at its new version:

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
  baseline: auto                          # auto | none | path

Bomly merges configuration from these sources, in increasing precedence:

  1. User-level ~/.bomly/config.yaml — your defaults across every project.
  2. --config <path> or BOMLY_CONFIG — an explicitly trusted file.
  3. BOMLY_* environment variables.
  4. CLI flags.

Repository config files are never loaded automatically. A team may commit .bomly/config.yaml, but each invocation must select it explicitly with --config .bomly/config.yaml or BOMLY_CONFIG. When both are set, --config wins. Every key is listed in CONFIG_REFERENCE.md.

Finding baselines

A project may commit .bomly/baseline.json to suppress accepted package findings without removing them from reports. Policy-status resolution is part of auditing: auditors first emit ordinary findings, then the audit stage marks compatible entries suppressed. It never removes a finding or suppresses pipeline diagnostics. If automatic discovery finds a symbolic link at the conventional baseline path, Bomly warns and behaves as though no baseline exists. An explicit --baseline <path> remains a trusted user-selected path. See Finding Baselines.

See also