Verify Permissions on SSH Server config file
Ensures /etc/ssh/sshd_config is owned by root with no read/write/execute for group or other, protecting the SSH daemon's master policy from tampering and disclosure.
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
/etc/ssh/sshd_config is the master configuration of the SSH daemon and enables or disables security-critical features (root login, password vs. key auth, ciphers, allowed users). If it is writable by group or other, a non-privileged user could alter it to weaken remote access or plant a backdoor that takes effect on the next reload; if readable by group/other, the access policy is disclosed to anyone on the host. The file must be owned by root with no read/write/execute for group or other and no special bits, so only the administrator controls the SSH server policy.
What Pavois checks
Pavois reads the effective inode mode of /etc/ssh/sshd_config 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').exist? }. Note: this control covers the permissions of the file; the effective SSH policy itself (which can be overridden by Included drop-ins) is what sshd -T reports, Pavois's service controls audit that resolved state, while this rule locks down the file that seeds it.
only_if { file('/etc/ssh/sshd_config').exist? }
describe file('/etc/ssh/sshd_config') 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 }
endHow to verify it is applied
Run stat -c '%a %U %G' /etc/ssh/sshd_config. The expected output is 600 root root (or stricter): no read, write or execute for group or other.
Inspect & investigate
stat /etc/ssh/sshd_config shows the current mode; sshd -T shows the effective policy it produces. SSH service and auth events are in journalctl -u ssh / /var/log/auth.log (Debian/Ubuntu) or journalctl -u sshd / /var/log/secure (RHEL family). File modifications 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 then chmod 0600 /etc/ssh/sshd_config.
Pavois applies this with its own harden engine, the plan below, not a shell script:
| group | root |
|---|---|
| mode | 0600 |
| owner | root |
| path | /etc/ssh/sshd_config |
| 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 lets an unprivileged user re-enable root login, switch on password auth, or whitelist a backdoor account on the next reload, a critical remote-access compromise; a readable one leaks the access policy. Precautions: tightening to 0600 root:root does not interrupt active SSH sessions and matches the distro default, so it is low-risk. Run sshd -t to validate syntax before any reload to avoid bringing the daemon down and locking yourself out, and keep at least one authenticated session open during changes.
Standards mapping
| Standard | Reference | Type | Version | Confidence |
|---|---|---|---|---|
| ANSSI BP-028 | R50 | direct | 2.0 | high |
| CIS | 2.2.6, 5.1.1, 5.1.2 | direct | per OS, see the benchmark table | high |
| NIST | AC-17(a), AC-6(1), CM-6(a) | supporting | 800-53 Rev 5 · 800-171 Rev 2 (pinned) | medium |
| PCI DSS | 2.2.6 | supporting | 4.0.1 | medium |
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.