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
Pass
compauth=pass reason=108
1xx
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.
🔗 Related Reason Codes
🔧 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.