← All rules
SOCLE-CLD-IAM-042// Passwords (pwquality)mediumpersistent config

Ensure PAM Enforces Password Requirements - Enforce for root User

Set enforce_for_root in the pwquality configuration so the password policy (length, character classes, dictionary checks) is enforced for root too. Without it, pam_pwquality only prints a warning when root sets a weak password, then accepts it.

Checked against the content of a persistent configuration file, the source of truth that survives reboots.

A pass proves? running now✓ on disk✓ survives rebootthe qualified verdict →
Debian 12CIS 1.1.0Debian 13CIS 1.0.0FedoraRHEL 10 / Rocky 10 / AlmaLinux 10RHEL 8 / Rocky 8 / AlmaLinux 8CIS 4.0.0RHEL 9 / Rocky 9 / AlmaLinux 9CIS 2.0.0Ubuntu 24.04CIS 1.0.0Ubuntu 26.04
One check, maps to 2 standards

A mapping is a cross-reference to where each standard places this requirement, anchored and cross-validated, not a claim of equivalence. A passing check is evidence toward these references, how to read it.

Why this rule matters

Use of a complex password helps to increase the time and resources required to compromise the password. Password complexity, or strength, is a measure of the effectiveness of a password in resisting attempts at guessing and brute-force attacks. Password complexity is one factor of several that determines how long it takes to crack a password. The more complex the password, the greater the number of possible combinations that need to be tested before the password is compromised.

What Pavois checks

Pavois greps for a non-commented enforce_for_root directive across /etc/security/pwquality.conf and the /etc/security/pwquality.conf.d/ drop-in directory, which together are the full set of files libpwquality actually reads. Checking only the main file would miss the directive when it is delivered by a drop-in (and, conversely, would not see one re-added there). enforce_for_root is a boolean directive: its mere presence enables it, which is why the check tests for the key rather than for a value.

describe command('grep -rqE \'^[[:space:]]*enforce_for_root\b\' /etc/security/pwquality.conf /etc/security/pwquality.conf.d/ 2>/dev/null && echo ok || echo ko') do
  its('stdout.strip') { should eq 'ok' }
end

How to verify it is applied

Confirm the directive is present in the resolved configuration set:

grep -rE '^[[:space:]]*enforce_for_root' /etc/security/pwquality.conf /etc/security/pwquality.conf.d/
/etc/security/pwquality.conf.d/99-pavois.conf:enforce_for_root = 1

The effective test is behavioural: as root, run passwd root and enter a deliberately weak password. With the directive active it is rejected (BAD PASSWORD: The password is shorter than N characters) instead of merely warned about.

Inspect & investigate

A rejection is logged by PAM in /var/log/auth.log (Debian/Ubuntu) or journalctl (RHEL family):

passwd[7788]: pam_pwquality(passwd:chauthtok): bad password: The password fails the dictionary check

Without enforce_for_root, the same line still appears for root, but the password change succeeds anyway: the log alone does not tell you whether the policy was enforced, which is why the behavioural test above matters.

Remediation

The Pavois harden plan uses a keyval remediation that writes enforce_for_root = 1 into its own drop-in, /etc/security/pwquality.conf.d/99-pavois.conf, rather than patching the distribution's pwquality.conf. The resource is aggregated: Pavois rewrites that drop-in with the complete set of pwquality keys it manages (minlen, minclass, difok, …), so the file always carries the full desired state. A key you add to 99-pavois.conf by hand is therefore overwritten at the next apply; put your own overrides in a separate drop-in file. On distributions driven by authselect (RHEL family), Pavois also enables the matching authselect feature so the PAM stack keeps calling pam_pwquality.

Pavois applies this with its own harden engine, the plan below, not a shell script:

file/etc/security/pwquality.conf.d/99-pavois.conf
keyenforce_for_root
resourcekeyval
value1
pavois harden plan local

where the target is local, a user@host SSH alias, or a container , Docs

Impact & precautions

Without enforce_for_root, the most privileged account of the machine is the only one allowed to pick a trivially guessable password, which defeats the whole policy. Enabling it has no effect on existing passwords and cannot lock anyone out: it constrains only future password changes made through PAM (passwd). Two consequences to anticipate. First, a break-glass procedure that relies on setting a simple root password will now be rejected: prepare a compliant password beforehand. Second, the directive covers only the PAM path; scripted changes that bypass PAM (usermod -p, writing a hash straight into /etc/shadow) are not filtered by pwquality, so provisioning tooling must apply the policy on its own.

Standards mapping

StandardReferenceTypeVersionConfidence
CIS5.3.3.2.8directper OS, see the benchmark tablehigh
NISTIA-5(c), IA-5(1)(a), CM-6(a), IA-5(4)supporting800-53 Rev 5 · 800-171 Rev 2 (pinned)medium

Each reference is a cross-reference anchored in the upstream benchmark and cross-validated against the SCAP Security Guide and ansible-lockdown, not a claim of equivalence. Direct = a prescriptive, line-level requirement; supporting = an abstract control family (NIST) the check provides evidence toward. How to read a mapping.

Sources & references