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

Verify /boot/grub2/user.cfg Permissions

Ensures /boot/grub2/user.cfg (the GRUB superuser password file) is readable and writable only by root, with no execute/setuid/setgid/sticky bits.

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 4 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

/boot/grub2/user.cfg stores the GRUB bootloader superuser password hash (PBKDF2). If group or other can read it, an attacker can crack the hash offline and gain the GRUB superuser password, letting them edit boot entries, drop to a root shell via init=/bin/bash, or disable security at boot, a full bypass of OS-level access controls. If the file is writable by a non-root user, they can replace or remove the password protection entirely. Only root should read or modify it.

What Pavois checks

Pavois reads the effective inode mode of /boot/grub2/user.cfg and asserts no read/write for group or other and no special bits. Checking the live file (rather than assuming the generator wrote it correctly) catches cases where the file was regenerated, copied, or chmod-ed after creation and silently became group/world-readable.

only_if { file('/boot/grub/user.cfg').exist? }
describe file('/boot/grub/user.cfg') 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 '%U %G %a' /boot/grub2/user.cfg. Expected: owner/group root with mode 600 (or 0600), readable/writable by root only, no bits for group/other.

Inspect & investigate

There is no runtime log for this file. Integrity drift can be detected with rpm -Vf /boot/grub2/user.cfg (RHEL/Alma/Fedora). GRUB regeneration that may rewrite it is triggered by grub2-mkconfig; review its output and re-check the mode afterward.

Remediation

No automated remediation ships for this rule. Tighten the file manually: chown root:root /boot/grub2/user.cfg && chmod 600 /boot/grub2/user.cfg.

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

mode0600
path/boot/grub/user.cfg
resourcefile
pavois harden plan local

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

Impact & precautions

A readable user.cfg leaks the GRUB superuser hash (offline crackable, leading to boot-time root access); a writable one lets an attacker disable boot password protection. Setting it to 0600 root:root is safe and matches the GRUB default. Precaution: do not delete or empty the file, that removes GRUB password protection. Re-run grub2-mkconfig only when needed, since regeneration can reset the mode.

Standards mapping

StandardReferenceTypeVersionConfidence
ANSSI BP-028R29direct2.0high
CIS2.2.6, 1.4.2directper OS, see the benchmark tablehigh
NIST3.4.5, AC-6(1), CM-6(a)supporting800-53 Rev 5 · 800-171 Rev 2 (pinned)medium
PCI DSS2.2.6supporting4.0.1medium

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