Skip to content

DKIM probe: TXT fallback for Google Workspace (google._domainkey) — fixes the CNAME-only asymmetry - #34

Open
fpietrosanti wants to merge 1 commit into
mxmap:mainfrom
fpietrosanti:fix/google-dkim-txt-fallback
Open

DKIM probe: TXT fallback for Google Workspace (google._domainkey) — fixes the CNAME-only asymmetry#34
fpietrosanti wants to merge 1 commit into
mxmap:mainfrom
fpietrosanti:fix/google-dkim-txt-fallback

Conversation

@fpietrosanti

Copy link
Copy Markdown

Re-filing davidhuser/mxmap#28 here at the maintainer's request (that repo is frozen in favour of this one). Issues are disabled on this repository, so I'm filing the report as a PR with the fix included — happy to adapt or split it however you prefer.

Problem

probe_dkim queries CNAME only (resolve_robust(qname, "CNAME") + dkim_cname_patterns). But standard Google Workspace publishes its DKIM key as a TXT record at google._domainkey.<domain> (v=DKIM1; k=rsa; p=...), not a CNAME. So the GOOGLE signature's dkim_selectors=("google", "google2048") can never fire for ordinary Google tenants — effectively dead code — while the equivalent Microsoft signal (selector1/selector2 CNAME → *.onmicrosoft.com) works.

This matters most behind gateways/relays: the MX points at the filter and SPF is often ambiguous, so DKIM is the decisive backend signal — and it's structurally unavailable for Google.

Quick check:

dig +short TXT   google._domainkey.<domain>   → "v=DKIM1; k=rsa; p=..." on Google Workspace tenants
dig +short CNAME google._domainkey.<domain>   → (empty)

Fix

When the CNAME query for a selector yields nothing and the signature is GOOGLE, fall back to a TXT query on the same qname; a v=DKIM1 answer is emitted as Google Evidence (same SignalKind.DKIM weight). The fallback is gated to the Google signature because its selector names are Google-distinctive — a stray TXT at selector1 must not classify (covered by a test).

CNAME behaviour is unchanged; 3 tests added mirroring the existing mock style. tests/provider_classification/test_probes.py: 68/68 pass.

Field validation (Italian PA dataset, ~23k entities)

We run a downstream fork for Italian public administrations (mxmap-it/mxmap.it, tracking issue #17) and validated exactly this fallback against all entities already classified as Google by other signals:

  • Recall of the new signal: 1,057 / 6,405 confirmed-Google domains (16.5%) publish a google._domainkey TXT key — every one of them invisible to the CNAME-only probe.
  • False positives: 4 / 600 Microsoft-classified domains (0.67%), all dual-config tenants; weighted multi-signal scoring resolves them cleanly in favour of the mailbox host.

Public, verifiable examples (Italian): carabinieri.it, izssicilia.it — TXT present, CNAME absent.

🤖 Generated with Claude Code

probe_dkim was CNAME-only, but standard Google Workspace publishes its DKIM
key as a TXT record (v=DKIM1) at google._domainkey — so the GOOGLE signature's
dkim_selectors could never fire. When the CNAME query for a Google selector
yields nothing, fall back to a TXT query and treat a v=DKIM1 answer as Google
DKIM evidence. Fallback is gated to the Google signature: its selector names
are Google-distinctive, unlike selector1/selector2.

Field-validated on the Italian PA dataset (mxmap-it/mxmap.it fork): 1,057 of
6,405 confirmed-Google domains (16.5%) publish the TXT key and were invisible
to the CNAME-only probe; false positives 4/600 (0.67%, dual-config tenants).

Re-files davidhuser/mxmap-ch#28 per maintainer request.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant