Finding baselines
Keep accepted package findings visible without failing audits.
Last updated July 27, 2026View source (v0.20.2)
Finding baselines let a project keep known package findings visible without
letting those findings fail an audit. Bomly automatically looks for
.bomly/baseline.json when scan, diff, or explain runs against a project.
A matching finding is still emitted with the same package, advisory, severity,
and reasons, but its policy status becomes suppressed. Machine-readable
findings expose the status as policy_status.
Create and maintain a baseline
Baseline creation runs the normal audited project pipeline and therefore requires explicit enrichment:
bomly baseline create --enrich
bomly baseline inspect
bomly baseline inspect --path ../another-project
Creation refuses to overwrite an existing file. baseline update --enrich
accepts current new or changed findings while retaining historical entries.
baseline prune --enrich removes accepted entries absent from a complete
current audit and never accepts new findings. All writes use a temporary file
and atomic replacement. Lifecycle commands are limited to writable local
filesystem projects and refuse to mutate a baseline when the scan reports
degraded detector, matcher, analyzer, or auditor coverage.
Use --analyze for lifecycle commands when the audited CI workflow also uses
reachability analysis. The baseline records that policy state as a safety bound.
Selection
The shared --baseline option accepts:
auto(default): use.bomly/baseline.jsonwhen present;none: disable baseline consumption;- a relative or absolute path: require that baseline file.
A relative path is resolved from the project root. During a Git diff it is resolved independently in the materialized base and head trees, so each side uses the baseline committed with that project state. The merge base selected by Bomly Guard is simply the diff's base tree.
Automatic discovery also applies to --url targets, using the baseline
committed in the checked-out repository. Use --baseline none when that
project policy should not participate in evaluation, or provide an explicit
path to use a different baseline. At -v, Bomly logs every detected baseline
with its path, entry count, selection mode, and target kind. Audit completion
logs include the baseline path, entries, findings evaluated, and findings
accepted, including when those counts are zero.
If automatic discovery sees a symbolic-link .bomly directory or
baseline.json, Bomly warns and behaves as though no project baseline exists.
This rejects links discovered during path inspection; it does not protect
against another process replacing a path between inspection and reading. An
explicit --baseline <path> is different: it is a trusted path selected by the
user and may refer to a symbolic link or a file outside the project.
Container targets have no reliable project root, so they require an absolute baseline path. For a standalone SBOM file, automatic discovery starts beside the file; an explicit path is recommended when the baseline lives elsewhere.
policy:
baseline: auto
Identity and portability
Entries identify the full package PURL (including version), finding kind, auditor, and either advisory identifiers or a stable policy rule. They do not contain dependency node IDs, manifest paths, subproject names, project names, or mutable finding prose.
A baseline can therefore be copied to another project and suppresses the same finding for the same package version there. It does not automatically suppress the finding after a package version changes. Advisory aliases are retained so equivalent identifiers can match across enrichment sources.
{
"schema_version": "bomly.finding-baseline/v1",
"entries": [
{
"package_ref": "pkg:npm/example@1.0.0",
"kind": "package",
"auditor": "package",
"rule_id": "denied-package",
"severity": "high",
"policy_status": "fail"
}
]
}
Structured findings expose rule_id, so a non-vulnerability entry can be
reviewed or authored without relying on mutable finding titles.
Severity, failing policy status, and reachability state are recorded as safety
bounds. An escalation remains unsuppressed until baseline update explicitly
accepts it. A safer reachability result remains accepted: for example, a
finding recorded as unknown stays suppressed if analysis later proves it
unreachable, but becomes gating if analysis reports it reachable.
Output and automation
Baselines do not add report sections or collections. Findings remain in their
normal scan, explain, and diff locations. JSON and MCP expose the
policy_status field; text, Markdown, and the TUI call it the policy status;
SARIF marks the result as externally suppressed at note level; and
Bomly Guard continues consuming the ordinary diff output and exit status.
The CLI output schema identifier remains 1.0.
Baseline failures do not hide pipeline diagnostics. A malformed explicitly selected file fails before the audit runs. An automatically discovered baseline is loaded only for audited commands, so a malformed file cannot break a plain inventory scan; audited commands fail closed rather than silently ignoring it. Bomly rejects baseline files larger than 16 MiB and baseline documents with more than 10,000 entries.