From 7f6b7c221560d979496ba919f429921ad617aa1d Mon Sep 17 00:00:00 2001 From: DarkCat09 Date: Mon, 25 Sep 2023 12:04:22 +0400 Subject: [PATCH 1/2] Security bugfix: HTML sanitizing --- package-lock.json | 22 ++++++++++++++++++++++ package.json | 2 ++ src/handlers/main.ts | 7 +++++-- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 438771e..073e370 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@fastify/view": "^8.0.0", "@mozilla/readability": "^0.4.4", "axios": "^1.4.0", + "dompurify": "^3.0.5", "dotenv": "^16.3.1", "ejs": "^3.1.9", "fastify": "^4.21.0", @@ -25,6 +26,7 @@ "micromatch": "^4.0.5" }, "devDependencies": { + "@types/dompurify": "^3.0.3", "@types/ejs": "^3.1.2", "@types/express": "^4.17.17", "@types/jsdom": "^21.1.1", @@ -373,6 +375,15 @@ "@types/node": "*" } }, + "node_modules/@types/dompurify": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.3.tgz", + "integrity": "sha512-odiGr/9/qMqjcBOe5UhcNLOFHSYmKFOyr+bJ/Xu3Qp4k1pNPAlNLUVNNLcLfjQI7+W7ObX58EdD3H+3p3voOvA==", + "dev": true, + "dependencies": { + "@types/trusted-types": "*" + } + }, "node_modules/@types/ejs": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.2.tgz", @@ -489,6 +500,12 @@ "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", "dev": true }, + "node_modules/@types/trusted-types": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.4.tgz", + "integrity": "sha512-IDaobHimLQhjwsQ/NMwRVfa/yL7L/wriQPMhw1ZJall0KX6E1oxk29XMDeilW5qTIg5aoiqf5Udy8U/51aNoQQ==", + "dev": true + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.3.0.tgz", @@ -1260,6 +1277,11 @@ "node": ">=12" } }, + "node_modules/dompurify": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.5.tgz", + "integrity": "sha512-F9e6wPGtY+8KNMRAVfxeCOHU0/NPWMSENNq4pQctuXRqqdEPW7q3CrLbR5Nse044WwacyjHGOMlvNsBe1y6z9A==" + }, "node_modules/dotenv": { "version": "16.3.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", diff --git a/package.json b/package.json index a8d673f..9902509 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "@fastify/view": "^8.0.0", "@mozilla/readability": "^0.4.4", "axios": "^1.4.0", + "dompurify": "^3.0.5", "dotenv": "^16.3.1", "ejs": "^3.1.9", "fastify": "^4.21.0", @@ -21,6 +22,7 @@ "micromatch": "^4.0.5" }, "devDependencies": { + "@types/dompurify": "^3.0.3", "@types/ejs": "^3.1.2", "@types/express": "^4.17.17", "@types/jsdom": "^21.1.1", diff --git a/src/handlers/main.ts b/src/handlers/main.ts index 45e5e2f..1cedb56 100644 --- a/src/handlers/main.ts +++ b/src/handlers/main.ts @@ -17,6 +17,7 @@ import { HandlerInput } from "./handler-input"; import { Readable } from "stream"; import { decodeStream, parseEncodingName } from "../utils/http"; import replaceHref from "../utils/replace-href"; +import DOMPurify from "dompurify"; export default async function handlePage( url: string, // remote URL @@ -47,10 +48,12 @@ export default async function handlePage( ); // post-process + const dom = new JSDOM(output.content, { url }); replaceHref(dom, requestUrl, engine, redirectPath); - output.content = dom.serialize(); - // TODO: DomPurify + + const purify = DOMPurify(dom.window); + output.content = purify.sanitize(dom.serialize()); return output; } From b31bbc547eb88359779d1ef4adfc54f9f806a46f Mon Sep 17 00:00:00 2001 From: DarkCat09 Date: Mon, 25 Sep 2023 12:06:50 +0400 Subject: [PATCH 2/2] Rearranged imports --- src/handlers/main.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/handlers/main.ts b/src/handlers/main.ts index 1cedb56..01c79f7 100644 --- a/src/handlers/main.ts +++ b/src/handlers/main.ts @@ -5,6 +5,9 @@ import axios from "../types/axios"; import micromatch from "micromatch"; import { JSDOM } from "jsdom"; +import DOMPurify from "dompurify"; + +import { Readable } from "stream"; import readability from "./readability"; import google, { GoogleDomains } from "./google"; @@ -14,10 +17,8 @@ import isLocalResource from "../utils/islocal"; import { LocalResourceError, NotHtmlMimetypeError } from "../errors/main"; import { HandlerInput } from "./handler-input"; -import { Readable } from "stream"; import { decodeStream, parseEncodingName } from "../utils/http"; import replaceHref from "../utils/replace-href"; -import DOMPurify from "dompurify"; export default async function handlePage( url: string, // remote URL