reason=108: Passed, but an earlier hop broke the DKIM signature

compauth reason=108 means DKIM failed because a hop Microsoft considers legitimate modified the message body, typically your own on-premises Exchange. A plumbing problem, not an attack.

Published · Last verified · Maintained by TamingDNS

Verdict
Pass
Stamped as
compauth=pass reason=108
Family
1xx
Seen on
Microsoft 365 only

📖 What Microsoft Says

DKIM failed due to a message body modification attributed to previous legitimate hops. For example, the message body was modified in the organization's on-premises email environment.

Verbatim from Anti-spam message headers in Microsoft 365, "Composite authentication Reason codes". Everything below is our reading of it.

💬 What It Actually Means

DKIM signs the body. Something rewrote the body after it was signed, so the signature no longer verifies. Microsoft attributed the change to a hop it considers legitimate rather than to an attacker. Composite authentication passed anyway.

What happens to the message

The message goes through, but the DKIM failure is real and it is yours. Anywhere that does not extend Microsoft's benefit of the doubt sees a broken signature and judges accordingly.

What to do

Find what is rewriting the body. In a hybrid deployment the usual culprit is on-premises Exchange, and disclaimer or footer injection is the classic case: appending a signature block to a signed message invalidates it. Anything that touches the body after signing does the same: a gateway, a legacy DLP appliance, a link rewriter. Signing after the modification rather than before it is the fix.

⚠️ Easily confused with

A plain dkim=fail with no reason=108 means Microsoft did not attribute the change to a trusted hop, which is a different and worse situation.

📋 What It Looks Like in a Header

Paste your own headers into the email header analyser to see this line decoded against the rest of the message.

Authentication-Results: spf=pass (sender IP is 192.0.2.44)
    smtp.mailfrom=contoso.com;
    dkim=fail (body hash did not verify) header.d=contoso.com;
    dmarc=pass action=none header.from=contoso.com;
    compauth=pass reason=108

"body hash did not verify" is the tell. The signature itself is intact; the body it covers is not the body that arrived.

🔧 Check It Yourself

A reason code is one line of one header. These read the rest of the picture: what the domain publishes, and whether the message that carried this code holds up.

Check the signing selector → Analyse the full headers →
← All COMPAUTH reason codes