-
Notifications
You must be signed in to change notification settings - Fork 1
Security advisories
Two different things are checked, and the report says which is which. Installed
system packages are matched against your distro's security tracker. Separately, the
Python and Node environments the distro does not manage — project venvs, uv/pipx
apps, pip install --user — are matched against OSV. That second half means fettle
walks your filesystem: [advisories] venv_roots (default ["~/src"]) and
venv_depth (default 5) bound the search, and every run prints what it looked at:
What was checked:
arch installed system packages, matched against the Arch Linux security tracker
osv 49 Python environment(s) found on disk — a walk of ~/src (depth 5) plus
uv/pipx apps and pip --user; environments the distro does NOT manage
In the HTML report, a finding that spans several environments expands to show them,
oldest version first — because within one finding the installed versions differ a lot
(pip sat at 11 distinct versions across 44 venvs), and which ones are furthest behind
is what turns a count into a work queue. Plain lines, so a drag-select copies clean paths:
[-] 44 environments
23.2.1 /home/paulda/src/ALEAPP/venv
23.2.1 /home/paulda/src/CVE-Half-Day-Watcher/venv
24.0 /home/paulda/src/CVE-2022-31814/venv
…
26.1.1 /home/paulda/src/bifrost/.venv
The terminal report lists them by a short label and resolves those to full paths at
the end (and in the JSON), because "jetkvm is vulnerable" is not actionable until you
know which jetkvm:
Environments (46) — the short names above, in full:
ALEAPP /home/paulda/src/ALEAPP/venv
jetkvm /home/paulda/src/jetkvm/venv
Exit status: 1 when something is Critical and a fix is already released — the one
case that should stop an automated run. Everything else outstanding is a warning and exits
0, as is a run whose feed data could not be refreshed (reported as such, never as a
clean bill of health).
fettle advisory-check (Arch/Manjaro, Debian, and Ubuntu for OS packages, plus
Python/Node packages via OSV on any distro) tells you, per
installed package: CVEs with a fix you haven't applied yet, and — the distinctive
part — CVEs you're currently vulnerable to with no fix released yet (a heads-up
before an advisory/patch exists). It bulk-fetches the distro's security tracker into
a rebuildable SQLite cache (~/.cache/fettle/advisories.db; sqlite3 is stdlib,
so the core stays dependency-free), refreshed on-run when stale or via
fettle advisory-update.
fettle advisory-update # refresh the local advisory cache
fettle advisory-check # report pending + fix-available CVEs (read-only)The report leads with a Pending fixes callout (vulnerable, no fix yet), then a
severity-banded Fix available table, then the packages the tracker doesn't
cover (AUR/manual/foreign) so a clean result never over-reassures. Version
comparison is delegated to vercmp (Arch) / dpkg --compare-versions (Debian). It's
opt-in (never in the default -a set). On fettle -u/-a it prints a
best-effort security note before the upgrade — how many packages are known-vulnerable,
how many Critical, and which Criticals have no fix released (the only ones an
upgrade cannot address). It never blocks the update: an unpatched CVE is a
pre-existing condition that refusing to upgrade does not fix, and for anything with a
fix released the upgrade is the remedy. It reads only the cached database, so a
network problem can never delay an upgrade either.
[advisories] config: cache_ttl, severity_threshold, exclude_packages (globs),
exclude_classes (hide distro class tags, e.g. Debian ["nodsa","unimportant", "end-of-life"]), ubuntu_pending / ubuntu_pending_severity (opt-in
Ubuntu "no fix yet", below), and venv_roots / venv_depth (where to hunt for
virtualenvs, below). On Manjaro, "fix available" is phrased as possible sync lag, not
alarm.
Language coverage is deliberately limited to what your distro does not
manage — virtualenvs, uv tools, pipx apps, per-user (pip install --user)
installs, bun/nvm Node trees, and cargo installed Rust crates (read from cargo's
own install index, since a crate's binaries need not share its name). A crate built
from a path/git checkout rather than the registry is labelled cargo(path) /
cargo(git), because its version need not be the published release of that name.
Distro-packaged modules (python-requests and
friends) belong to your distro's tracker, which knows about backported fixes; judging
them by PyPI version numbers instead produces both false alarms and duplicate
findings. Each result is labelled by environment (SploitScan:requests), because the
same vulnerable package in three virtualenvs is three things to fix. Virtualenv
discovery is bounded by venv_roots (default ["~/src"]) and venv_depth (default
5) — an unbounded $HOME walk is far too slow to run on every check.
Debian's tracker dump is large (~80 MB); a refresh downloads and parses it once per
cache_ttl. Coverage is by source package; third-party/local.debs aren't separately flagged yet. On Ubuntu, fix-available findings come from the per-release OVAL feed (with Canonical's priority); "vulnerable, no fix yet" (pending) is opt-in via[advisories] ubuntu_pending = true+ubuntu_pending_severity(highby default), sourced from OSV — a real box carries ~1300 pending Ubuntu CVEs, so the severity floor keeps it to a few actionable items. Python/Node packages are checked against OSV on any distro (system-widepip/npm ls -g).