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

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

What debsecan is good at

Install debsecan

Always use the correct suite codename

First pass: show vulnerabilities affecting installed packages

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

Review package results before upgrading everything blindly

Understand one important caveat before you panic

Check for obsolete packages too

Use a whitelist carefully, not lazily

Add a daily check

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

Practical workflow I recommend

References 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. debsecan is useful when you want to: 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. 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. Examples in this article use bookworm. Replace that with your actual codename. 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: If you want only vulnerability IDs: If you want just package names: That last format becomes handy when you want to review impacted packages at the package level before changing anything. This is where debsecan becomes operationally useful. If you want the package list only: 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: And then, for a specific package: That combination is a good reality check: 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. Then inspect one package at a time when needed: If you do want a compact review command, this is reasonable: That prints a unique package list first, without immediately installing anything. After review, you can update normally: Or upgrade selected packages if you have a staged maintenance process. 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. 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. If you see obsolete-package warnings, investigate reverse dependencies before removing anything. debsecan supports a whitelist so you can suppress known noise. For example, to whitelist one CVE entirely: To whitelist a CVE for one package only: Show current whitelist entries: My advice: whitelist only when you have a documented reason, such as: A whitelist should reduce noise, not hide unfinished work. debsecan ships with debsecan-create-cron, which creates a cron entry for periodic reporting. 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: That is a good way to validate behavior before wiring it into your preferred alerting path. This gives you a quick daily summary of fixable exposure: If you want the short version, this is the loop: That is simple, auditable, and much better than guessing based on generic CVE headlines. 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. Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Command

Copy

$ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install debsecan -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install debsecan -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install debsecan debsecan --help debsecan --help debsecan --help . /etc/os-release echo "$VERSION_CODENAME" . /etc/os-release echo "$VERSION_CODENAME" . /etc/os-release echo "$VERSION_CODENAME" debsecan --suite bookworm debsecan --suite bookworm debsecan --suite bookworm debsecan --suite bookworm --format detail debsecan --suite bookworm --format detail debsecan --suite bookworm --format detail debsecan --suite bookworm --format bugs debsecan --suite bookworm --format bugs debsecan --suite bookworm --format bugs debsecan --suite bookworm --format packages debsecan --suite bookworm --format packages debsecan --suite bookworm --format packages debsecan --suite bookworm --only-fixed debsecan --suite bookworm --only-fixed debsecan --suite bookworm --only-fixed debsecan --suite bookworm --only-fixed --format packages debsecan --suite bookworm --only-fixed --format packages debsecan --suite bookworm --only-fixed --format packages -weight: 500;">apt list --upgradable -weight: 500;">apt list --upgradable -weight: 500;">apt list --upgradable -weight: 500;">apt-cache policy openssl -weight: 500;">apt-cache policy openssl -weight: 500;">apt-cache policy openssl debsecan --suite bookworm --only-fixed --format packages | sort -u debsecan --suite bookworm --only-fixed --format packages | sort -u debsecan --suite bookworm --only-fixed --format packages | sort -u -weight: 500;">apt-cache policy package-name -weight: 500;">apt changelog package-name -weight: 500;">apt-cache policy package-name -weight: 500;">apt changelog package-name -weight: 500;">apt-cache policy package-name -weight: 500;">apt changelog package-name mapfile -t pkgs < <(debsecan --suite bookworm --only-fixed --format packages | sort -u) printf '%s\n' "${pkgs[@]}" mapfile -t pkgs < <(debsecan --suite bookworm --only-fixed --format packages | sort -u) printf '%s\n' "${pkgs[@]}" mapfile -t pkgs < <(debsecan --suite bookworm --only-fixed --format packages | sort -u) printf '%s\n' "${pkgs[@]}" -weight: 600;">sudo -weight: 500;">apt -weight: 500;">upgrade -weight: 600;">sudo -weight: 500;">apt -weight: 500;">upgrade -weight: 600;">sudo -weight: 500;">apt -weight: 500;">upgrade debsecan --suite bookworm --format detail debsecan --suite bookworm --format detail debsecan --suite bookworm --format detail -weight: 500;">apt-cache rdepends package-name -weight: 500;">apt show package-name -weight: 500;">apt-cache rdepends package-name -weight: 500;">apt show package-name -weight: 500;">apt-cache rdepends package-name -weight: 500;">apt show package-name debsecan --add-whitelist CVE-2005-4601 debsecan --add-whitelist CVE-2005-4601 debsecan --add-whitelist CVE-2005-4601 debsecan --add-whitelist CVE-2005-4601 imagemagick debsecan --add-whitelist CVE-2005-4601 imagemagick debsecan --add-whitelist CVE-2005-4601 imagemagick debsecan --show-whitelist debsecan --show-whitelist debsecan --show-whitelist debsecan ---weight: 500;">remove-whitelist CVE-2005-4601 imagemagick debsecan ---weight: 500;">remove-whitelist CVE-2005-4601 imagemagick debsecan ---weight: 500;">remove-whitelist CVE-2005-4601 imagemagick -weight: 600;">sudo debsecan-create-cron -weight: 600;">sudo debsecan-create-cron -weight: 600;">sudo debsecan-create-cron debsecan \ --suite bookworm \ --format report \ ---weight: 500;">update-history debsecan \ --suite bookworm \ --format report \ ---weight: 500;">update-history debsecan \ --suite bookworm \ --format report \ ---weight: 500;">update-history 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 "== -weight: 500;">apt upgradable ==" -weight: 500;">apt list --upgradable 2>/dev/null || true EOF -weight: 600;">sudo -weight: 500;">install -m 0755 debsecan-review /usr/local/bin/debsecan-review /usr/local/bin/debsecan-review 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 "== -weight: 500;">apt upgradable ==" -weight: 500;">apt list --upgradable 2>/dev/null || true EOF -weight: 600;">sudo -weight: 500;">install -m 0755 debsecan-review /usr/local/bin/debsecan-review /usr/local/bin/debsecan-review 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 "== -weight: 500;">apt upgradable ==" -weight: 500;">apt list --upgradable 2>/dev/null || true EOF -weight: 600;">sudo -weight: 500;">install -m 0755 debsecan-review /usr/local/bin/debsecan-review /usr/local/bin/debsecan-review - 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 - debsecan tells you which installed packages are affected - --only-fixed narrows to issues with known fixes available - -weight: 500;">apt list --upgradable shows what APT currently wants to -weight: 500;">upgrade - -weight: 500;">apt-cache policy helps you inspect candidate versions and repository origin - 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 - Install debsecan - Run debsecan --suite <codename> --only-fixed - Review affected packages with --format packages, -weight: 500;">apt list --upgradable, and -weight: 500;">apt-cache policy - Upgrade during your normal maintenance process - Use a whitelist sparingly - Add a daily report path - Debian debsecan man page: https://manpages.debian.org/bookworm/debsecan/debsecan.1.en.html - Debian debsecan-create-cron man page: https://manpages.debian.org/bookworm/debsecan/debsecan-create-cron.8.en.html - Debian Securing Manual, Security Tracker section: https://www.debian.org/doc/manuals/securing-debian-manual/ch07s03.en.html - Debian Security Tracker: https://security-tracker.debian.org/ - Debian Security Team tracker overview: https://security-team.debian.org/security_tracker.html