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.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Origin
Post-batch security review (2026-07-03), defense-in-depth. Not currently exploitable —
contentIdis always an app-generatedimg-<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 intocontentId.Problem
SmtpSender.inlinePartbuilds a MIME header ascontentID = "<${attachment.contentId}>", andGraphSenderputscontentIdinto the Graph JSON — neither validates for CR/LF or other control characters. IfcontentIdever became attacker-influenced, the SMTP path is a MIME header-injection vector.Scope
contentIdbefore it becomes aContent-IDheader (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 inComposeViewModel) is fine — pick the cleanest.contentIdcontaining\r\n/control chars does not yield an injected header line (GreenMail assertion inSmtpSenderTest), and is sanitized in the Graph payload (GraphSenderTest).Files
mail/SmtpSender.kt,mail/GraphSender.kt(and wherevercontentIdis 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.