From febddc2a8b06c718f12f5535e9fb9cbe1d1e5e71 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Thu, 2 May 2024 13:25:32 -1000 Subject: [PATCH] feat(api): :sparkles: Reimplement HTML sanitization --- bun.lockb | Bin 159140 -> 156556 bytes package.json | 213 +++++++++--------- .../v1/accounts/update_credentials/index.ts | 17 +- utils/sanitization.ts | 19 +- 4 files changed, 123 insertions(+), 126 deletions(-) diff --git a/bun.lockb b/bun.lockb index 77b8adebbd2cea107279f6791263359597182ab3..092c4f45656a0804667d4a1eb84f30183fefbc96 100755 GIT binary patch delta 25613 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 delta 27100 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 JaVSyR{$FV?WRm~@ diff --git a/package.json b/package.json index 73c9dee0..a6ee1677 100644 --- a/package.json +++ b/package.json @@ -1,109 +1,110 @@ { - "name": "lysand", - "module": "index.ts", - "type": "module", - "version": "0.5.0", - "description": "A project to build a federated social network", - "author": { - "email": "contact@cpluspatch.com", - "name": "CPlusPatch", - "url": "https://cpluspatch.com" - }, - "bugs": { - "url": "https://github.com/lysand-org/lysand/issues" - }, - "icon": "https://github.com/lysand-org/lysand", - "license": "AGPL-3.0", - "keywords": ["federated", "activitypub", "bun"], - "workspaces": ["packages/*"], - "maintainers": [ - { - "email": "contact@cpluspatch.com", - "name": "CPlusPatch", - "url": "https://cpluspatch.com" - } - ], - "repository": { - "type": "git", - "url": "git+https://github.com/lysand-org/lysand.git" - }, - "private": true, - "scripts": { - "dev": "bun run --watch index.ts", - "start": "NODE_ENV=production bun run dist/index.js --prod", - "lint": "bunx @biomejs/biome check .", - "prod-build": "bun run build.ts", - "benchmark:timeline": "bun run benchmarks/timelines.ts", - "cloc": "cloc . --exclude-dir node_modules,dist,.output,.nuxt,meta,logs,glitch,glitch-dev --exclude-ext sql,log,pem", - "cli": "bun run cli.ts" - }, - "trustedDependencies": [ - "@biomejs/biome", - "@fortawesome/fontawesome-common-types", - "@fortawesome/free-regular-svg-icons", - "@fortawesome/free-solid-svg-icons", - "es5-ext", - "esbuild", - "json-editor-vue", - "msgpackr-extract", - "nuxt-app", - "sharp", - "vue-demi" - ], - "devDependencies": { - "@biomejs/biome": "^1.7.0", - "@types/cli-table": "^0.3.4", - "@types/html-to-text": "^9.0.4", - "@types/ioredis": "^5.0.0", - "@types/jsonld": "^1.5.13", - "@types/markdown-it-container": "^2.0.10", - "@types/mime-types": "^2.1.4", - "@types/pg": "^8.11.5", - "bun-types": "latest", - "drizzle-kit": "^0.20.14", - "typescript": "latest" - }, - "peerDependencies": { - "typescript": "^5.3.2" - }, - "dependencies": { - "@hackmd/markdown-it-task-lists": "^2.1.4", - "@json2csv/plainjs": "^7.0.6", - "@shikijs/markdown-it": "^1.3.0", - "@tufjs/canonical-json": "^2.0.0", - "blurhash": "^2.0.5", - "bullmq": "^5.7.1", - "chalk": "^5.3.0", - "cli-parser": "workspace:*", - "cli-table": "^0.3.11", - "config-manager": "workspace:*", - "drizzle-orm": "^0.30.7", - "extract-zip": "^2.0.1", - "html-to-text": "^9.0.5", - "ioredis": "^5.3.2", - "ip-matching": "^2.1.2", - "iso-639-1": "^3.1.0", - "isomorphic-dompurify": "latest", - "jose": "^5.2.4", - "linkify-html": "^4.1.3", - "linkify-string": "^4.1.3", - "linkifyjs": "^4.1.3", - "log-manager": "workspace:*", - "magic-regexp": "^0.8.0", - "markdown-it": "^14.1.0", - "markdown-it-anchor": "^8.6.7", - "markdown-it-container": "^4.0.0", - "markdown-it-toc-done-right": "^4.2.0", - "media-manager": "workspace:*", - "megalodon": "^10.0.0", - "meilisearch": "^0.38.0", - "mime-types": "^2.1.35", - "oauth4webapi": "^2.4.0", - "pg": "^8.11.5", - "request-parser": "workspace:*", - "sharp": "^0.33.3", - "string-comparison": "^1.3.0", - "zod": "^3.22.4", - "zod-validation-error": "^3.2.0" + "name": "lysand", + "module": "index.ts", + "type": "module", + "version": "0.5.0", + "description": "A project to build a federated social network", + "author": { + "email": "contact@cpluspatch.com", + "name": "CPlusPatch", + "url": "https://cpluspatch.com" + }, + "bugs": { + "url": "https://github.com/lysand-org/lysand/issues" + }, + "icon": "https://github.com/lysand-org/lysand", + "license": "AGPL-3.0", + "keywords": ["federated", "activitypub", "bun"], + "workspaces": ["packages/*"], + "maintainers": [ + { + "email": "contact@cpluspatch.com", + "name": "CPlusPatch", + "url": "https://cpluspatch.com" } + ], + "repository": { + "type": "git", + "url": "git+https://github.com/lysand-org/lysand.git" + }, + "private": true, + "scripts": { + "dev": "bun run --watch index.ts", + "start": "NODE_ENV=production bun run dist/index.js --prod", + "lint": "bunx @biomejs/biome check .", + "prod-build": "bun run build.ts", + "benchmark:timeline": "bun run benchmarks/timelines.ts", + "cloc": "cloc . --exclude-dir node_modules,dist,.output,.nuxt,meta,logs,glitch,glitch-dev --exclude-ext sql,log,pem", + "cli": "bun run cli.ts" + }, + "trustedDependencies": [ + "@biomejs/biome", + "@fortawesome/fontawesome-common-types", + "@fortawesome/free-regular-svg-icons", + "@fortawesome/free-solid-svg-icons", + "es5-ext", + "esbuild", + "json-editor-vue", + "msgpackr-extract", + "nuxt-app", + "sharp", + "vue-demi" + ], + "devDependencies": { + "@biomejs/biome": "^1.7.0", + "@types/cli-table": "^0.3.4", + "@types/html-to-text": "^9.0.4", + "@types/ioredis": "^5.0.0", + "@types/jsonld": "^1.5.13", + "@types/markdown-it-container": "^2.0.10", + "@types/mime-types": "^2.1.4", + "@types/pg": "^8.11.5", + "bun-types": "latest", + "drizzle-kit": "^0.20.14", + "typescript": "latest" + }, + "peerDependencies": { + "typescript": "^5.3.2" + }, + "dependencies": { + "@hackmd/markdown-it-task-lists": "^2.1.4", + "@json2csv/plainjs": "^7.0.6", + "@shikijs/markdown-it": "^1.3.0", + "@tufjs/canonical-json": "^2.0.0", + "blurhash": "^2.0.5", + "bullmq": "^5.7.1", + "chalk": "^5.3.0", + "cli-parser": "workspace:*", + "cli-table": "^0.3.11", + "config-manager": "workspace:*", + "dompurify": "^3.1.2", + "drizzle-orm": "^0.30.7", + "extract-zip": "^2.0.1", + "happy-dom": "14.5.0", + "html-to-text": "^9.0.5", + "ioredis": "^5.3.2", + "ip-matching": "^2.1.2", + "iso-639-1": "^3.1.0", + "isomorphic-dompurify": "latest", + "jose": "^5.2.4", + "linkify-html": "^4.1.3", + "linkify-string": "^4.1.3", + "linkifyjs": "^4.1.3", + "log-manager": "workspace:*", + "magic-regexp": "^0.8.0", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^8.6.7", + "markdown-it-container": "^4.0.0", + "markdown-it-toc-done-right": "^4.2.0", + "media-manager": "workspace:*", + "meilisearch": "^0.38.0", + "mime-types": "^2.1.35", + "oauth4webapi": "^2.4.0", + "pg": "^8.11.5", + "request-parser": "workspace:*", + "sharp": "^0.33.3", + "string-comparison": "^1.3.0", + "zod": "^3.22.4", + "zod-validation-error": "^3.2.0" + } } diff --git a/server/api/api/v1/accounts/update_credentials/index.ts b/server/api/api/v1/accounts/update_credentials/index.ts index ee71140b..e0065908 100644 --- a/server/api/api/v1/accounts/update_credentials/index.ts +++ b/server/api/api/v1/accounts/update_credentials/index.ts @@ -97,19 +97,10 @@ export default apiRoute( const sanitizedNote = await sanitizeHtml(note ?? ""); - const sanitizedDisplayName = display_name ?? ""; /* sanitize(display_name ?? "", { - ALLOWED_TAGS: [], - ALLOWED_ATTR: [], - }); - */ - /* if (!user.source) { - user.source = { - privacy: "public", - sensitive: false, - language: "en", - note: "", - }; - } */ + const sanitizedDisplayName = await sanitizeHtml(display_name ?? "", { + ALLOWED_TAGS: [], + ALLOWED_ATTR: [], + }); let mediaManager: MediaBackend; diff --git a/utils/sanitization.ts b/utils/sanitization.ts index a1a57710..e4ad126c 100644 --- a/utils/sanitization.ts +++ b/utils/sanitization.ts @@ -1,10 +1,14 @@ import { config } from "config-manager"; -// import { sanitize } from "isomorphic-dompurify"; +import type DOMPurify from "dompurify"; +import createDomPurify from "dompurify"; +import { Window } from "happy-dom"; -export const sanitizeHtml = async (html: string) => { - // TEMP: Allow all tags and attributes - return html; - /* const sanitizedHtml = sanitize(html, { +const window = new Window(); +// @ts-expect-error Mismatch between types, but they're okay i swear +const purifier = createDomPurify(window); + +export const sanitizeHtml = async (html: string, extraConfig?: DOMPurify.Config) => { + const sanitizedHtml = purifier.sanitize(html, { ALLOWED_TAGS: [ "a", "p", @@ -40,7 +44,8 @@ export const sanitizeHtml = async (html: string) => { USE_PROFILES: { mathMl: true, }, - }); + ...extraConfig, + }) as string; // Check text to only allow h-*, p-*, u-*, dt-*, e-*, mention, hashtag, ellipsis, invisible classes const allowedClasses = [ @@ -72,5 +77,5 @@ export const sanitizeHtml = async (html: string) => { }, }) .transform(new Response(sanitizedHtml)) - .text(); */ + .text(); };