Skip to content

fix(emailauth): IDNA-encode domains before DMARC DNS lookups - #931

Merged
jiashuoz merged 1 commit into
tokencanopy:mainfrom
AmirF194:fix/608-dmarc-idna-unicode-domain
Aug 23, 2026
Merged

fix(emailauth): IDNA-encode domains before DMARC DNS lookups#931
jiashuoz merged 1 commit into
tokencanopy:mainfrom
AmirF194:fix/608-dmarc-idna-unicode-domain

Conversation

@AmirF194

Copy link
Copy Markdown
Contributor

Summary

normDomain lowercased and trimmed a domain but never converted it to
its ASCII/punycode form. The DMARC tree walk builds every
_dmarc.<domain> TXT lookup from that value (discoverDMARCRecordWithEvaluator,
walkDMARCTree), so a message with an internationalized From domain
queried the raw Unicode label instead of the label the DNS zone
actually publishes records under, and evaluation silently degraded to
policy=none. internal/identity.normalizeDomain already does
lowercase + idna.Lookup.ToASCII for stored domains; this applies the
same pattern to the inbound auth path, with the same fallback to the
unmodified string on an encoding error.

Operational risk

None outside the emailauth package. normDomain also feeds the
displayed SPF/DKIM domain fields; those are already-ASCII values in
practice (SMTP HELO and DKIM d= tags), and the full existing suite
for this package (including those cases) is unchanged by this diff.

Test plan

  • TestEvaluateDMARCEncodesUnicodeFromDomainForLookup (new):
    fails on main (queries _dmarc.münchen.example, the record
    under the punycode name is never found), passes on this branch.
  • go test ./internal/emailauth/...: full package suite green.
  • go build ./... and go test ./...: unaffected elsewhere.
  • Not checked: real DNS resolution against a live internationalized
    domain (fakeTXTResolver only); the query-name construction is what
    this fix changes and what the test asserts.

Fixes #608

normDomain lowercased and trimmed a domain but never converted it to
its ASCII/punycode form. Every "_dmarc."+domain TXT lookup in the
DMARC tree walk is built from that value, so a message with an
internationalized From domain queried the raw Unicode label instead
of the label the DNS zone actually publishes records under, and
silently fell back to policy=none. internal/identity already has the
same lowercase+idna.Lookup.ToASCII pattern for stored domains; this
applies it to the inbound auth path too, with the same fallback to
the unmodified string on an encoding error.

Fixes tokencanopy#608
@AmirF194
AmirF194 requested a review from jiashuoz as a code owner August 23, 2026 15:25

@jiashuoz jiashuoz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution!!

@jiashuoz
jiashuoz merged commit fe0a52e into tokencanopy:main Aug 23, 2026
29 checks passed
@AmirF194

Copy link
Copy Markdown
Contributor Author

Thanks for the quick review and merge. Glad the IDNA fix lines up cleanly with the pattern already in identity/store.go.

@AmirF194
AmirF194 deleted the fix/608-dmarc-idna-unicode-domain branch August 23, 2026 21:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(emailauth): close remaining RFC 9989 DMARC gaps

2 participants