diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-02 17:41:39 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-04 12:52:28 +0200 |
| commit | 5690c50ff9a6ef4555c2c4ccd9a7dbd7dc172c7a (patch) | |
| tree | 90da159f0ae913ee8f6d1a12ddc0d70faa31183b /docs/superpowers/specs/2026-08-02-qtmaildir-design.md | |
| parent | 14843569125f7aeb4adaf547c323c8eb18961461 (diff) | |
| download | qtmaildir-5690c50ff9a6ef4555c2c4ccd9a7dbd7dc172c7a.tar.gz qtmaildir-5690c50ff9a6ef4555c2c4ccd9a7dbd7dc172c7a.zip | |
docs: scope the document-load exemption to an exact URL
The interceptor previously trusted the whole qtmaildir: scheme, so a
hostile message body referencing qtmaildir://anything would have been
allowed. That made the interceptor's correctness depend on the scheme
handler in a different, later task.
It now trusts only the exact base URL passed to setHtml() and fails
closed when none is set. Records the resulting obligation on MessageView
to call setDocumentUrl() with that same URL.
Also corrects the attachment path guard to a separator-aware comparison
and notes that it is unreachable defence-in-depth: safeFilename() runs
first, so no caller-supplied name can reach it. A test driving saveTo()
expecting refusal cannot pass; test safeFilename() instead.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'docs/superpowers/specs/2026-08-02-qtmaildir-design.md')
| -rw-r--r-- | docs/superpowers/specs/2026-08-02-qtmaildir-design.md | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/docs/superpowers/specs/2026-08-02-qtmaildir-design.md b/docs/superpowers/specs/2026-08-02-qtmaildir-design.md index 1edc75f..0f49b61 100644 --- a/docs/superpowers/specs/2026-08-02-qtmaildir-design.md +++ b/docs/superpowers/specs/2026-08-02-qtmaildir-design.md @@ -312,6 +312,15 @@ pointed at input from strangers. from the current message's own parts are permitted. Remote images, CSS, and fonts are blocked before a connection opens, which defeats tracking pixels and read receipts. + + The document-load exemption is scoped to the **exact** base URL passed to + `setHtml()`, not to the whole `qtmaildir:` scheme. A blanket + scheme-level allow would let a hostile body reference + `qtmaildir://anything` and have it trusted, making the interceptor's + correctness depend on the scheme handler's. The interceptor fails closed: + with no document URL set, every `qtmaildir:` URL is denied. `MessageView` + must therefore call `setDocumentUrl()` with the same URL it gives + `setHtml()`. - When anything was blocked, the header bar shows "Remote content blocked" with a **Load remote content** button. Clicking it re-renders that one message with remote loads permitted. The grant is never sticky and never |
