← All rules
SOCLE-CLD-GEN-047// Hardening (misc)mediumeffective runtime

Disable Postfix SMTP VRFY Command

Set disable_vrfy_command = yes so the Postfix SMTP server refuses the VRFY verb. VRFY asks the server whether a mailbox exists, and the server answers truthfully, which turns any reachable MTA into a free user-enumeration oracle: an attacker harvests valid local accounts one probe at a time, then feeds them to a password-spraying or phishing campaign.

Checked against the resolved running state (e.g. sshd -T, sysctl, systemctl show), catches drop-ins and Includes a file read would miss. Caveat: runtime ≠ persistence; a value correct now may not survive a reboot.

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

What Pavois checks

Pavois queries the effective parameter with postconf -h disable_vrfy_command, which prints the value Postfix will actually use, after main.cf and the built-in defaults (the default is no, so a main.cf that simply omits the parameter is exposed). Grepping /etc/postfix/main.cf would make a missing line look inconclusive instead of the non-compliance it really is. When postconf is absent (Postfix not installed) the control returns ok: an MTA that does not exist cannot leak.

describe command('if ! command -v /usr/sbin/postconf >/dev/null 2>&1; then echo ok; elif /usr/sbin/postconf -h disable_vrfy_command 2>/dev/null | grep -qi ''^yes''; then echo ok; else echo ko; fi') do
  its('stdout.strip') { should eq 'ok' }
end

How to verify it is applied

Read the resolved value, then prove it on the wire:

postconf -h disable_vrfy_command      # must print: yes
printf 'VRFY root\r\nQUIT\r\n' | nc localhost 25

A hardened server answers 502 5.5.1 VRFY command is disabled. Without the setting it answers 252 or 250, confirming the account exists.

Inspect & investigate

Postfix logs SMTP sessions to /var/log/mail.log (Debian, Ubuntu) or /var/log/maillog (RHEL), also reachable via journalctl -u postfix. Once the command is disabled, enumeration attempts leave a visible trail of rejected VRFY verbs from a single source: that pattern is worth an alert, because a probe that keeps trying is reconnaissance, not a misconfigured client.

Remediation

Pavois runs the postfix-anti-vrfy step: it calls postconf -e 'disable_vrfy_command = yes' (the supported way to edit main.cf, rewriting the parameter in place), falls back to a de-duplicating sed plus append when postconf is unavailable, then reloads Postfix. A not_if guard skips the step when main.cf already carries the setting, keeping confkit harden apply idempotent.

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

commandmkdir -p /etc/postfix; touch /etc/postfix/main.cf; if command -v postconf >/dev/null 2>&1; then postconf -e 'disable_vrfy_command = yes'; else sed -ri '/^disable_vrfy_command/d' /etc/postfix/main.cf; echo 'disable_vrfy_command = yes' >> /etc/postfix/main.cf; fi; systemctl reload postfix 2>/dev/null || true
namepostfix-anti-vrfy
not_ifgrep -Eqs '^disable_vrfy_command[[:space:]]*=[[:space:]]*yes' /etc/postfix/main.cf
resourceexec
pavois harden plan local

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

Impact & precautions

No effect on mail delivery: VRFY is a diagnostic verb, outside the message path, and modern clients never use it. The only things that break are the rare monitoring probes or address-validation scripts that still call VRFY; migrate them to a RCPT TO against a test recipient, or to a local postmap -q lookup. The remediation reloads Postfix rather than restarting it, so the mail queue is untouched.

0