chore: replace em dashes with hyphens, add no-em-dash rule to CLAUDE.md
Chart Release / chart (push) Successful in 20s
Server Deploy / deploy (push) Failing after 1m52s

This commit is contained in:
2026-09-10 09:18:55 +00:00
parent b36a696d0e
commit 6ee203f5e9
172 changed files with 860 additions and 856 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ type Advisory struct {
// state, not an absence of data, and callers must treat it as vulnerable.
FixedVersion string
Severity string
// Status is filled by trivy-db ONLY when FixedVersion is empty when there
// Status is filled by trivy-db ONLY when FixedVersion is empty - when there
// is a fix, "fixed" is the obvious state and the field is left zero. It is
// what separates "the vendor confirms this package is affected and has not
// fixed it" from "nobody has looked yet".
+2 -2
View File
@@ -8,7 +8,7 @@ type VulnSource interface {
// MetaCache enriches match results with the CVE's own metadata.
//
// This is not an optimisation, it is where severity comes from. Debian, Ubuntu
// and Alpine advisories carry no severity of their own trivy-db leaves
// and Alpine advisories carry no severity of their own - trivy-db leaves
// Advisory.Severity zero for those buckets and keeps the rating in the
// vulnerability bucket's VendorSeverity map instead. Taking the advisory's
// value alone reported an entire fleet as "unknown".
@@ -27,7 +27,7 @@ func NewMetaCache(src VulnSource) *MetaCache {
// Enrich fills severity, title, score and references in place.
//
// The advisory's severity is kept when the vulnerability bucket has nothing
// better to say RHEL does publish it per advisory so this can only raise
// better to say - RHEL does publish it per advisory - so this can only raise
// the quality of the answer, never lower it.
func (m *MetaCache) Enrich(results []Result) {
if m == nil {
+10 -10
View File
@@ -16,7 +16,7 @@ type AdvisorySource interface {
// Result is one vulnerable package on one server, before it becomes a finding.
//
// Severity, Title, CVSSScore and References are only as good as the advisory
// until MetaCache.Enrich has run over them for the Debian-family buckets the
// until MetaCache.Enrich has run over them - for the Debian-family buckets the
// advisory carries no severity at all, so an unenriched Result reads "unknown".
type Result struct {
CVEID string
@@ -33,7 +33,7 @@ type Result struct {
//
// Vulnerable means: no fix has been published, or the installed version sorts
// strictly before the fixed version under the distribution's own ordering.
// Equal is NOT vulnerable that is the backported-fix case, where a
// Equal is NOT vulnerable - that is the backported-fix case, where a
// distribution patches in place without changing the upstream version, and
// treating it as vulnerable reports a patched fleet as exposed.
func Match(src AdvisorySource, os models.OSRelease, pkgs []models.InstalledPackage) ([]Result, error) {
@@ -47,7 +47,7 @@ func Match(src AdvisorySource, os models.OSRelease, pkgs []models.InstalledPacka
var advisoryCount, skipped, unactionable, noFix int
// Advisories are keyed on the SOURCE package, and several hundred binary
// packages on a host resolve to the same few hundred sources linux-modules,
// packages on a host resolve to the same few hundred sources - linux-modules,
// linux-image and linux-headers all ask about "linux", whose advisory list is
// thousands long. Without this the same bolt read is repeated once per binary
// package, which is most of what made a single Ubuntu host take minutes.
@@ -78,7 +78,7 @@ func Match(src AdvisorySource, os models.OSRelease, pkgs []models.InstalledPacka
for _, a := range advs {
// No published fix. Whether that is a finding depends entirely on the
// status the vendor attached to it see actionable().
// status the vendor attached to it - see actionable().
if a.FixedVersion == "" {
if !actionable(a.Status) {
unactionable++
@@ -97,7 +97,7 @@ func Match(src AdvisorySource, os models.OSRelease, pkgs []models.InstalledPacka
if err != nil {
// Skip this one advisory rather than failing the whole server:
// one unparseable version must not blind us to every other CVE
// on the host. Log it a silent skip is a silent false
// on the host. Log it - a silent skip is a silent false
// negative, which is the direction that hurts.
log.Printf("vulndb: compare %s %s vs %s: %v", p.Name, p.Version, a.FixedVersion, err)
skipped++
@@ -127,8 +127,8 @@ func Match(src AdvisorySource, os models.OSRelease, pkgs []models.InstalledPacka
// necessary: Ubuntu encodes the ABI in the binary name, so an upgrade INSTALLS
// linux-headers-6.8.0-137 beside linux-headers-6.8.0-124 rather than replacing
// it, and the old one lingers until an autoremove. Matched per binary package,
// a fully patched host reports every superseded ABI package as vulnerable
// which is the noise this exists to stop and reports it twice over, once for
// a fully patched host reports every superseded ABI package as vulnerable -
// which is the noise this exists to stop - and reports it twice over, once for
// linux-headers-6.8.0-124 and again for its -generic sibling.
//
// The version, not the name, decides. There is no kernel special case here: a
@@ -176,7 +176,7 @@ func newestPerSource(family string, pkgs []models.InstalledPackage) []models.Ins
// actionable decides whether an advisory with no fixed version is a finding.
//
// trivy-db fills Status only when FixedVersion is empty, and Ubuntu publishes a
// status for every CVE against every source package it ships the vast
// status for every CVE against every source package it ships - the vast
// majority being "under_investigation" (the tracker's needs-triage), meaning
// nobody has yet established that the package is affected at all. Reporting
// those produced ~24,000 findings for a single 797-package host, which is not a
@@ -185,11 +185,11 @@ func newestPerSource(family string, pkgs []models.InstalledPackage) []models.Ins
//
// What survives is what the vendor has confirmed: affected, will_not_fix,
// fix_deferred, end_of_life. Those are exactly the findings the CLAUDE.md rule
// is about an empty fixed_in that means "no fix exists", the one most in need
// is about - an empty fixed_in that means "no fix exists", the one most in need
// of acceptance rather than patching.
// Only the two statuses that positively say "this is not a finding" are
// dropped. "unknown" is kept: a feed that sets no status at all must not become
// a silent false negative, and it is not what generates the noise Ubuntu
// a silent false negative, and it is not what generates the noise - Ubuntu
// states under_investigation explicitly.
func actionable(status string) bool {
switch status {
+2 -2
View File
@@ -25,7 +25,7 @@ const DefaultRef = "ghcr.io/aquasecurity/trivy-db:2"
// SupportedSchema is the trivy-db schema version this code understands.
//
// A different version is refused rather than parsed on the assumption it is
// close enough. Mis-reading the schema would not fail loudly it would return
// close enough. Mis-reading the schema would not fail loudly - it would return
// no advisories, which is indistinguishable from a clean fleet.
const SupportedSchema = 2
@@ -54,7 +54,7 @@ func Disabled() bool {
// DebugEnabled turns on per-package and per-advisory tracing.
//
// It is a switch rather than always-on because a single scan asks the store one
// question per installed package ~2000 lines per server, per tick which
// question per installed package - ~2000 lines per server, per tick - which
// would bury every other subsystem's logs on a fleet of any size. The lifecycle
// logs (pull, tick, per-server totals) are unconditional; only the inner loop
// is gated.
+1 -1
View File
@@ -6,7 +6,7 @@
// epochs and sorts "~" before the empty string, rpmvercmp has its own segment
// rules and treats "~" and "^" differently again, and any ordering that falls
// back on string comparison puts 1.10 before 1.9. Every one of those mistakes
// produces a false negative a vulnerable host reported clean which is the
// produces a false negative - a vulnerable host reported clean - which is the
// failure nobody notices.
package vulndb