chore(security): validate Content-ID before use in MIME header / Graph payload #204

Closed
opened 2026-07-03 12:00:57 +00:00 by JMR-dev · 0 comments
JMR-dev commented 2026-07-03 12:00:57 +00:00 (Migrated from github.com)

Origin

Post-batch security review (2026-07-03), defense-in-depth. Not currently exploitable — contentId is always an app-generated img-<UUID>@libremail (ComposeViewModel.onImagePicked), so it cannot contain CR/LF today. This is insurance against a future change that lets a user- or external-value flow into contentId.

Problem

SmtpSender.inlinePart builds a MIME header as contentID = "<${attachment.contentId}>", and GraphSender puts contentId into the Graph JSON — neither validates for CR/LF or other control characters. If contentId ever became attacker-influenced, the SMTP path is a MIME header-injection vector.

Scope

  • Sanitize/validate contentId before it becomes a Content-ID header (SmtpSender) or a JSON field (GraphSender): strip or reject CR/LF and other ISO control characters. A single shared helper (or validation at the mint point in ComposeViewModel) is fine — pick the cleanest.
  • Unit tests: a contentId containing \r\n/control chars does not yield an injected header line (GreenMail assertion in SmtpSenderTest), and is sanitized in the Graph payload (GraphSenderTest).

Files

mail/SmtpSender.kt, mail/GraphSender.kt (and wherever contentId is minted, e.g. ComposeViewModel).

Notes

Defense-in-depth only — no behavior change for the app-generated IDs in use today. Origin: post-batch security review of PRs #194–#201.

## Origin Post-batch security review (2026-07-03), defense-in-depth. **Not currently exploitable** — `contentId` is always an app-generated `img-<UUID>@libremail` (`ComposeViewModel.onImagePicked`), so it cannot contain CR/LF today. This is insurance against a future change that lets a user- or external-value flow into `contentId`. ## Problem `SmtpSender.inlinePart` builds a MIME header as `contentID = "<${attachment.contentId}>"`, and `GraphSender` puts `contentId` into the Graph JSON — neither validates for CR/LF or other control characters. If `contentId` ever became attacker-influenced, the SMTP path is a MIME header-injection vector. ## Scope - Sanitize/validate `contentId` before it becomes a `Content-ID` header (`SmtpSender`) or a JSON field (`GraphSender`): strip or reject CR/LF and other ISO control characters. A single shared helper (or validation at the mint point in `ComposeViewModel`) is fine — pick the cleanest. - Unit tests: a `contentId` containing `\r\n`/control chars does not yield an injected header line (GreenMail assertion in `SmtpSenderTest`), and is sanitized in the Graph payload (`GraphSenderTest`). ## Files `mail/SmtpSender.kt`, `mail/GraphSender.kt` (and wherever `contentId` is minted, e.g. `ComposeViewModel`). ## Notes Defense-in-depth only — no behavior change for the app-generated IDs in use today. Origin: post-batch security review of PRs #194–#201.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: JMR-dev/LibreMail#204