Hardening DKIM: oversigning, replay resistance, and the l= tag
A valid DKIM signature can be abused: replayed at scale, extended with unsigned headers, or exploited via partial body coverage. The hardening measures that limit it.
DKIM's guarantees are precise: the signed content of this message was authorized by the signing domain. Everything outside that guarantee is attack surface. Headers not covered by the signature can be added afterward, body content beyond an l= limit can be appended, and the message as a whole can be re-sent to anyone, signature intact. Hardening DKIM means shrinking each of those gaps deliberately.
Oversigning: closing the unsigned-header gap
The h= tag in the signature header covers the headers it lists, as they existed at signing. It says nothing about headers added later: a second Subject, an extra Reply-To, another From. Since many clients display the newest instance of a duplicated header, an attacker holding a signed message can change what the recipient sees without touching what was signed. Oversigning closes this: listing a header in h= once more than it appears signs its absence, so any later addition invalidates the signature.
1h=from:from:to:to:cc:cc:subject:subject:date:date:
2 reply-to:reply-to:message-id:message-id;
3
4Each doubled entry covers one existing instance plus the
5absence of a second one. Adding any of these headers after
6signing now breaks verification.Oversign the display-relevant, mutable headers: From, To, Cc, Subject, Date, Reply-To, Message-ID. OpenDKIM, Rspamd, and serious ESP platforms all support it, and the cost is a few bytes per message. This is the cheapest hardening step in email.
The l= tag: delete it wherever found
The l= tag limits the body hash to the first N bytes, meaning anything appended after that point rides along with a valid signature. Security research published in 2024 demonstrated practical attacks: appended HTML that visually replaces the signed content while the signature keeps verifying. The mailing-list edge case that justified l= no longer outweighs a demonstrated content-injection vector, and provider guidance is unanimous. No production signature should carry l=, and finding one in an audit is a same-week fix.
Replay: the abuse DKIM permits by design
A DKIM signature validates the message, not the transmission: nothing in it names the recipients or bounds the send count. An attacker who legitimately receives one signed message, by signing up for a service and provoking a signed notification with attacker-influenced content, can re-transmit it to millions of recipients with the signature verifying everywhere. SPF fails on the replay hops; DKIM passes, DMARC passes, and the complaints accrue to the signing domain's reputation. The victims are usually ESPs, freemail providers, and SaaS platforms with open signup and strong domain reputation.
Replay resistance in practice
Bounding what a captured signature is worth
- 1
Segment signing identities
User-triggered mail (invites, notifications with user content) signs with a different selector or subdomain than corporate and transactional streams. A replay burns the segment, not the domain.
- 2
Constrain attacker-controlled content
Rate-limit and validate the product surfaces that let arbitrary users place text into signed mail; the replayed message has to come from somewhere.
- 3
Rotate keys on a schedule
Regular selector rotation bounds the lifetime of any captured signature. Quarterly is a sound baseline; immediate rotation is the containment move.
- 4
Weigh x= expiry for high-risk streams
A short signature expiry (hours) makes captured messages worthless quickly, at the cost of failing slow delivery paths and late forwards. Reserve it for streams where the replay risk outweighs that breakage.
- 5
Watch the disconnect metrics
Alert on complaint or reputation movement that lacks corresponding send volume, and on DMARC report sources passing DKIM from unknown infrastructure.
The hardening baseline
DKIM security audit
- Mutable display headers oversigned in every stream's h= tag
- No l= tag in any production signature
- 2048-bit keys, rotation scheduled and rehearsed
- User-influenced mail signed under a separate selector or subdomain from transactional and corporate streams
- Signup and notification surfaces rate-limited against replay-feed harvesting
- Monitoring alerts on reputation movement without matching send volume
Frequently asked questions
Does DMARC stop DKIM replay?
Is a small newsletter at risk of replay abuse?
Why not just set a very short x= expiry everywhere?
Does oversigning break anything?
Key takeaways
- Oversign mutable display headers so nothing can be appended to a signed message after the fact
- Remove any l= tag; partial body coverage is a demonstrated content-injection vector
- Replay is permitted by DKIM's design: one captured signed message can be re-sent at scale with the signature intact
- Segmented signing identities, constrained user-content surfaces, and rehearsed rotation bound the replay blast radius
- The tell for active replay is reputation damage without matching send volume, and the containment move is immediate selector rotation