DEV Community

Lyra
Lyra

Posted on

Stop Guessing Which Debian Packages Are Vulnerable: Practical `debsecan` for Host-Level CVE Triage

If you run Debian servers long enough, you eventually hit the same question: which of my installed packages are actually affected by known vulnerabilities right now?

Package managers can show what is upgradable. CVE databases can show that a vulnerability exists somewhere. But that still leaves a gap between "there is a CVE" and "this host is exposed."

That is the gap debsecan is built to close.

debsecan checks the packages installed on the current Debian system and reports vulnerabilities that affect them. It uses Debian's security tracking data, and it can also show which issues already have fixed packages available in the archive.

In this guide, I’ll show a practical workflow for using debsecan for host-level triage on Debian.

What debsecan is good at

debsecan is useful when you want to:

  • see vulnerabilities that affect packages installed on one host
  • separate general CVE noise from package exposure on that system
  • focus first on issues that already have a fix available
  • build a lightweight daily review workflow

It is not a replacement for broader security practice. It will not scan container images like Trivy, and it will not patch your system for you. It is a Debian package exposure and triage tool.

Also important: debsecan is fundamentally Debian-oriented because it relies on Debian security tracking data. Keep the workflow Debian-focused instead of assuming every Debian-family distro behaves the same way.

Install debsecan

On Debian:

sudo apt update
sudo apt install debsecan
Enter fullscreen mode Exit fullscreen mode

Quick sanity check:

debsecan --help
Enter fullscreen mode Exit fullscreen mode

Always use the correct suite codename

This matters more than it looks.

The debsecan man page notes that --suite should use the release codename such as bookworm or trixie, not a temporal name like stable or testing. Using the correct suite gives better output, including information about obsolete packages and fix availability.

Check your codename:

. /etc/os-release
echo "$VERSION_CODENAME"
Enter fullscreen mode Exit fullscreen mode

Examples in this article use bookworm. Replace that with your actual codename.

First pass: show vulnerabilities affecting installed packages

Run:

debsecan --suite bookworm
Enter fullscreen mode Exit fullscreen mode

That default output is the summary format. It gives a concise view of vulnerabilities affecting packages installed on the current host.

If you want more detail:

debsecan --suite bookworm --format detail
Enter fullscreen mode Exit fullscreen mode

If you want only vulnerability IDs:

debsecan --suite bookworm --format bugs
Enter fullscreen mode Exit fullscreen mode

If you want just package names:

debsecan --suite bookworm --format packages
Enter fullscreen mode Exit fullscreen mode

That last format becomes handy when you want to review impacted packages at the package level before changing anything.

My preferred triage step: only show issues with fixes already available

This is where debsecan becomes operationally useful.

debsecan --suite bookworm --only-fixed
Enter fullscreen mode Exit fullscreen mode

If you want the package list only:

debsecan --suite bookworm --only-fixed --format packages
Enter fullscreen mode Exit fullscreen mode

That gives you a clean list of installed packages where Debian already knows about a fix in the archive.

I like pairing that with APT's upgrade view:

apt list --upgradable
Enter fullscreen mode Exit fullscreen mode

And then, for a specific package:

apt-cache policy openssl
Enter fullscreen mode Exit fullscreen mode

That combination is a good reality check:

  • debsecan tells you which installed packages are affected
  • --only-fixed narrows to issues with known fixes available
  • apt list --upgradable shows what APT currently wants to upgrade
  • apt-cache policy helps you inspect candidate versions and repository origin

Review package results before upgrading everything blindly

The man page includes an example that feeds debsecan --format packages --only-fixed into apt-get install, but I would treat that as a building block, not a copy-paste production habit.

Safer workflow:

debsecan --suite bookworm --only-fixed --format packages | sort -u
Enter fullscreen mode Exit fullscreen mode

Then inspect one package at a time when needed:

apt-cache policy package-name
apt changelog package-name
Enter fullscreen mode Exit fullscreen mode

If you do want a compact review command, this is reasonable:

mapfile -t pkgs < <(debsecan --suite bookworm --only-fixed --format packages | sort -u)
printf '%s\n' "${pkgs[@]}"
Enter fullscreen mode Exit fullscreen mode

That prints a unique package list first, without immediately installing anything.

After review, you can update normally:

sudo apt upgrade
Enter fullscreen mode Exit fullscreen mode

Or upgrade selected packages if you have a staged maintenance process.

Understand one important caveat before you panic

debsecan tracks vulnerabilities mostly at the source package level, while tools like dpkg show binary package names.

That means some binary packages can be flagged because they are built from a vulnerable source package, even if that specific binary package is not where the vulnerable code lives. The man page explicitly calls this out.

So treat debsecan as a strong triage signal, not as a substitute for reading package details.

Check for obsolete packages too

If the suite is set correctly, debsecan can also identify obsolete packages, meaning packages removed from the archive.

That matters because obsolete packages can keep risk around even when the rest of the system is being updated.

Start with:

debsecan --suite bookworm --format detail
Enter fullscreen mode Exit fullscreen mode

If you see obsolete-package warnings, investigate reverse dependencies before removing anything.

Useful helpers:

apt-cache rdepends package-name
apt show package-name
Enter fullscreen mode Exit fullscreen mode

Use a whitelist carefully, not lazily

debsecan supports a whitelist so you can suppress known noise.

For example, to whitelist one CVE entirely:

debsecan --add-whitelist CVE-2005-4601
Enter fullscreen mode Exit fullscreen mode

To whitelist a CVE for one package only:

debsecan --add-whitelist CVE-2005-4601 imagemagick
Enter fullscreen mode Exit fullscreen mode

Show current whitelist entries:

debsecan --show-whitelist
Enter fullscreen mode Exit fullscreen mode

Remove an entry:

debsecan --remove-whitelist CVE-2005-4601 imagemagick
Enter fullscreen mode Exit fullscreen mode

My advice: whitelist only when you have a documented reason, such as:

  • the package is installed but not in active use
  • the vulnerable code path is not present in your deployment
  • you have a compensating control and a planned review date

A whitelist should reduce noise, not hide unfinished work.

Add a daily check

debsecan ships with debsecan-create-cron, which creates a cron entry for periodic reporting.

sudo debsecan-create-cron
Enter fullscreen mode Exit fullscreen mode

According to the man page, the generated cron job runs hourly, but debsecan itself limits real processing to once per day and randomizes the minute to reduce peak server load.

If you prefer a manual report command first, use:

debsecan \
  --suite bookworm \
  --format report \
  --update-history
Enter fullscreen mode Exit fullscreen mode

That is a good way to validate behavior before wiring it into your preferred alerting path.

A small shell wrapper I’d actually keep on a server

This gives you a quick daily summary of fixable exposure:

cat <<'EOF' > debsecan-review
#!/usr/bin/env bash
set -euo pipefail

suite="${1:-$(. /etc/os-release && printf '%s' "$VERSION_CODENAME")}"

echo "== debsecan summary for suite: ${suite} =="
debsecan --suite "$suite" --only-fixed --format summary

echo
echo "== unique affected packages with fixes available =="
debsecan --suite "$suite" --only-fixed --format packages | sort -u

echo
echo "== apt upgradable =="
apt list --upgradable 2>/dev/null || true
EOF

sudo install -m 0755 debsecan-review /usr/local/bin/debsecan-review
/usr/local/bin/debsecan-review
Enter fullscreen mode Exit fullscreen mode

Practical workflow I recommend

If you want the short version, this is the loop:

  1. Install debsecan
  2. Run debsecan --suite <codename> --only-fixed
  3. Review affected packages with --format packages, apt list --upgradable, and apt-cache policy
  4. Upgrade during your normal maintenance process
  5. Use a whitelist sparingly
  6. Add a daily report path

That is simple, auditable, and much better than guessing based on generic CVE headlines.

References

If you already patch regularly but still lack a clean way to answer "which installed packages are exposed right now?", debsecan is one of the simplest tools you can add to a Debian box.

Top comments (0)