| Age | Commit message (Collapse) | Author | Files | Lines |
|
The for-clause rule anchored on the clause terminator, which is strictly
stronger than RFC 5321 4.4: For sits inside Opt-info, so With, ID, Via or a
CFWS comment may legitimately follow it, and its ABNF is 1*( Path / Mailbox )
where Mailbox carries no angle brackets. Only the tidiest shape was stripped.
Four ordinary ones published the victim's address in the one header a report
reproduces verbatim, including "for <a@b> (envelope-from <c@d>);", which is
routine Exim and Sendmail output.
Anchored on the address instead. The envelope SENDER survives the cut, since
that is what the report is about, and the leftover whitespace, orphan
separator and emptied comment are tidied because the line is published to a
third party verbatim. Table-driven over all five shapes; reverting the regex
fails six of nine tests in the class.
Two accepted disclosures are now named in the spec's "Where the headers come
from" rather than living in a test comment: our own relay's hostname, which
the by and authserv-id clauses carry by construction, and attacker-controlled
free text in Subject and the From display name, which the whitelist does not
and should not filter. The second is asserted as a documented limit so it
reads as deliberate, and the manifest assertion now bars the obfuscated
you%40example.org spelling alongside the plain one.
case.create() seeds an empty headers block so an unparsed case has the same
shape as a parsed one. Additive, so FORMAT_VERSION is unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xj1ayFRSUQ2u7cwb3S4axE
|
|
report must never open source.eml, so parse decides once what may be
published and report formats only what it is given. To, Cc, Delivered-To and
X-Original-To are absent by construction rather than stripped.
Received is cut to the boundary hop alone, in both directions. Above it are
our own relays; below it is the attacker's own writing, and a forged chain
names an innocent third party there, so publishing a hop below the boundary
puts someone else's address into a report a desk will act on. That is the
third property applied to disclosure rather than to sending_ip().
Truncating the chain was not sufficient on its own: the surviving line is
written by our own relay and records the envelope recipient in its optional
"for <addr>" clause, so the whitelist alone would have published the
victim's address verbatim in the one header a report reproduces in full.
The clause is removed and the rest of the hop kept.
The manifest-wide "no example.org" assertion is narrowed to the headers
block only, where the whitelist deliberately publishes our receiving relay's
name in a by/authserv-id clause. The address itself is still barred there,
asserted separately.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xj1ayFRSUQ2u7cwb3S4axE
|
|
A re-run overwrites contacts[] wholesale rather than merging. A merge
would let a contact resolved a week ago survive into a report filed
today, which is the stale-address hazard the response caching policy
already refuses, and overwriting makes a re-run always safe, which
matters because a partial network failure makes re-running the natural
next step.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wrfqr2xqQfhtXCscU7zrdz
|
|
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KphFXTc2QajxXsHWyvGJ4R
|