Documentation
¶
Overview ¶
Package feeds fetches and caches the exploitability datasets Draugr can enrich findings with: CISA's Known Exploited Vulnerabilities catalog and FIRST's EPSS scores.
Fetching is never implicit. A scan that silently reaches the internet is not reproducible, and the gate has to be. So the network is touched when someone asks for it, by running `draugr feeds update` or by passing `auto`, and a scan otherwise reads a local cache with no network access at all. That keeps the air-gapped path and the connected path the same code.
The cache records where each feed came from and when, because "we escalated this to critical because it was on KEV as of 2026-08-01" is an auditable statement and "KEV said so" is not.
Index ¶
- Constants
- Variables
- func CheckGoVulnDB(path string) error
- func Describe(n Name) string
- func Dir() (string, error)
- func HumanAge(d time.Duration) string
- func HumanBytes(n int64) string
- func Load(dir string) map[Name]Record
- func Path(dir string, n Name) string
- func URL(n Name) string
- type LocalGoVulnDB
- type Name
- type Record
Constants ¶
const DefaultMaxAge = 24 * time.Hour
DefaultMaxAge is how old a cached feed may be before `auto` refetches it and a scan warns.
One day, because EPSS is republished daily: a score is a 30-day probability recomputed every morning, so a week-old copy silently mis-ranks. KEV changes far less often and is held to the same bar deliberately, two staleness rules to explain is worse than one that is slightly strict for one feed.
Variables ¶
var ErrNoLocalGoVulnDB = errors.New("no local Go vulnerability database")
ErrNoLocalGoVulnDB means no local copy of the Go vulnerability database has been fetched.
Functions ¶
func CheckGoVulnDB ¶ added in v0.133.0
CheckGoVulnDB reports whether path holds a Go vulnerability database govulncheck can answer from: an index that parses, and at least one module in it.
The shape is the documented offline form (`index/db.json`, `index/modules.json`, `ID/*.json`). Both checks exist because govulncheck reports "No vulnerabilities found" against a database that is empty or unreadable, and a scan must never read that as a clean result.
func HumanAge ¶ added in v0.135.0
HumanAge renders a duration the way someone reads a staleness report: the largest unit that still says something useful, and never more precision than the answer deserves.
func HumanBytes ¶ added in v0.135.0
HumanBytes renders a size in the largest unit that keeps it under four digits.
func Load ¶
Load reads the manifest. A missing or unreadable manifest is an empty one: the feeds it described are then treated as absent, which is the safe direction, worst case a refetch.
Types ¶
type LocalGoVulnDB ¶ added in v0.133.0
LocalGoVulnDB is a local copy of the Go vulnerability database that passed its checks.
func FindGoVulnDB ¶ added in v0.133.0
FindGoVulnDB returns the cached Go vulnerability database if it is usable as of now: fetched, no older than maxAge, and structurally sound. The error names the check that failed.
Age is measured from when Draugr fetched the copy, not from the database's own modified date, which moves only when an advisory changes and so can lag a copy fetched this morning by days.
type Name ¶
type Name string
Name identifies a feed.
type Record ¶
type Record struct {
URL string `json:"url"`
FetchedAt time.Time `json:"fetchedAt"`
SHA256 string `json:"sha256"` // of the decompressed bytes on disk
Bytes int64 `json:"bytes"`
}
Record is what the cache knows about one fetched feed.
func Fetch ¶
Fetch downloads one feed into dir, decompressing it if the upstream is gzipped, and records what it fetched. It returns the resulting cache entry.
The write is atomic: a temporary file in the same directory, renamed into place. A fetch interrupted halfway must not leave a half a catalog behind for the next scan to parse as though it were complete.