Debian GNU/Linux · Desktop environment

Require a password at the graphical login, without automatic login or guest session

When it fails: The display manager opens a session without a password. Automatic, timed or guest login gives a working session to anyone who turns on or sits at the machine.

CB-DEB-DESK-006highactiveautomatedautomated fixprofile desktop

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

Description

Display managers can open a session without authentication:

  • GDM: AutomaticLoginEnable and TimedLoginEnable in the [daemon] section of /etc/gdm3/daemon.conf;
  • LightDM: autologin-user, autologin-guest and the guest session (allow-guest, on by default upstream);
  • SDDM: User in the [Autologin] section of its configuration.

This control checks that none of them is enabled and that LightDM explicitly disables the guest session.

GDM has no guest session. LightDM's guest session needs a helper script that Debian does not ship, but the option is still turned off explicitly. The LightDM and SDDM checks read every configuration file in load order and keep the last value; they ignore sections, so a value set for one seat only counts for all. The automated fix covers GDM only; the LightDM and SDDM checks were written from their documentation and not tested in a lab.

Rationale

A session opened without a password gives the account's files, browser sessions, stored credentials and network access to whoever is in front of the screen, or to whoever steals the machine. A guest session gives an unaudited foothold on the system.

Impact

Every user types a password at boot. Kiosks that rely on automatic login must be excluded through tailoring.

Setting

Location/etc/gdm3/daemon.conf, /etc/lightdm/lightdm.conf(.d), /etc/sddm.conf(.d)
DefaultOff, except LightDM allow-guest (true upstream)
RecommendedNo automatic, timed or guest login

Audit

  1. GDM: /etc/gdm3/daemon.conf must not set AutomaticLoginEnable=true or TimedLoginEnable=true in [daemon].
  2. LightDM: the configuration must set allow-guest=false, and must not set autologin-user or autologin-guest=true.
  3. SDDM: no User= value in an [Autologin] section of /etc/sddm.conf, /etc/sddm.conf.d/ or /usr/lib/sddm/sddm.conf.d/.

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

gdm

GDM has no automatic or timed login.

script: |
  [ -f /etc/gdm3/daemon.conf ] || { echo "no /etc/gdm3/daemon.conf"; exit 0; }
  rc=0
  for k in AutomaticLoginEnable TimedLoginEnable; do
    v=$(K=$k awk '/^[ \t]*\[/ { h = $0; gsub(/^[ \t]+|[ \t]+$/, "", h); s = (h == "[daemon]"); next }
      s && $0 ~ "^[ \t]*" ENVIRON["K"] "[ \t]*=" { v = $0; sub(/^[^=]*=[ \t]*/, "", v); sub(/[ \t]+$/, "", v) }
      END { print v }' /etc/gdm3/daemon.conf)
    echo "$k=${v:-unset}"
    case $v in [Tt][Rr][Uu][Ee] | 1) rc=1 ;; esac
  done
  exit "$rc"

lightdm

LightDM has no automatic login and no guest session.

script: |
  files=
  for f in /usr/share/lightdm/lightdm.conf.d/*.conf /etc/xdg/lightdm/lightdm.conf.d/*.conf \
    /etc/lightdm/lightdm.conf.d/*.conf /etc/lightdm/lightdm.conf; do
    [ -f "$f" ] && files="$files $f"
  done
  get() {
    # shellcheck disable=SC2086 # one word per file
    [ -n "$files" ] && K=$1 awk '$0 ~ "^[ \t]*" ENVIRON["K"] "[ \t]*=" { v = $0; sub(/^[^=]*=[ \t]*/, "", v); sub(/[ \t]+$/, "", v) }
      END { print v }' $files
  }
  g=$(get allow-guest) u=$(get autologin-user) a=$(get autologin-guest)
  echo "allow-guest=${g:-unset} autologin-user=${u:-unset} autologin-guest=${a:-unset}"
  case $g in [Ff][Aa][Ll][Ss][Ee] | 0) ;; *) exit 1 ;; esac
  [ -z "$u" ] || exit 1
  case $a in [Tt][Rr][Uu][Ee] | 1) exit 1 ;; esac

sddm

SDDM has no automatic login.

script: |
  files=
  for f in /usr/lib/sddm/sddm.conf.d/*.conf /etc/sddm.conf.d/*.conf /etc/sddm.conf; do
    [ -f "$f" ] && files="$files $f"
  done
  [ -n "$files" ] || { echo "no SDDM configuration file"; exit 0; }
  # shellcheck disable=SC2086 # one word per file
  u=$(awk 'FNR == 1 { s = 0 } /^[ \t]*\[/ { h = $0; gsub(/^[ \t]+|[ \t]+$/, "", h); s = (h == "[Autologin]"); next }
    s && /^[ \t]*User[ \t]*=/ { v = $0; sub(/^[^=]*=[ \t]*/, "", v); sub(/[ \t]+$/, "", v) }
    END { print v }' $files)
  echo "[Autologin] User=${u:-unset}"
  [ -z "$u" ]

Remediation

  • GDM: in /etc/gdm3/daemon.conf, section [daemon], set AutomaticLoginEnable=false and TimedLoginEnable=false (or remove the lines). The change applies when GDM restarts.
  • LightDM: in /etc/lightdm/lightdm.conf, section [Seat:*], set allow-guest=false, greeter-allow-guest=false, and remove autologin-user and autologin-guest.
  • SDDM: remove User= from the [Autologin] section of the SDDM configuration files.
Restartsystem reboot
Disruptionlow

Rollback

Restore /etc/gdm3/daemon.conf from the backup directory.

gdm

# Turn off automatic and timed login in GDM. Only edits /etc/gdm3/daemon.conf when one is on.
f=/etc/gdm3/daemon.conf
[ -f "$f" ] || { echo "$f not found" >&2; exit 1; }

# ini_get SECTION KEY: last value of KEY in [SECTION] of daemon.conf, empty when unset.
ini_get() {
  S="[$1]" K=$2 awk '
    BEGIN { s = ENVIRON["S"]; k = ENVIRON["K"] }
    /^[ \t]*\[/ { h = $0; gsub(/^[ \t]+|[ \t]+$/, "", h); in_s = (h == s); next }
    in_s && /=/ && !/^[ \t]*[#;]/ {
      key = substr($0, 1, index($0, "=") - 1); gsub(/^[ \t]+|[ \t]+$/, "", key)
      if (key == k) { v = substr($0, index($0, "=") + 1); gsub(/^[ \t]+|[ \t]+$/, "", v) }
    }
    END { print v }
  ' "$f"
}

# ini_set SECTION KEY VALUE: set KEY=VALUE right after the [SECTION] header, adding the section if missing.
ini_set() {
  S="[$1]" K=$2 V=$3 awk '
    BEGIN { s = ENVIRON["S"]; k = ENVIRON["K"]; v = ENVIRON["V"] }
    function out() { if (!done) { print k "=" v; done = 1 } }
    /^[ \t]*\[/ { print; h = $0; gsub(/^[ \t]+|[ \t]+$/, "", h); in_s = (h == s); if (in_s) out(); next }
    in_s && $0 ~ "^[ \t]*" k "[ \t]*=" { next }
    { print }
    END { if (!done) { print s; out() } }
  ' "$f" >"$f.cirsec-tmp" && cat "$f.cirsec-tmp" >"$f"
  rc=$?
  rm -f "$f.cirsec-tmp"
  return "$rc"
}

is_true() { case $1 in [Tt][Rr][Uu][Ee] | 1) return 0 ;; esac; return 1; }

for k in AutomaticLoginEnable TimedLoginEnable; do
  is_true "$(ini_get daemon "$k")" || continue
  cb_backup "$f"
  ini_set daemon "$k" false || exit 1
done

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

FrameworkIDRelation
NIST SP 800-53 Rev. 55.1.1IA-2related
NIST SP 800-53 Rev. 55.1.1AC-14related

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 with minimal GNOME (gdm3, gnome-shell), Debian 12 genericcloud image, kernel 6.1.0-54-cloud-amd64. GDM check and fix tested (desktop-hardened), including AutomaticLoginEnable=True and TimedLoginEnable=1 turned off; the LightDM and SDDM checks were not tested (no such machine), only reported not applicable.
Verified2026-10-18 by Sn0wAlice on 13, Proxmox VM with minimal GNOME (gdm3, gnome-shell), Debian 13 genericcloud image, kernel 6.12.113+deb13-cloud-amd64. GDM check and fix tested (desktop-hardened), including AutomaticLoginEnable=True and TimedLoginEnable=1 turned off; the LightDM and SDDM checks were not tested (no such machine), only reported not applicable.
Introduced inv0.1.0
Created, updated2026-10-18, 2026-10-18
Translationsfr