Debian GNU/Linux · Logging & auditing

Keep audit logs instead of rotating them away

When it fails: Old audit logs are deleted automatically. auditd rotates its logs and deletes the oldest one, so a busy system or a deliberate flood erases the audit history.

CB-DEB-AUDIT-013mediumactiveautomatedautomated fixprofile server-hardenedprofile desktop-hardened

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

Description

/etc/audit/auditd.conf decides what auditd does when its log reaches max_log_file megabytes. Debian ships max_log_file_action = ROTATE with num_logs = 5: the oldest file is deleted at each rotation. This control requires:

  • max_log_file of at least {{ max_log_file }} MB;
  • max_log_file_action = keep_logs: auditd rotates the file but never deletes old ones.

Archiving or removing old audit logs then becomes a deliberate task of the administrator, and running out of space is handled by CB-DEB-AUDIT-014.

Rationale

The audit log is evidence. Automatic deletion lets an attacker push the records of their actions out of the history by generating noise.

Impact

Audit logs accumulate in /var/log/audit/ until they are archived. Plan the space, ideally a dedicated partition (CB-DEB-AUDIT-014 reacts when it runs low).

Setting

Location/etc/audit/auditd.conf
Defaultmax_log_file = 8, max_log_file_action = ROTATE
Recommendedmax_log_file >= {{ max_log_file }}, max_log_file_action = keep_logs

Parameters

ParameterCoreServerServer hardenedDesktopDesktop hardenedBounds
max_log_fileinteger, MB. Minimum size of one audit log file before rotation.888881 to 4096

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

Run grep -Ei '^\s*max_log_file(_action)?\s*=' /etc/audit/auditd.conf. max_log_file must be at least {{ max_log_file }} and max_log_file_action must be keep_logs.

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

retention

max_log_file and max_log_file_action in auditd.conf.

script: |
  f=/etc/audit/auditd.conf
  [ -r "$f" ] || { echo "$f not found: auditd is not installed"; exit 1; }
  get() { sed -n "s/^[[:space:]]*$1[[:space:]]*=[[:space:]]*\([^[:space:]]*\).*/\1/p" "$f" | tail -n 1; }
  s=$(get max_log_file) a=$(get max_log_file_action | tr 'A-Z' 'a-z')
  echo "max_log_file=${s:-unset} max_log_file_action=${a:-unset}"
  case $s in '' | *[!0-9]*) exit 1 ;; esac
  [ "$s" -ge "$CB_MAX_LOG_FILE" ] && [ "$a" = keep_logs ]

Remediation

In /etc/audit/auditd.conf, set max_log_file = {{ max_log_file }} (or more) and max_log_file_action = keep_logs, then run systemctl restart auditd.

Restartservice: auditd
Disruptionnone

Rollback

Set max_log_file_action = ROTATE back in /etc/audit/auditd.conf and restart auditd.

auditd-conf

f=/etc/audit/auditd.conf
[ -f "$f" ] || { echo "$f not found: auditd is not installed" >&2; exit 1; }
cb_backup "$f"
set_kv() {
  sed -i "/^[[:space:]]*$1[[:space:]]*=/d" "$f"
  printf '%s = %s\n' "$1" "$2" >>"$f"
}
s=$(sed -n 's/^[[:space:]]*max_log_file[[:space:]]*=[[:space:]]*\([0-9]*\).*/\1/p' "$f" | tail -n 1)
if [ -z "$s" ] || [ "$s" -lt "$CB_MAX_LOG_FILE" ]; then set_kv max_log_file "$CB_MAX_LOG_FILE"; fi
set_kv max_log_file_action keep_logs

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

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, BIOS boot. Fails on fresh install (ROTATE); fix sets keep_logs, auditd restarted; second run idempotent; kept after reboot.
Verified2026-10-18 by Sn0wAlice on 13, Proxmox VM, Debian 13 genericcloud image, kernel 6.12.113+deb13-cloud-amd64, BIOS boot. Fails on fresh install (ROTATE); fix sets keep_logs, auditd restarted; second run idempotent; kept after reboot.
Introduced inv0.1.0
Created, updated2026-10-18, 2026-10-18
Translationsfr