Skip to content

fix(be): tolerate gateway leaving line terminator on DKIM header values#3939

Merged
aterga merged 2 commits into
mainfrom
sea-snake/dkim-strip-trailing-crlf
May 22, 2026
Merged

fix(be): tolerate gateway leaving line terminator on DKIM header values#3939
aterga merged 2 commits into
mainfrom
sea-snake/dkim-strip-trailing-crlf

Conversation

@sea-snake
Copy link
Copy Markdown
Contributor

DKIM signature verification on beta currently fails every well-formed inbound message with SignatureInvalid. We caught this via the new email_recovery_logs query (#3934) — two separate users tried to bind recovery emails over the DoH/gmail path and both hit identical doh verify_failed err=EmailVerificationFailed("SignatureInvalid") log lines. Inspecting a captured SmtpRequest showed every header value arriving with its terminating CRLF attached (e.g. Subject as " II-Recovery-…\r\n").

Per RFC 5322 §2.2 the CRLF that ends a header line is structural framing, not field-body. The gateway should be stripping it during parsing. Today's beta gateway leaves it attached, which makes our DKIM hash input end with …\r\n\r\n instead of …\r\nrelaxed_header_value adds its own line terminator on top of the value's leftover one — so SHA-256(hash_input) never matches what Gmail signed.

This is a defensive workaround on the canister side until the gateway is fixed: relaxed_header_value now strips any trailing \r/\n from the input value before running the rest of the relaxed canonicalization pipeline. The trim is intentionally narrow — it pops only structural CR/LF, not whitespace inside the value — so is_wsp stays at the RFC 6376 §2.8 SP/HTAB definition. Marked FIXME(gateway) with a pointer to the right long-term fix.

Changes

  • dkim/canonicalize.rs: strip trailing \r\n (and bare \r/\n) from header values before relaxed canonicalization. Comment marks it as a temporary tolerance for the gateway parser bug.

Tests

  • relaxed_header_strips_trailing_line_terminator — value ending in \r\n no longer produces a double-CRLF canonical form.
  • relaxed_header_strips_trailing_terminator_with_wsp — value ending in SP HTAB \r\n is fully cleaned.
  • relaxed_header_strips_bare_trailing_lf — bare trailing \n (no \r) is also tolerated.
  • relaxed_header_folded_value_with_trailing_terminator — Gmail-shaped folded DKIM-Signature value still unfolds correctly even with a trailing terminator.

All 108 existing dkim::* unit tests continue to pass.

The beta SMTP gateway hands the canister header values with the
structural CRLF still attached (e.g. `Subject` arrives as
" II-Recovery-…\r\n"). Per RFC 5322 §2.2 the CRLF that terminates
a header line is framing, not field-body — the gateway should be
stripping it during parsing. Today every DKIM signature lands as
SignatureInvalid because our hash input ends with `…\r\n\r\n`
instead of `…\r\n`.

Defensively strip a trailing line terminator in `relaxed_header_value`
so DKIM verification works against the current gateway. Marked
FIXME(gateway) — once the gateway parser is fixed to strip the CRLF
on its side this workaround can be removed and `is_wsp` left at its
strict RFC 6376 §2.8 SP/HTAB definition.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 22, 2026 14:55
@sea-snake sea-snake requested a review from a team as a code owner May 22, 2026 14:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a defensive workaround in the DKIM relaxed header canonicalization to tolerate an SMTP gateway bug where header values incorrectly include their trailing line terminator (\r\n / \r / \n), which currently causes DKIM verification to fail with SignatureInvalid.

Changes:

  • Strip trailing \r/\n from header values before applying relaxed canonicalization steps.
  • Add unit tests covering trailing terminator stripping (including with trailing WSP, bare \n, and folded values).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/internet_identity/src/dkim/canonicalize.rs
@zeropath-ai
Copy link
Copy Markdown

zeropath-ai Bot commented May 22, 2026

No security or compliance issues detected. Reviewed everything up to 2d67428.

Security Overview
Detected Code Changes

| Change Type | Relevant files

... (code changes summary truncated to fit VCS comment limits.)

@aterga aterga enabled auto-merge (squash) May 22, 2026 15:20
@aterga aterga merged commit a6f0437 into main May 22, 2026
47 checks passed
@aterga aterga deleted the sea-snake/dkim-strip-trailing-crlf branch May 22, 2026 15:26
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.

3 participants