← All rules
SOCLE-CLD-FSP-133// File permissionsmediumfilesystem state

Verify Permissions on /etc/audit/rules.d/*.rules

Ensures every *.rules file in /etc/audit/rules.d/ is no more permissive than 0640 (no group/other write, no other read, no special bits).

Checked against a path’s metadata, mode, owner, group, SUID/SGID.

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

The *.rules fragments under /etc/audit/rules.d/ declare which syscalls, files and events auditd watches, they are compiled into the active ruleset at boot. If they are writable by group or other, an attacker can delete or weaken rules to blind the system to their actions; if readable by other, they reveal exactly what is (and is not) monitored, helping evasion. Restricting them to root keeps the audit policy tamper-proof and confidential.

What Pavois checks

Pavois runs find /etc/audit/rules.d -name "*.rules" -perm /0137 and expects an empty result: the /0137 mask matches any file carrying group-write, other-read, other-write or any execute bit. Because it scans the directory at audit time rather than trusting a packaged template, it catches new fragments dropped in by Ansible, a cookbook or an operator, the same drop-in blind spot that file-template scanners miss.

only_if { file('/etc/audit/rules.d').exist? }
describe command('find /etc/audit/rules.d -name "*.rules" -perm /0137 2>/dev/null') do
  its('stdout') { should eq '' }
end

How to verify it is applied

Run find /etc/audit/rules.d -name '*.rules' -perm /0137 -ls. Expected output is nothing (all fragments are 0640 or stricter, owned by root). Any line printed names a non-compliant file. You can also confirm with stat -c '%a %n' /etc/audit/rules.d/*.rules and expect each mode to be 640 or lower.

Inspect & investigate

auditd compiles these fragments at start; check journalctl -u auditd and auditctl -l to confirm the expected rules loaded, and /var/log/audit/audit.log (grep CONFIG_CHANGE) for any tampering. A permission fix that follows a rule edit should be followed by augenrules --load.

Remediation

Pavois's harden plan runs an exec resource named chmod-audit-rulesd: chmod 0640 /etc/audit/rules.d/*.rules, guarded by a not_if that re-runs the same find so it is a no-op once compliant (idempotent). Apply it with pavois harden apply. It does not re-load auditd, so run augenrules --load (or restart auditd) afterwards if rules changed.

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

commandchmod 0640 /etc/audit/rules.d/*.rules 2>/dev/null || true
namechmod-audit-rulesd
not_iftest -z "$(find /etc/audit/rules.d -name '*.rules' -perm /0137 2>/dev/null)"
resourceexec
pavois harden plan local

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

Impact & precautions

Setting 0640 on rule fragments is safe, auditd reads them as root. Precautions: the remediation only tightens permissions, never edits rule content, so monitoring coverage is unaffected. Verify auditd still loads the policy afterwards with auditctl -l. The only way to break things is an unrelated bad rule edit; the chmod itself cannot cause a lockout. Leaving fragments group/other-writable would let an unprivileged process silently disable auditing. Directory traversal (RHEL): /etc/audit/rules.d is a directory, keep its owner search bit (0750); a file-style 0600/0640 strips x, and under SELinux enforcing auditd is denied dac_read_search and fails to start. Recover with chmod 750 /etc/audit/rules.d && restorecon -R /etc/audit.

Standards mapping

StandardReferenceTypeVersionConfidence
CIS6.2.4.5, 6.3.4.5directper OS, see the benchmark tablehigh
NISTAU-12(b)supporting800-53 Rev 5 · 800-171 Rev 2 (pinned)medium
DISA STIGUBTU-22-653065, UBTU-24-900040directper OS STIG releasehigh

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