logtail: Inbound log takes Postfix's own tail, not a recipient's (audit M2)
Security audit 2026-10-17, finding M2, stage 0 - proven on the live server: Postfix quotes a refused recipient in its reply in internal form (quotes removed, "; < > =" kept: extract_addr, tok822_internalize), so RCPT TO:<"; from=<ceo@…> to=<board@…> proto=ESMTP helo=<x>; "@domain> spelled a whole tail inside the reply, and inboundRejectRe, whose reply ended at the FIRST "; from=<", took the stranger's sender, recipient and inbound domain for the row. Now the reply is greedy and the tail anchored: "; from=<…> to=<…> proto=\S+", a HELO name holding none of Postfix's NEUTER_CHARACTERS (smtpd.c:1634, helo_cmd neuters ` <>()\";@`), and one-word SASL fields to the end of the line (a `.*` SASL tail would have let a quoted MAIL FROM spell the whole tail). Belt and braces: a reply that still holds "; from=<" - a line with two tails - makes no row, so neither a recipient nor an un-neutered HELO name can choose one. The quote/bracket/space filter on from/to stays. Tests: TestInboundRecipientCannotWriteTheRow (the live line's shape, and with a forged MAIL FROM too); TestInboundHeloCannotWriteTheRow now feeds HELO names as Postfix logs them (neutered) and expects no row for the un-neutered ones. go test ./internal/logtail on Windows (the three known Windows-only Follow failures aside). Docs: security.md § Mail path; CHANGELOG; plan line ticked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,11 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
|
||||
check. Adding a user, setting a password, changing an e-mail or a role on
|
||||
the user form, and deleting a user now ask for your own account password,
|
||||
as a backup does, under the same limit on wrong guesses.
|
||||
- **A stranger's recipient no longer writes an Inbound › Log row** (audit
|
||||
M2): Postfix quotes a refused recipient in its reply with the quotes
|
||||
removed, so `RCPT TO:<"; from=<x> to=<y> …"@domain>` spelled a second
|
||||
sender and recipient there, and the parser took the first. It now takes
|
||||
Postfix's own tail at the end of the line.
|
||||
- **The entrypoint follows no link at the DMARC maps** (audit I2): the
|
||||
three `dmarc_*` maps root creates at the start were missing from the list
|
||||
of paths where a symbolic link is removed first.
|
||||
|
||||
Reference in New Issue
Block a user