The issue of what headers to include in your DKIM signatures

October 26, 2023

Increasingly, you have to sign your outgoing email messages with DKIM. When you use DKIM to sign things, in one sense you're signing an abstract 'email message', and in another, more concrete sense, you're signing the email body plus some of the email message headers. You might innocently think that the message headers to sign are standardized and obvious, but I've recently learned that neither is the case due to a recent discussion on the Exim mailing list. Different mail systems may sign different sets of headers in ways that are more or less aggressive, and some of these ways have downstream effects.

(This is especially relevant to Exim, where the default configuration of what headers to sign is perhaps somewhat aggressive.)

A basic part of DKIM signing is that if a message doesn't have a particular header and you include it in the DKIM signature headers anyway, what you're doing is signing that there is no such header in the email; basically, the header is interpreted as having a null value. If someone adds the header later, it will have a non-null value and so fail the DKIM signature check. Signing nonexistent headers is important if you think that adding them would change the meaning of the message as people perceive it (or as they see it).

As far as what headers to include goes, RFC 6376 provides relatively little guidance in section 5.4 and then a big and somewhat questionable list in section 5.4.1. Some headers are in practice part of the meaning of the message as people reading it will perceive things; in this category I'd include From: (which is required anyway), Subject: and Date:, and probably To:, cc:, and Reply-To:, and in practice I'd roll in In-Reply-To and References and some others. Some headers will change the interpretation of the message body if modified so must be protected by the DKIM signature; this includes all MIME related headers.

But then you have headers that may or may not change what you see as the meaning of the message if they're added to it after your signature. In this category are both the Resent-* family of headers for resent messages and especially the List-* family of mailing list headers. In some environments, whether a message was sent directly to people or came through a (visible) mailing list matters, as does what mailing list; in those environments you probably want to include the List-* headers in your DKIM signatures. But in other environments, this is not critical and in fact your people may be sending messages to outside mailing lists and want this to not break the DKIM signatures of their messages so the post-mailing-list version of their email is still accepted by, for example, GMail.

(You can have a similar discussion about Resent-*. Maybe these headers should never be signed, maybe they should be signed only if they're present, and maybe they should always be signed so that if someone visibly resends a signed message, it no longer passes DKIM verification.)

Now that I'm aware of this issue, we're probably going to change away from the Exim default (which signs all of the section 5.4.1 headers, plus the MIME headers) to something where we definitely don't sign the List-* headers and probably don't sign the Resent-* headers.

PS: One of the reasons to not sign Resent-* and List-* headers is that in both cases, you can do resending and mailing lists without changing the headers at all. Breaking DKIM signatures if people actually do add headers thus only encourages them to not add the headers; since adding the headers is useful and nice, we shouldn't discourage people from doing so.

Written on 26 October 2023.
« There are at least two ways to 'verify' TLS client host certificates
Alerting on sticky configuration reload failures for Prometheus »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Thu Oct 26 23:20:19 2023
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.