← All rules
SOCLE-CLD-FSP-144// File permissionsmediumpersistent config

Verify Permissions on /etc/security/opasswd File

Ensures /etc/security/opasswd is unreadable and unwritable by group and other (no setuid/setgid/sticky/exec), so only root can access the password-history hashes.

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 22.04CIS 3.0.0Ubuntu 24.04CIS 1.0.0Ubuntu 26.04
One check, maps to 1 standard

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

/etc/security/opasswd is the password-history file used by pam_pwhistory/pam_unix to prevent users from reusing old passwords. It contains old password hashes, so it is as sensitive as /etc/shadow. If it is readable by group or other, those hashes become available for offline cracking; if it is writable, an attacker could erase history to allow password reuse or inject crafted entries. setuid/setgid/executable bits have no purpose here. Only root must be able to read or write it.

What Pavois checks

Pavois reads the live mode bits of /etc/security/opasswd on the target, including the group/other read bit (not just write), because the threat here is hash disclosure. Permissions are inode metadata, so the audit reflects exactly what the kernel enforces, no include or drop-in to subvert. The only_if guard skips the control when no history file exists yet.

only_if { file('/etc/security/opasswd').exist? }
describe file('/etc/security/opasswd') do
  it { should_not be_executable.by('owner') }
  it { should_not be_setuid }
  it { should_not be_executable.by('group') }
  it { should_not be_writable.by('group') }
  it { should_not be_readable.by('group') }
  it { should_not be_setgid }
  it { should_not be_executable.by('other') }
  it { should_not be_writable.by('other') }
  it { should_not be_readable.by('other') }
  it { should_not be_sticky }
end

How to verify it is applied

Run stat -c '%A %U %G' /etc/security/opasswd. Expected: mode -rw------- (0600), or 0640 root:root at most, owned by root root, with no read/write bit for group or other. Quick check: find /etc/security/opasswd -perm /0177 must return nothing.

Inspect & investigate

Permission changes are not logged by default. Watch this sensitive file with auditd: auditctl -w /etc/security/opasswd -p wa -k identity, then review with grep 'key="identity"' /var/log/audit/audit.log. PAM password-history activity appears in /var/log/auth.log (Debian/Ubuntu) or journalctl -u systemd-logind//var/log/secure (RHEL). Current mode and ownership: stat /etc/security/opasswd.

Remediation

No automated harden plan ships for this rule yet, so it must be applied manually: chown root:root /etc/security/opasswd && chmod 0600 /etc/security/opasswd. This removes all group/other access and any setuid/setgid/sticky bits, limiting the password-history hashes to root.

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

mode0600
path/etc/security/opasswd
resourcefile
pavois harden plan local

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

Impact & precautions

Risk if left mis-set: world/group read exposes old password hashes for offline cracking, which can reveal reused or weak passwords still in use elsewhere. Applying the fix is safe, 0600 root:root is the expected mode and only pam_unix (running as root during password change) needs access. Precaution: do not loosen to 0644; unlike /etc/passwd, this file must not be world-readable.

Standards mapping

StandardReferenceTypeVersionConfidence
CIS7.1.10directper OS, see the benchmark tablehigh

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