Description
Display managers authenticate users through PAM services in /etc/pam.d/. A line
auth required pam_succeed_if.so user != root quiet_success at the top of the auth stack
refuses root before the password is checked. Debian's GDM and SDDM packages ship that line;
LightDM's lightdm service does not. The control checks the password, fingerprint and smart
card services of GDM, and the login services of LightDM and SDDM, that are present.
Automatic login services (gdm-autologin, lightdm-autologin, sddm-autologin) are not
checked: CB-DEB-DESK-006 forbids automatic login. The fix only adds the line to services
that lack it and was tested by removing the line from gdm-password; it was not tested with
LightDM or SDDM. It changes PAM, so it is disabled by default.
Rationale
A graphical session runs hundreds of processes and parses untrusted content (web pages, mail, documents). Running all of it as root turns any bug into a full compromise. Administrators should log in with their own account and elevate with sudo, which keeps their actions attributable.
Impact
root cannot log in graphically. Administrators use their own account and sudo.
Setting
| Location | /etc/pam.d/gdm-password, gdm-fingerprint, gdm-smartcard, lightdm, sddm |
| Default | Present for GDM and SDDM, missing for LightDM |
| Recommended | auth required pam_succeed_if.so user != root quiet_success |
Audit
For each of /etc/pam.d/gdm-password, gdm-fingerprint, gdm-smartcard, lightdm and
sddm that exists, check that the auth stack contains a pam_succeed_if.so line with
user != root and a required or requisite control (or default=bad).
Automated: every check must pass. Scanners report each check by its id.
pam-root
Display manager PAM services refuse root.
script: |
re='^[[:space:]]*auth[[:space:]]+(required|requisite|\[[^]]*default=(bad|die)[^]]*\])[[:space:]]+pam_succeed_if\.so[[:space:]].*user[[:space:]]*!=[[:space:]]*root'
found=0 rc=0
for f in /etc/pam.d/gdm-password /etc/pam.d/gdm-fingerprint /etc/pam.d/gdm-smartcard \
/etc/pam.d/lightdm /etc/pam.d/sddm; do
[ -f "$f" ] || continue
found=1
if grep -Eq "$re" "$f"; then echo "$f refuses root"; else echo "$f allows root"; rc=1; fi
done
[ "$found" = 1 ] || { echo "no display manager PAM service"; exit 2; }
exit "$rc"
Remediation
In each display manager PAM service listed by the audit that lacks it, add before the first
auth line:
auth required pam_succeed_if.so user != root quiet_success
| Restart | none |
| Disruption | low |
| Lockout risk | yes: can cut off administrative access. Off by default in generated scripts and playbooks, opt in through a tailoring file. |
Rollback
Restore the changed files of /etc/pam.d/ from the backup directory.
pam-root
# Add "auth required pam_succeed_if.so user != root quiet_success" before the first auth line of
# each display manager PAM service that lacks a root refusal.
re='^[[:space:]]*auth[[:space:]]+(required|requisite|\[[^]]*default=(bad|die)[^]]*\])[[:space:]]+pam_succeed_if\.so[[:space:]].*user[[:space:]]*!=[[:space:]]*root'
line='auth required pam_succeed_if.so user != root quiet_success'
for f in /etc/pam.d/gdm-password /etc/pam.d/gdm-fingerprint /etc/pam.d/gdm-smartcard \
/etc/pam.d/lightdm /etc/pam.d/sddm; do
[ -f "$f" ] || continue
grep -Eq "$re" "$f" && continue
grep -Eq '^[[:space:]]*(auth[[:space:]]|@include[[:space:]]+common-auth)' "$f" || {
echo "$f has no auth line, left unchanged" >&2
continue
}
cb_backup "$f"
L=$line awk '!done && /^[ \t]*(auth[ \t]|@include[ \t]+common-auth)/ { print ENVIRON["L"]; done = 1 } { print }' \
"$f" >"$f.cirsec-tmp" && cat "$f.cirsec-tmp" >"$f"
rc=$?
rm -f "$f.cirsec-tmp"
[ "$rc" -eq 0 ] || exit 1
echo "added root refusal to $f"
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
- pam_succeed_if(8), Debian manual pages Debian, vendor-doc, accessed 2026-10-18
- ANSSI-BP-028 v2.0 - Recommandations de configuration d'un système GNU/Linux (R33) ANSSI, guide, accessed 2026-10-18
Mappings
| Framework | ID | Relation | Note |
|---|---|---|---|
| ANSSI-BP-028 - Recommandations de configuration d'un système GNU/Linux2.0 | R33 | related | R33 asks for attributable administration; refusing graphical root sessions is one part of it. |
| NIST SP 800-53 Rev. 55.1.1 | AC-6(2) | related |
How this control relates to the other framework's: equivalent, stricter, looser, partial or related.
Threats mitigated
| Taxonomy | ID |
|---|---|
| MITRE ATT&CK | T1078.003 |
Related controls
- related
CB-DEB-DESK-006Require a password at the graphical login, without automatic login or guest session
People and lifecycle
| Authors |
|
| Verified | 2026-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. Check and fix tested on GDM after removing the root line from gdm-password; pamtester confirmed root refused and a normal account still authenticated after the fix. LightDM and SDDM services not tested. |
| Verified | 2026-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. Check and fix tested on GDM after removing the root line from gdm-password; pamtester confirmed root refused and a normal account still authenticated after the fix. LightDM and SDDM services not tested. |
| Introduced in | v0.1.0 |
| Created, updated | 2026-10-18, 2026-10-18 |
| Translations | fr |