feeds

package
v0.60.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 3, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

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

View Source
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

This section is empty.

Functions

func Describe

func Describe(n Name) string

Describe returns a human-readable name for a feed, or "" if it is not a known one.

func Dir

func Dir() (string, error)

Dir is the feed cache, ~/.draugr/feeds.

func Load

func Load(dir string) map[Name]Record

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.

func Path

func Path(dir string, n Name) string

Path is where a feed's data lives inside dir, decompressed and ready to parse.

func URL

func URL(n Name) string

URL returns the upstream a feed is fetched from, or "" if it is not a known one.

Types

type Name

type Name string

Name identifies a feed.

const (
	KEV  Name = "kev"
	EPSS Name = "epss"
)

The feeds Draugr knows how to fetch.

func Names

func Names() []Name

Names lists every known feed, in the order commands should present them.

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

func Fetch(ctx context.Context, dir string, n Name, client *http.Client) (Record, error)

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 catalogue behind for the next scan to parse as though it were complete.

func (Record) Age

func (r Record) Age(now time.Time) time.Duration

Age reports how long ago the feed was fetched, as of now.

func (Record) Stale

func (r Record) Stale(now time.Time, maxAge time.Duration) bool

Stale reports whether the feed is older than maxAge. A maxAge of zero or less means never stale — the caller has said it does not care, which is a legitimate thing to say on a runner that is deliberately pinned to a known copy.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL