Skip to main content

On This Page

Automating Linux Vulnerability Scanning with Python and dpkg

3 min read
Share

These articles are AI-generated summaries. Please check the original sources for full details.

Matching live CVEs to your actual apt packages in ~800 lines of Python

Developer Aiden Bolin engineered a CVE matcher to solve the signal-to-noise problem in modern security monitoring. The system processes over 41,000 NVD records to generate specific, one-liner remediation commands for Linux environments.

Why This Matters

In the technical reality of systems administration, most security advisories are irrelevant to a specific environment, but the manual cost of verification is prohibitive. While ideal models suggest using complex relational databases for vulnerability management, Bolin demonstrates that for fleets under 10,000 servers, using JSONL with atomic renames avoids the ‘premature SQL tax’ while maintaining high performance and simplified backups.

Key Insights

  • The NVD currently indexes over 41,000 CVEs, necessitating automated filtering to identify actionable security threats in 2026.
  • Reliable version comparison is achieved by wrapping ‘dpkg —compare-versions’ to determine if an installed package version is strictly less than the security-fixed version.
  • Remediation is not always a package bump; kernel-level vulnerabilities like CVE-2026-31431 require specific modprobe blacklisting rather than standard apt upgrades.
  • Ubuntu Pro and ESM channels introduce complexity where the ‘fixed’ version is only available through a paid token, requiring the matcher to emit specialized remediation playbooks.
  • A resilient feed architecture uses nine distributed pollers (e.g., stackpatch-usn-poller.py) to aggregate data from Ubuntu, Debian, Alpine, and OSV.dev every 30-60 minutes.

Working Examples

Core logic for intersecting advisory fixed versions with server package inventory using dpkg.

import subprocess
from pathlib import Path

def is_affected(installed: str, fixed: str) -> bool:
    """Wrap dpkg --compare-versions. Returns True if installed < fixed."""
    rc = subprocess.run(
        ["dpkg", "--compare-versions", installed, "lt", fixed],
        check=False,
    ).returncode
    return rc == 0

def match_advisory(advisory: dict, inventory: dict[str, str], codename: str):
    fixes = advisory.get("releases", {}).get(codename, {}).get("binaries", {})
    for pkg, fixed_version in fixes.items():
        installed = inventory.get(pkg)
        if installed and is_affected(installed, fixed_version):
            yield {
                "advisory": advisory["id"],
                "cves": advisory["cves"],
                "package": pkg,
                "installed": installed,
                "fixed": fixed_version,
                "remediation": f"sudo apt update && sudo apt install --only-upgrade {pkg}={fixed_version}",
            }

Practical Applications

  • Use case: A production VPS environment uses the matcher to identify unpatched OpenSSH vulnerabilities and automatically generates a ‘sudo apt install —only-upgrade’ command. Pitfall: Matching on source package names instead of binary package names, which causes the system to miss vulnerabilities in specific binaries like libssl3.
  • Use case: Enterprise fleet management where the system detects pinned repositories via apt-pinning. Pitfall: Attempting to force an upgrade when a pin conflict exists, which is mitigated by flagging a ‘remediation_blocked’ state instead of executing the command.
  • Use case: Kernel security management where the matcher identifies that an upstream fix is unavailable in the current distribution. Pitfall: Relying on generic apt upgrades for kernel modules, which fails to mitigate local-priv-esc vulnerabilities that require a modprobe blacklist.

References:

Continue reading

Next article

Thinking Machines Lab Unveils Interaction Models: Native Multimodal Architecture for Real-Time AI

Related Content