mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-09-05 07:27:27 +08:00
feat: add setting to disable auto-loading external images in emails (#1092)
* feat: add setting to disable auto-loading external images in emails Adds a privacy setting (default off) that blocks remote images in email content until the user explicitly loads them per message. Blocked images are replaced with a placeholder; a banner allows one-click loading. Closes #1073 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(frontend): block remote content with DOMPurify and an allowlist policy Address review on the blocking logic. The first pass matched quoted `<img src="http...">` with a regex, which left unquoted src, srcset, `<source>`, CSS background-image, SVG `<image href>` and entity-encoded schemes fetching as usual, and replaced only `src` on an element that also carried `srcset` -- so the browser still had a remote candidate to prefer while the UI claimed the image was blocked. Two changes rather than a wider regex: Sanitising is delegated to DOMPurify, which is already a dependency. The hard part here is not enumerating attributes but surviving the parser: a hand-written pass over a DOMParser tree still missed that `<noscript>` is parsed as markup where scripting is off and as raw text where it is on, so a `</noscript>` smuggled into an attribute value reopens the document at render time and revives an `<img>` the cleaner never saw. Elements that fetch by themselves or change how relative URLs resolve -- base, meta, script, link, iframe, object, embed, noscript -- are dropped in this mode. `<style>` is kept so layout survives, with its url(), image-set() and @import references filtered. URL classification is an allowlist. Asking "does this look remote?" means enumerating every disguise -- backslash authorities, tab/newline/control characters the URL parser strips, CSS escapes, schemes with no slashes -- and losing to the first one not thought of. Asking "can I prove this is local?" fails closed instead: cid:, data:image/, blob: and relative paths are kept, everything else is blocked. Relative paths are only safe because `<base>` is removed, which is what stopped it re-pointing them at a tracker. The blocked URL is discarded rather than parked in a data-* attribute, so "the cleaned body contains no remote URL at all" is directly assertable; restoring images re-renders from the untouched source. Also: blob: is added to the allowed schemes -- DOMPurify's default list omits it, and email-parser rewrites cid: attachments into blob: URLs, so without it every inline image would be stripped along with the trackers. The policy lives in its own module with its own tests (30 attack vectors, 7 preservation cases); email-parser.js goes back to MIME parsing only. The per-mail override no longer initialises from the global setting, and the banner reports the blocked count as the PR description promised. Refs #1073 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
342fe22e4f
commit
e499211197
@@ -12,6 +12,7 @@
|
||||
|
||||
- feat: |Frontend| 邮箱新增「邮箱全宽列表视图」开关(在外观设置中控制),开启后默认全宽列表展示邮件标题与正文预览,点击单封邮件再展开为双栏,再次点击同一封邮件可回到列表视图;多选模式下点击邮件会同步切换勾选状态与右侧预览,并禁用同邮件点击收回列表,展开时双栏左侧列表宽度仍遵循「邮箱双栏视图左侧列表宽度占比」配置;默认关闭,保留原有双栏行为
|
||||
- feat: |Frontend| 邮箱全宽列表视图新增「正文预览行数」配置(在外观设置中控制),可设置邮件正文预览的最大行数,默认 2 行,0 表示关闭预览
|
||||
- feat: |Frontend| 外观设置新增「自动加载邮件正文中的外部图片」开关,关闭后邮件预览(含全屏视图)会先经 DOMPurify 消毒,并以白名单策略处理所有可能发起请求的位置:仅保留可证明为本地的引用(`cid:`、`data:image/`、`blob:` 与站内相对路径),其余一律阻断;`base`、`meta`、`script`、`link`、`iframe`、`object`、`embed`、`noscript` 等会自行取用资源或改变解析基准的元素在此模式下移除,`<style>` 保留但其中 `url()`、`image-set()`、`@import` 的远端引用会被替换。正文上方显示已阻断资源数量的提示条,可一键按封加载;默认保持开启,行为与此前一致(issue #1073)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user