Verify Permissions on SSH Server Config File
Ensures the /etc/ssh/sshd_config.d drop-in directory is owned by root with no access for group or other, so SSH config fragments cannot be added or read by unprivileged users.
Checked against the content of a persistent configuration file, the source of truth that survives reboots.
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 /etc/ssh/sshd_config.d directory holds drop-in fragments that are included by the main sshd_config and that can enable or disable security-critical SSH features (authentication methods, ciphers, root login). If the directory is writable by group or other, a non-privileged user could add a drop-in that weakens or backdoors the SSH daemon on the next reload; if readable beyond root, the configuration surface is disclosed. The directory must be owned by root with no read/write/execute for group or other so only the administrator controls the effective SSH configuration.
What Pavois checks
Pavois reads the effective directory mode of /etc/ssh/sshd_config.d and asserts no read/write/execute for group or other and no setuid/setgid/sticky bits. Guarded by only_if { file('/etc/ssh/sshd_config.d').exist? }. Because sshd assembles its effective policy from every fragment in this directory, securing the directory is what actually prevents an attacker from injecting an Included override, checking the live inode reflects that real attack surface.
only_if { file('/etc/ssh/sshd_config.d').exist? }
describe file('/etc/ssh/sshd_config.d') do
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 }
endHow to verify it is applied
Run stat -c '%a %U %G' /etc/ssh/sshd_config.d. The expected output is 700 root root (or stricter): no read, write or execute for group or other. Confirm the resulting effective config with sshd -T after a reload.
Inspect & investigate
stat /etc/ssh/sshd_config.d shows the directory mode. The effective SSH policy assembled from its fragments is shown by sshd -T. SSH service events are in journalctl -u sshd (RHEL/Fedora) and authentication attempts in /var/log/secure. Directory changes appear in /var/log/audit/audit.log if watched.
Remediation
No automated harden plan is defined for this rule yet, so apply it manually: chown root:root /etc/ssh/sshd_config.d then chmod 0700 /etc/ssh/sshd_config.d.
Pavois applies this with its own harden engine, the plan below, not a shell script:
| mode | 0700 |
|---|---|
| path | /etc/ssh/sshd_config.d |
| resource | file |
pavois harden plan localwhere the target is local, a user@host SSH alias, or a container , Docs
Impact & precautions
A group- or world-writable sshd_config.d lets an unprivileged user drop in an override (e.g. PermitRootLogin yes, weak ciphers, an authorized backdoor) that takes effect on the next sshd reload, a serious remote-access compromise. Precautions: changing only the directory permissions does not affect live SSH sessions, so it is safe; just keep the directory owned by root and 0700, and validate with sshd -t (config test) before reloading to avoid an sshd that fails to restart.
Standards mapping
| Standard | Reference | Type | Version | Confidence |
|---|---|---|---|---|
| CIS | 5.1.1 | direct | per OS, see the benchmark table | high |
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.