-
0.47.0 Stable
released this
2026-08-25 18:45:29 -05:00 | 69 commits to main since this releaseThree defects in how a message's authentication is reported, all of them in
the direction of a confident wrong answer. One was firing on 100% of Gmail
messages; one would have made any future survey of the ARC chain wrong the same
way the last one was; the third is a check that was never wired up. A fourth
turned up while fixing them: the Gmail tenant shippedget_message_security
with noassessmentat all.Fixed
-
dmarc_policy_nonewas reported on every Gmail message, whatever the
sender publishes.decideread(results.dmarc_policy or "none"), which
collapses absent into p=none. The policy is recovered from iCloud's
X-DMARC-Policy; Gmail stamps no equivalent, so it is empty for every
message on that tenant — and the warning then asserted the weakest possible
policy for senders publishingp=reject. It contradicted
AuthResults.to_dicton the same payload, which correctly omitted the key.Absent and
noneare now two facts:dmarc_policy_unknownwhere nothing was
read,dmarc_policy_noneonly where a policy was read and isnone. The
authentication block sayspolicy_available: falsewith a note rather than
going silent, because an absent key reads as "nothing to say" and the reader
supplies their own prior. -
_parse_oneread the ARC instance tag as the authserv-id. RFC 8617 puts
i=Nin front of the identity, so on anARC-Authentication-Resultsthe
authserv-id is the second clause and every verdict lands a clause out. A
survey run through it reports "an authserv-id and nothing else" about a
header full of results — which is how that claim enteredmail/origin.py._parse_onetakes anarcflag andparse_arcreads those headers
properly. The flag rather than sniffing for a leadingi=: a plain
Authentication-Resultsis attacker-controlled untilis_trustedhas ruled
on it, and skipping ani=1there would let a sender write the receiving
server's own identity into their message.origin.py's claim survives the correction, and is now measured with a
parser that could have disproved it.probes/probe_origin_dkim.pyover the
4,602-message Gmail archive: the i=1 record really isi=1; mail.protonmail.chwith no verdicts, 258 of 258. What the old parser also
hid is the i=2 record sealed bymx.google.comon the same messages,
carryingdkim,dmarc,spfandarc— Google's verdicts about the
relay, which read as proof of the origin if the instance number is missed.
Parser and a raw regex now agree at 258; before the fix the parser said 0. -
A surviving original DKIM signature was never looked for.
_relay_signed_fromreadsAuthResults.dkimonly to confirm the relay
signedFrom, but the receiving MTA verifies every signature on a message
— and a forwarder that only adds headers does not break the original
sender's. Such a signature would make the origin a cryptographic verdict
rather than the relay's claim, lifting the restriction the module is built
around._origin_signednow checks for one: passing, not from a relay, and aligned
with the recovered origin.Origin.verified_bynames the signer and
claimedbecomes False.It fires on nothing, and that is the finding. 258 of 258 relayed messages
carry the relay's signature and nothing else — not one aligned original
signature, and none from any non-relay domain at all. SimpleLogin re-signs
what it forwards. So the claim/verdict distinction stands on evidence rather
than on inference, a gate tiered on origin authentication still has no input,
and the path is kept because it can only ever raise confidence, only ever on
a signature the receiving server verified. If a relay stops re-signing, the
next message says so instead of the next survey.provenancedeliberately stays"relayed"rather than gaining a
relayed_verified: the alias index filters on that exact string, and a new
one would have silently dropped every better-evidenced message out of the
historymail/aliases.pyis built on. -
Gmail's
get_message_securityreturned noassessment. iCloud has
carried it since 0.23.0. It is the sentence that stops four green ticks being
read as "this message is legitimate", and it is also where the relay caveats
live — that a relayed message's verdicts belong to the forwarder, and that a
policy read off such a message is the forwarder's. Gmail is the tenant where
56% of mail is relayed, so it needed it most and had it least. Every other
key was present and correct, which is why the gap was invisible.Under a relay the unknown-policy qualifier is deliberately suppressed: the
pass being qualified is the relay's, so naming "the policy this domain
publishes" would point at the wrong domain while sounding like the sender.
Verified
probes/probe_origin_dkim.py, read-only, both tenants, 2026-08-25. Like
every probe here it is gitignored — they read.envand print real account
data — so the counts above are a dated record against a named sample, not
something re-derivable from this repo.- Live on real relayed Gmail mail:
dmarc_policy_unknownin place of
dmarc_policy_none,policy_available: falsein the authentication block,
and the assessment present with its relay attribution intact.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-