Debian GNU/Linux · Packages & updates

Leave no security update pending

When it fails: Security updates are available but not installed. Packages with published security fixes are still installed in their vulnerable version.

CB-DEB-PKG-008mediumactiveautomatedprofile core

As released in v0.1.0 beta · pre-release. Current state.

Description

apt-get -s dist-upgrade simulates an upgrade from the local package lists and shows, for each package, the version and origin of the update. Updates coming from the Debian security suite fix vulnerabilities. The result is only as fresh as the package lists, refreshed by apt-get update or apt-daily.timer.

The check fails on pending security updates and on package lists older than {{ max_lists_age }} days, since stale lists hide pending updates. Other pending updates (point release, backports) are only listed in the evidence. The check does not run apt-get update: refresh the lists first for an up-to-date answer.

Rationale

An available security update means the vulnerability is public and a fix exists, which is when exploitation is most likely. Checking for pending security updates catches systems where automatic updates are disabled, broken, or blocked by a held package or a dependency change.

Impact

None for the check, which changes nothing. Installing updates restarts the services concerned.

Parameters

ParameterCoreServerServer hardenedDesktopDesktop hardenedBounds
max_lists_ageinteger, days. Maximum age of the newest package list before the check fails.777771 to 90

The value used is your override (tailoring file), else the profile's, else the one of the profile it extends, else the default. Bounds limit what an override may set.

Audit

  1. Run apt-get update.
  2. Run apt-get -s dist-upgrade | grep '^Inst' | grep -i security. It must print nothing.

Automated: every check must pass. Scanners report each check by its id.

pending

Updates pending in the local package lists, and the age of these lists.

script: |
  s=$(LC_ALL=C apt-get -s -o Debug::NoLocking=1 dist-upgrade 2>/dev/null) || { echo "apt-get simulation failed"; exit 3; }
  all=$(printf '%s\n' "$s" | grep -c '^Inst ')
  sec=$(printf '%s\n' "$s" | grep '^Inst ' | grep -E '\(.*(Debian-Security|-security)' | awk '{ print $2 }')
  nsec=$(printf '%s' "$sec" | grep -c .)
  newest=$(find /var/lib/apt/lists -maxdepth 1 -name '*Release' -printf '%T@\n' 2>/dev/null | sort -n | tail -1)
  age=999
  [ -n "$newest" ] && age=$(( ($(date +%s) - ${newest%.*}) / 86400 ))
  echo "$all pending, $nsec security ($(printf '%s' "$sec" | head -20 | tr '\n' ' ')), lists $age days old"
  [ "$nsec" -eq 0 ] && [ "$age" -le "$CB_MAX_LISTS_AGE" ]

Remediation

Run apt-get update then apt-get dist-upgrade (or unattended-upgrade for security updates only), during a maintenance window if services must not restart. Reboot when the kernel, libc or systemd were updated (/run/reboot-required exists). If a package is held (apt-mark showhold), find out why before releasing it.

References

Mappings

FrameworkIDRelationNote
ANSSI-BP-028 - Recommandations de configuration d'un système GNU/Linux2.0R61partialR61 asks for a regular update process; this control checks its result for security updates.
NIST SP 800-53 Rev. 55.1.1SI-2related

How this control relates to the other framework's: equivalent, stricter, looser, partial or related.

Threats mitigated

People and lifecycle

Authors
Verified2026-10-18 by Sn0wAlice on 12, Proxmox VM, Debian 12 genericcloud image, kernel 6.1.0-54-cloud-amd64. Passes on up-to-date VM; fails after downgrading libexpat1 below its security version and with lists older than max_lists_age; passes again after upgrade.
Verified2026-10-18 by Sn0wAlice on 13, Proxmox VM, Debian 13 genericcloud image, kernel 6.12.113+deb13-cloud-amd64. Passes on up-to-date VM; fails after downgrading libexpat1 below its security version and with lists older than max_lists_age; passes again after upgrade.
Introduced inv0.1.0
Created, updated2026-10-18, 2026-10-18
Translationsfr