Skip to main content

Scan frequency

How often should a project be scanned? The short answer: scan when the source changes, not on a clock to chase new CVEs. A source scan re-reads the dependency tree; new vulnerabilities against an unchanged tree are picked up automatically by the Trivy DB re-match beat, without re-scanning. This page helps you set a cadence that keeps results fresh without flooding the queue or the disk.

Audience

team_admin and super_admin deciding a scanning policy for their teams. Familiarity with CI triggers and the scan lifecycle. This is a decision guide — for recovering a stuck or failed scan, see the on-call runbook.

Two axes that are often confused

A finding surfaces from the combination of two independent inputs. Separating them is the whole decision:

AxisChanges whenKept current by
The SBOM (which components you ship)You add, remove, or bump a dependency — a source change.A source scan re-reading the tree.
The vulnerability data (which CVEs are known)Trivy publishes new advisories against components you already ship.The Trivy DB refresh + re-match beat — no re-scan.

Software Bill of Materials (SBOM) is the machine-readable inventory of components a scan produces. CVE is Common Vulnerabilities and Exposures, the public identifier for a known vulnerability.

The mistake is scheduling nightly re-scans "so we catch new CVEs". You do not need to — TRUSCA already re-matches existing SBOMs against the refreshed database on a beat. Scheduling scans to chase CVE freshness only burns queue slots and disk.

Scan on source change

Trigger a scan on the events that actually change the SBOM:

  • Every pull / merge request — so a reviewer sees the risk delta of a dependency change before it merges. This is where the build gate earns its keep.
  • Every push to a protected branch (main, release/*) — so the branch's live snapshot always reflects what is merged.
  • Tag / release builds — with a release label so the SBOM is kept as a permanent compliance record (see scan retention).

The CI templates wire this for you and forward the ref so each branch and PR groups into its own retention target:

A lockfile change is the real trigger

If your CI is chatty, gate the scan step on changes to dependency manifests (package-lock.json, pom.xml, go.mod, requirements.txt, …). A documentation-only commit does not change the SBOM, so it does not need a scan. This trims the queue without missing a single dependency change.

Let the beat handle CVE freshness

You do not schedule scans to detect newly disclosed CVEs against dependencies you already ship. Two background jobs cover that:

  1. The Trivy DB refresh pulls the updated vulnerability database (weekly by default). See Vulnerability data.
  2. The re-match beat re-evaluates existing SBOMs against the refreshed data every few hours and raises a cve_detected notification for anything new — the user-facing view of this is Re-detection.

So an idle project with no source changes still gets new-CVE alerts. Cadence is about source changes, freshness is about the database — and the database is already handled.

A stale Trivy DB silently starves re-detection

The re-match beat is only as fresh as the database it reads. If the Trivy DB refresh has been failing, new CVEs stop landing even though scans still succeed. This is a data-freshness incident, not a scan-frequency decision — diagnose and recover it with on-call runbook Scenario 1. Watch the Vulnerability data card on /admin/health for staleness.

A cadence that scales

Match the trigger to the branch's role rather than applying one rule everywhere:

Branch / eventRecommended triggerWhy
Pull / merge requestScan on every PR, gate the mergeCatch a risky dependency before it lands.
main / protected branchesScan on every pushKeep the live snapshot honest.
Release tagScan once, with a release labelPermanent SBOM of a shipped version.
Long-lived, low-churn servicePR + push only; no scheduleThe beat covers new CVEs; source rarely moves.
Vendored / third-party importsScan when the vendored tree changesNo package manager event fires on its own.

The one place a scheduled scan earns its slot is a project whose dependencies drift without a commit — for example a build that resolves a floating version range at build time. There, a weekly scheduled scan re-pins the observed tree. Everything else is better served by source-change triggers plus the re-match beat.

Retention keeps this affordable: only the latest scan per branch or PR stays live, superseded snapshots are reclaimed after a grace window, and release-labelled scans are kept forever. Tune the windows in scan retention so a high-PR-volume repository does not fill the disk.

Verify it worked

Review your scanning policy against these checks:

  1. Opening a PR that changes a dependency manifest triggers a scan and a build-gate verdict on the PR — not a documentation-only PR.
  1. A push to main produces a new live snapshot for the main target (the previous one is marked superseded in the project's scan history).
  1. A project with no recent source scans still shows new cve_detected notifications after a Trivy DB refresh — proof the re-match beat, not a schedule, is carrying CVE freshness.
  1. The /admin/health Vulnerability data card reports a recent refresh (freshness fresh), so the beat has current data to match against.
  1. You are not running nightly re-scans purely to catch CVEs — if you are, remove them and rely on the beat.

See also