diff --git a/package-lock.json b/package-lock.json index ce438c4..9be1285 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,19 @@ { "name": "markpad", - "version": "2.3.5", + "version": "2.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "markpad", - "version": "2.3.5", + "version": "2.4.0", "license": "MIT", "dependencies": { "@tauri-apps/api": "^2", "@tauri-apps/plugin-dialog": "^2.5.0", "@tauri-apps/plugin-opener": "^2", + "@types/dompurify": "^3.0.5", + "dompurify": "^3.3.1", "highlight.js": "^11.11.1", "katex": "^0.16.27", "monaco-editor": "^0.55.1" @@ -909,7 +911,6 @@ "integrity": "sha512-JFtOqDoU0DI/+QSG8qnq5bKcehVb3tCHhOG4amsSYth5/KgO4EkJvi42xSAiyKmXAAULW1/Zdb6lkgGEgSxdZg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", @@ -953,7 +954,6 @@ "integrity": "sha512-Y1Cs7hhTc+a5E9Va/xwKlAJoariQyHY+5zBgCZg4PFWNYQ1nMN9sjK1zhw1gK69DuqVP++sht/1GZg1aRwmAXQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^4.0.1", "debug": "^4.4.1", @@ -1240,6 +1240,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/dompurify": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz", + "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==", + "license": "MIT", + "dependencies": { + "@types/trusted-types": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -1251,8 +1260,7 @@ "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/acorn": { "version": "8.15.0", @@ -1260,7 +1268,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1369,9 +1376,9 @@ "license": "MIT" }, "node_modules/dompurify": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", - "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", + "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -1553,6 +1560,15 @@ "marked": "14.0.0" } }, + "node_modules/monaco-editor/node_modules/dompurify": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", + "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -1612,7 +1628,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -1759,7 +1774,6 @@ "integrity": "sha512-Y5juST3x+/ySty5tYJCVWa6Corkxpt25bUZQHqOceg9xfMUtDsFx6rCsG6cYf1cA6vzDi66HIvaki0byZZX95A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", @@ -1838,7 +1852,6 @@ "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -1853,7 +1866,6 @@ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", diff --git a/package.json b/package.json index d45e003..96f43ff 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,8 @@ "@tauri-apps/api": "^2", "@tauri-apps/plugin-dialog": "^2.5.0", "@tauri-apps/plugin-opener": "^2", + "@types/dompurify": "^3.0.5", + "dompurify": "^3.3.1", "highlight.js": "^11.11.1", "katex": "^0.16.27", "monaco-editor": "^0.55.1" diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 00c38fc..ba5a260 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -36,7 +36,7 @@ fn convert_markdown(content: &str) -> String { }, ..ComrakOptions::default() }; - options.render.unsafe_ = true; + options.render.unsafe_ = false; options.render.hardbreaks = true; options.render.sourcepos = true; diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 464e5d1..c9c5523 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -12,7 +12,7 @@ "app": { "windows": [], "security": { - "csp": null, + "csp": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' asset: https: data:; connect-src 'self'; frame-src https://www.youtube.com https://www.youtube-nocookie.com; font-src 'self' https://fonts.gstatic.com", "assetProtocol": { "enable": true, "scope": ["**"] diff --git a/src/lib/MarkdownViewer.svelte b/src/lib/MarkdownViewer.svelte index aa4c76e..ba0f409 100644 --- a/src/lib/MarkdownViewer.svelte +++ b/src/lib/MarkdownViewer.svelte @@ -11,6 +11,7 @@ import Editor from './components/Editor.svelte'; import Modal from './components/Modal.svelte'; + import DOMPurify from 'dompurify'; import HomePage from './components/HomePage.svelte'; import { tabManager } from './stores/tabs.svelte.js'; @@ -41,6 +42,7 @@ let currentFile = $derived(tabManager.activeTab?.path ?? ''); let editorLanguage = $derived(getLanguage(currentFile)); let htmlContent = $derived(tabManager.activeTab?.content ?? ''); + let sanitizedHtml = $derived(DOMPurify.sanitize(htmlContent)); let scrollTop = $derived(tabManager.activeTab?.scrollTop ?? 0); let isScrolled = $derived(scrollTop > 0); let windowTitle = $derived(tabManager.activeTab?.title ?? 'Markpad');