fix: rewrite local file iframe srcs to assets:// - #13194
Conversation
Prod Electron enables webSecurity, so Chromium blocks file:// iframe loads. Rewrite surviving file:// and graph-asset iframe srcs to the existing assets:// protocol after HTML sanitization. Co-authored-by: Tienson Qin <[email protected]>
Move normalize-asset-resource-url above the iframe rewrite so the compiler no longer warns about an undeclared var. Co-authored-by: Tienson Qin <[email protected]>
There was a problem hiding this comment.
🟡 Changes recommended
The current iframe-src rewrite logic can miss replacements for repeated identical src values, and the file://→assets:// rewrite should be constrained to the current graph’s assets directory to avoid enabling arbitrary local file embedding.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR fixes Desktop Logseq 2 production iframe embeds that reference local files by rewriting iframe[src] values from file:// (and graph-relative assets/... paths) to the existing privileged assets:// protocol after DOMPurify sanitization.
Changes:
- Post-process
security/sanitize-htmloutput to rewrite eligible iframesrcvalues toassets://on Electron. - Add new helpers in
frontend.handler.assetsto detect/convert local iframe sources and to rewrite matching HTML attributes. - Add unit/security tests covering
local-file-iframe-src->assets-url,rewrite-local-file-iframe-srcs, and the “rewrite happens after purify” ordering.
File summaries
| File | Description |
|---|---|
| src/main/frontend/handler/assets.cljs | Adds regex-based rewriting of iframe src values and a converter from local file/asset paths to assets://. |
| src/main/frontend/security.cljs | Applies the iframe rewrite step after DOMPurify sanitization. |
| src/test/frontend/handler/assets_test.cljs | Adds unit tests for the new iframe-src rewrite/conversion helpers. |
| src/test/frontend/security_test.cljs | Adds a test asserting the rewrite happens after DOMPurify returns. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 4
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| (defn local-file-iframe-src->assets-url | ||
| "Convert a local-file iframe src to assets:// on Electron. | ||
|
|
||
| Chromium blocks file:// subframe loads when webSecurity is on (prod | ||
| Desktop). The privileged assets:// protocol is the existing safe | ||
| substitute used for images. Only file:// and graph-relative asset | ||
| paths are rewritten; http(s) and other protocols stay unchanged." | ||
| [src] | ||
| (when (and (util/electron?) (string? src) (not (string/blank? src))) | ||
| (let [protocol (iframe-src-protocol src)] | ||
| (cond | ||
| (= "file:" protocol) | ||
| (when-let [fs-path (not-empty (path/file-url-or-path->path src))] | ||
| (normalize-asset-resource-url fs-path)) | ||
|
|
| (def ^:private iframe-src-attr-re | ||
| #"(?i)(<iframe\b[^>]*?\bsrc(?!doc)\s*=\s*)(\"[^\"]*\"|'[^']*'|[^\s>]+)") |
| (defn rewrite-local-file-iframe-srcs | ||
| "Rewrite file:// and graph-asset iframe srcs to assets:// on Electron. | ||
|
|
||
| Only iframe src attributes are rewritten so http(s) embeds and other | ||
| tags keep their original URLs. No-op outside Electron." | ||
| [html] | ||
| (if-not (and (util/electron?) (string? html) (seq html)) | ||
| html | ||
| (reduce (fn [acc [_ prefix quoted-src]] | ||
| (let [src (unwrap-quoted-attr quoted-src) | ||
| rewritten (or (local-file-iframe-src->assets-url src) src) | ||
| from (str prefix quoted-src) | ||
| to (str prefix (wrap-quoted-attr quoted-src rewritten)) | ||
| idx (when (not= from to) | ||
| (string/index-of acc from))] | ||
| (if idx | ||
| (str (subs acc 0 idx) to (subs acc (+ idx (count from)))) | ||
| acc))) | ||
| html | ||
| (re-seq iframe-src-attr-re html)))) |
| (deftest local-file-iframe-src->assets-url-electron-windows-test | ||
| (with-redefs [util/electron? (constantly true)] | ||
| (is (= "assets:///C/logseq__colon/dev/work/notes/assets/foo.html" | ||
| (assets/local-file-iframe-src->assets-url | ||
| "file:///C:/dev/work/notes/assets/foo.html"))))) |
Fixes logseq/db-test#1166 (transferred from https://github.com/logseq/logseq/issues/13192).
Problem
Raw HTML iframes with a
file://src render blank on Desktop Logseq 2 prod. Chromium reportsNot allowed to load local resourcebecause prod Electron enableswebSecurity. The same markup works in Logseq OG, andhttp(s)/ localhost srcs still work in Logseq 2.Change
After DOMPurify sanitization, rewrite iframe
srcvalues that are local files to the existing privilegedassets://protocol:file://URLs becomeassets://(including Windows drive protection)assets/foo.html,./assets/foo.html) resolve toassets://http(s)and other non-file protocols are left unchangedwebSecuritystays enabledTests
local-file-iframe-src->assets-urlandrewrite-local-file-iframe-srcs, including the reported Windowsfile:///C:/...iframesanitize-htmlapplies the rewrite after purify