aboutsummaryrefslogtreecommitdiffstats
path: root/src/requestinterceptor.cpp
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-02 17:40:54 +0200
committerDanilo M. <danix@danix.xyz>2026-08-04 12:52:26 +0200
commit14843569125f7aeb4adaf547c323c8eb18961461 (patch)
treea5d336ae18eb37f9e01fe5b78ac59d905940cd14 /src/requestinterceptor.cpp
parentab4498ba12107529b8545f7d03dfe27433a3ffe2 (diff)
downloadqtmaildir-14843569125f7aeb4adaf547c323c8eb18961461.tar.gz
qtmaildir-14843569125f7aeb4adaf547c323c8eb18961461.zip
fix: scope qtmaildir: allow to the exact document base URL
Whole-scheme allow meant a hostile message body could reference any qtmaildir: URL (e.g. <img src="qtmaildir://other">) and have it pass, with safety depending entirely on Task 11's still-unwritten scheme handler. Add setDocumentUrl() and require an exact QUrl match; deny all qtmaildir: URLs when it is unset (fail closed). Document URL survives resetForNewMessage() since it is a property of the view, not of a message.
Diffstat (limited to 'src/requestinterceptor.cpp')
-rw-r--r--src/requestinterceptor.cpp20
1 files changed, 14 insertions, 6 deletions
diff --git a/src/requestinterceptor.cpp b/src/requestinterceptor.cpp
index 0ce95ca..8fd2419 100644
--- a/src/requestinterceptor.cpp
+++ b/src/requestinterceptor.cpp
@@ -15,12 +15,20 @@ bool RequestInterceptor::shouldAllow(const QUrl &url)
const QString scheme = url.scheme();
// The document itself is loaded via setHtml() with a qtmaildir: base URL,
- // so that scheme must pass or nothing renders at all. This is unconditional
- // on any path/host because Task 11's scheme handler is the only thing that
- // can ever originate a qtmaildir: navigation in the first place; the message
- // body cannot cause a request with this scheme, only reference cid:/http(s):.
- if (scheme == QLatin1String("qtmaildir"))
- return true;
+ // so a request for exactly that URL must pass or nothing renders at all.
+ // This is the ONLY trusted qtmaildir: URL: everything else on this scheme
+ // is denied, including sub-paths of it. A hostile message body can put
+ // arbitrary qtmaildir: URLs in <img src>, <link href>, etc., so this
+ // cannot be a whole-scheme allow; it must be an exact match against the
+ // one URL the application itself chose. If setDocumentUrl() was never
+ // called, m_documentUrl is a default-constructed (invalid, empty) QUrl,
+ // which cannot equal any real request URL, so this fails closed.
+ if (scheme == QLatin1String("qtmaildir")) {
+ if (!m_documentUrl.isEmpty() && url == m_documentUrl)
+ return true;
+ m_blockedAnything = true;
+ return false;
+ }
// Inline parts of the current message only.
if (scheme == QLatin1String("cid")) {