Ubuntu · Packages & updates

Install security updates automatically

When it fails: Security updates are not installed automatically. Fixes wait for a human to apply them, often for weeks, while the vulnerabilities they close are public.

CB-UBU-PKG-007mediumactiveautomatedautomated fixprofile core

Description

unattended-upgrades installs available updates without human action. Two systemd timers drive it: apt-daily.timer refreshes the package lists and apt-daily-upgrade.timer installs the updates, when APT::Periodic::Update-Package-Lists and APT::Periodic::Unattended-Upgrade are not 0. Which updates are installed is set by Unattended-Upgrade::Allowed-Origins (or Origins-Pattern); Ubuntu's default allows the <codename>-security pocket and the ESM security pockets (<codename>-infra-security, <codename>-apps-security), which are used once the system is attached to Ubuntu Pro.

Installed and enabled by default on every Ubuntu release, server, desktop and cloud images (/etc/apt/apt.conf.d/20auto-upgrades with both options set to 1). The control fails when someone disabled it. Snaps are not updated by unattended-upgrades: see CB-UBU-PKG-012.

Rationale

Most compromises exploit vulnerabilities for which a fix already exists. Installing security fixes daily and automatically closes that window without depending on a manual process. Ubuntu security updates are minimal backported fixes, designed to be installed without review.

Impact

Services are restarted by their package when updated, which can cause a short interruption. The system is not rebooted (Unattended-Upgrade::Automatic-Reboot is false by default), so kernel and libc fixes still need a planned reboot. Organisations that deploy updates with a central patch management tool can exclude this control in their tailoring file and document it.

Setting

Location/etc/apt/apt.conf.d/20auto-upgrades, /etc/apt/apt.conf.d/50unattended-upgrades
DefaultEnabled, security and ESM pockets allowed
Recommendedunattended-upgrades installed, both APT::Periodic options set to 1, security origin allowed, timers enabled

Audit

  1. dpkg -s unattended-upgrades shows Status: install ok installed.
  2. apt-config dump APT::Periodic shows Update-Package-Lists and Unattended-Upgrade set to 1 (or another non-zero value).
  3. apt-config dump Unattended-Upgrade::Allowed-Origins Unattended-Upgrade::Origins-Pattern contains ${distro_id}:${distro_codename}-security or another -security origin.
  4. systemctl is-enabled apt-daily.timer apt-daily-upgrade.timer prints enabled twice.
  5. unattended-upgrade --dry-run --debug lists the security origin among the allowed ones.

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

package

unattended-upgrades package.

name: unattended-upgrades
state: installed

periodic

APT::Periodic options, as merged by apt-config.

script: |
  eval "$(apt-config shell L APT::Periodic::Update-Package-Lists U APT::Periodic::Unattended-Upgrade)" || exit 3
  echo "Update-Package-Lists=${L:-unset} Unattended-Upgrade=${U:-unset}"
  case ${L:-0}:${U:-0} in 0:* | *:0 | false:* | *:false | no:* | *:no) exit 1 ;; esac

origins

Origins allowed to unattended-upgrades.

script: |
  o=$(apt-config dump Unattended-Upgrade::Origins-Pattern Unattended-Upgrade::Allowed-Origins 2>/dev/null | grep -E '::(Origins-Pattern|Allowed-Origins):: ')
  printf '%s\n' "$o" | grep -Ei -- '-security' || { echo "no security origin allowed"; exit 1; }

lists-timer

Timer that refreshes the package lists.

unit: apt-daily.timer
state: enabled

upgrade-timer

Timer that installs the updates.

unit: apt-daily-upgrade.timer
state: enabled

Remediation

  1. apt-get install unattended-upgrades.
  2. Write /etc/apt/apt.conf.d/20auto-upgrades with APT::Periodic::Update-Package-Lists "1"; and APT::Periodic::Unattended-Upgrade "1"; (this is what dpkg-reconfigure -plow unattended-upgrades does), and remove any setting to 0 in a file read later (apt-config dump APT::Periodic shows the result). The automated fix comments such settings out.
  3. If Unattended-Upgrade::Allowed-Origins was customised, add back "${distro_id}:${distro_codename}-security"; (and the ESM origins "${distro_id}ESMApps:${distro_codename}-apps-security"; and "${distro_id}ESM:${distro_codename}-infra-security";) in /etc/apt/apt.conf.d/50unattended-upgrades.
  4. systemctl enable --now apt-daily.timer apt-daily-upgrade.timer.
Restartnone
Disruptionlow

Rollback

Set both APT::Periodic options to 0 in /etc/apt/apt.conf.d/20auto-upgrades, or purge unattended-upgrades.

package

Generated from check package: the engine writes the fix for every output, it sets the expected value and the check runs again after.

periodic

f=/etc/apt/apt.conf.d/20auto-upgrades
cb_backup "$f"
printf '%s\n' 'APT::Periodic::Update-Package-Lists "1";' 'APT::Periodic::Unattended-Upgrade "1";' >"$f"
# Any other file setting either option to 0 can override 20auto-upgrades: comment it out.
r='^[^#/]*APT::Periodic::(Update-Package-Lists|Unattended-Upgrade)[[:space:]]+"?(0|false|no|off)"?'
for g in /etc/apt/apt.conf.d/* /etc/apt/apt.conf; do
  [ -f "$g" ] && [ "$g" != "$f" ] && grep -Eqi "$r" "$g" || continue
  cb_backup "$g"
  sed -E -i "s@($r.*)@// disabled by CB-UBU-PKG-007: \1@I" "$g"
done

lists-timer

Generated from check lists-timer: the engine writes the fix for every output, it sets the expected value and the check runs again after.

upgrade-timer

Generated from check upgrade-timer: the engine writes the fix for every output, it sets the expected value and the check runs again after.

Handwritten code reads parameters from CB_<NAME> environment variables. Each release turns these fixes into remediate.sh and an Ansible role per profile: dry run by default, a fix runs only when its check fails.

References

Mappings

FrameworkIDRelationNote
ANSSI-BP-028 - Recommandations de configuration d'un système GNU/Linux2.0R61partialR61 asks for a regular and reactive security update process; this control automates the Ubuntu part of it.
NIST SP 800-53 Rev. 55.1.1SI-2(5)equivalent

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

Threats mitigated

People and lifecycle

Authors
Verified2026-10-19 by Sn0wAlice on 20.04, Proxmox VM, Ubuntu 20.04 cloud image, kernel 5.4.0-216-generic. Passes on stock (security and ESM origins allowed); Unattended-Upgrade 0 in a later file and disabled upgrade timer detected; fix rewrites 20auto-upgrades, comments the overriding line and enables the timer.
Verified2026-10-19 by Sn0wAlice on 22.04, Proxmox VM, Ubuntu 22.04 cloud image, kernel 5.15.0-198-generic. Passes on stock (security and ESM origins allowed); Unattended-Upgrade 0 in a later file and disabled upgrade timer detected; fix rewrites 20auto-upgrades, comments the overriding line and enables the timer.
Verified2026-10-19 by Sn0wAlice on 24.04, Proxmox VM, Ubuntu 24.04 cloud image, kernel 6.8.0-147-generic. Passes on stock (security and ESM origins allowed); Unattended-Upgrade 0 in a later file and disabled upgrade timer detected; fix rewrites 20auto-upgrades, comments the overriding line and enables the timer.
Verified2026-10-19 by Sn0wAlice on 26.04, Proxmox VM, Ubuntu 26.04 cloud image, kernel 7.0.0-38-generic. Passes on stock (security and ESM origins allowed); Unattended-Upgrade 0 in a later file and disabled upgrade timer detected; fix rewrites 20auto-upgrades, comments the overriding line and enables the timer.
Introduced inv0.1.0
Created, updated2026-10-19, 2026-10-19
Translationsfr