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

Verify Permissions on cron.monthly

Ensures the /etc/cron.monthly directory is owned by root and is not readable, writable or executable by group or other, with no setuid/setgid/sticky bits, so only root can add or change monthly cron scripts.

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

/etc/cron.monthly holds scripts the cron daemon runs once a month as root. If the directory is writable by group or other, an unauthorized user can plant or modify a script that runs with root privileges, full compromise. If it is readable by group/other, the jobs can be enumerated for reconnaissance. Restricting it to the owner prevents both unauthorized changes and disclosure.

What Pavois checks

Pavois reads the live inode with file('/etc/cron.monthly') and asserts no group/other access and no special mode bits, gated by only_if to skip when absent. Inspecting effective on-disk permissions catches drift from package upgrades, manual chmod, or backup restores that a config-template assumption would miss.

only_if { file('/etc/cron.monthly').exist? }
describe file('/etc/cron.monthly') do
  it { should_not be_setuid }
  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/cron.monthly. Expected: mode 700 (or stricter), owner root, group root, no read/write/execute for group or other, and no setuid/setgid/sticky bit.

Inspect & investigate

No service log applies; inspect with stat /etc/cron.monthly or ls -ld /etc/cron.monthly. To detect tampering, add an auditd watch (auditctl -w /etc/cron.monthly -p wa -k cron) and grep /var/log/audit/audit.log for key="cron".

Remediation

No automated remediation is defined, so apply it manually: chown root:root /etc/cron.monthly && chmod 700 /etc/cron.monthly. Re-run the scan to confirm the rule passes.

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

grouproot
mode0700
ownerroot
path/etc/cron.monthly
resourcedirectory
pavois harden plan local

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

Impact & precautions

Risk if left misconfigured: a group/other-writable cron.monthly is a root-code-execution and persistence vector; a readable one leaks the schedule. Precautions: restricting to root:root 700 is safe, the cron daemon runs as root. Confirm no non-root tooling legitimately writes here before tightening, and keep ownership at root:root.

Standards mapping

StandardReferenceTypeVersionConfidence
CIS2.2.6, 2.4.1.6directper OS, see the benchmark tablehigh
NISTAC-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