inbound-antispam-panel: findings of the technical and security reviews
test / test (push) Canceled after 0s
test / test (push) Canceled after 0s
Steps 11 and 12 of docs/plans/inbound-antispam-panel.md: 12/12. Two
read-only reviews of d65d632..HEAD by different models (Opus,
technical; Fable, security), each given the code and questions, not
conclusions. Nothing Critical or High in the feature; the High the
technical review found outside it is the commit before this one.
Log tailer (internal/logtail/inbound.go):
- the reply of a refusal ends at the first "; from=<", Postfix's own,
and the HELO name after it is whatever is left. Taking the longest
reply let a HELO name that spelt "; from=<..> to=<..> proto=.."
supply the row's sender, recipient and reply - and so make a
refusal read as the deny list's;
- an address with a quote, a bracket or a space is not kept: a quoted
sender could otherwise supply the recipient;
- the journal is cut to its row cap every 500 rows written, not only
every six hours;
- a queue id is forgotten when the message is queued or the id is
opened by another listener, and a stale place in the queue of
arrivals no longer drops a live id;
- milter-hold lines are not read: the held message reaches the
journal milter, which writes its row - it was written twice.
Lists (internal/inbound/lists.go): a change of the table and the
rewrite of the files are one step under a mutex; a failed rewrite puts
a removed entry back and rewrites after taking a new one out.
Store: the row cap removes the oldest by time, as the page orders them.
Page: on a sheet a refusal's text is a Reply whatever it starts with.
Help and the guide say that an allow entry for a sender address trusts
an address anyone can claim (design commit before this one).
docs/security.md: the two reviews; the roles table gains Inbound > Log
and Filter lists; Mail path describes the milters, the tailer and the
lists; four accepted risks - the filter's verdict while it is down, an
allow entry by sender address, the list files' mode, log rows held by
domain name. The plan's stale lines (size and rate refusals, who reads
the journal) are corrected.
Left as found, told to the owner: the journal's rows after an unclean
stop may be written twice (the tailer saves its place every five
seconds); a "Deny sender" link is offered for an address the form then
refuses; 1.2.3.4 and 1.2.3.4/32 are two entries.
Checked on the test server, uncommitted tree: go vet ./... ok,
go test ./... ok (22 packages), make e2e ok.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,33 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Security
|
||||
|
||||
- **The level-2 rate limit and an application's client IP list held only for
|
||||
the first message of a connection.** After a refused `MAIL FROM`, a second
|
||||
one on the same connection was accepted, and so was every message after the
|
||||
first that a connection carried: an application over its limit could go on
|
||||
sending, and one restricted to certain client addresses could send from any
|
||||
other with a retry. In the code since `1.9.0` (the client IP list) and
|
||||
earlier (the limit); found by the technical review of 2026-10-12 and
|
||||
reproduced on the test stand. Postfix now gives the panel's milters the
|
||||
client address with every message, the limit no longer depends on it, and an
|
||||
application with a client IP list is refused when no address is known.
|
||||
- Reviews of the inbound antispam feature before its release (technical and
|
||||
security, 2026-10-12; nothing Critical or High in the feature itself). Fixed:
|
||||
a client's HELO name could supply the sender, recipient and reply of an
|
||||
inbound log row; the log's row cap was applied only every six hours; rows of
|
||||
a connection's later messages had no client address; two changes of the
|
||||
filter lists at once could leave the filter's files behind the page; a held
|
||||
message was logged twice. Recorded as accepted in
|
||||
[docs/security.md](docs/security.md): the filter's verdict in the log is the
|
||||
sender's own while the filter is down; an allow entry for a sender address
|
||||
trusts an address anyone can claim; the list files are readable by anyone on
|
||||
the host.
|
||||
- `INBOUND_ANTISPAM_MILTER` and `INBOUND_JOURNAL_MILTER_SOCKET` are checked
|
||||
character by character at start; the check looked at their first characters
|
||||
only.
|
||||
|
||||
### Changed
|
||||
|
||||
- **Port 25 logs as `postfix/inbound`.** Its lines in the mail log (Server ›
|
||||
|
||||
Reference in New Issue
Block a user