Merge pull request #63 from TxtDot/dompurify

Security bugfix: HTML sanitizing
This commit is contained in:
Artemy Egorov 2023-09-25 11:07:12 +03:00 committed by GitHub
commit edf8a4ffdd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 3 deletions

22
package-lock.json generated
View File

@ -15,6 +15,7 @@
"@fastify/view": "^8.0.0", "@fastify/view": "^8.0.0",
"@mozilla/readability": "^0.4.4", "@mozilla/readability": "^0.4.4",
"axios": "^1.4.0", "axios": "^1.4.0",
"dompurify": "^3.0.5",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
"ejs": "^3.1.9", "ejs": "^3.1.9",
"fastify": "^4.21.0", "fastify": "^4.21.0",
@ -25,6 +26,7 @@
"micromatch": "^4.0.5" "micromatch": "^4.0.5"
}, },
"devDependencies": { "devDependencies": {
"@types/dompurify": "^3.0.3",
"@types/ejs": "^3.1.2", "@types/ejs": "^3.1.2",
"@types/express": "^4.17.17", "@types/express": "^4.17.17",
"@types/jsdom": "^21.1.1", "@types/jsdom": "^21.1.1",
@ -373,6 +375,15 @@
"@types/node": "*" "@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": { "node_modules/@types/ejs": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.2.tgz", "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.2.tgz",
@ -489,6 +500,12 @@
"integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==",
"dev": true "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": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "6.3.0", "version": "6.3.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.3.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.3.0.tgz",
@ -1260,6 +1277,11 @@
"node": ">=12" "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": { "node_modules/dotenv": {
"version": "16.3.1", "version": "16.3.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",

View File

@ -11,6 +11,7 @@
"@fastify/view": "^8.0.0", "@fastify/view": "^8.0.0",
"@mozilla/readability": "^0.4.4", "@mozilla/readability": "^0.4.4",
"axios": "^1.4.0", "axios": "^1.4.0",
"dompurify": "^3.0.5",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
"ejs": "^3.1.9", "ejs": "^3.1.9",
"fastify": "^4.21.0", "fastify": "^4.21.0",
@ -21,6 +22,7 @@
"micromatch": "^4.0.5" "micromatch": "^4.0.5"
}, },
"devDependencies": { "devDependencies": {
"@types/dompurify": "^3.0.3",
"@types/ejs": "^3.1.2", "@types/ejs": "^3.1.2",
"@types/express": "^4.17.17", "@types/express": "^4.17.17",
"@types/jsdom": "^21.1.1", "@types/jsdom": "^21.1.1",

View File

@ -5,6 +5,9 @@ import axios from "../types/axios";
import micromatch from "micromatch"; import micromatch from "micromatch";
import { JSDOM } from "jsdom"; import { JSDOM } from "jsdom";
import DOMPurify from "dompurify";
import { Readable } from "stream";
import readability from "./readability"; import readability from "./readability";
import google, { GoogleDomains } from "./google"; import google, { GoogleDomains } from "./google";
@ -14,7 +17,6 @@ import isLocalResource from "../utils/islocal";
import { LocalResourceError, NotHtmlMimetypeError } from "../errors/main"; import { LocalResourceError, NotHtmlMimetypeError } from "../errors/main";
import { HandlerInput } from "./handler-input"; import { HandlerInput } from "./handler-input";
import { Readable } from "stream";
import { decodeStream, parseEncodingName } from "../utils/http"; import { decodeStream, parseEncodingName } from "../utils/http";
import replaceHref from "../utils/replace-href"; import replaceHref from "../utils/replace-href";
@ -47,10 +49,12 @@ export default async function handlePage(
); );
// post-process // post-process
const dom = new JSDOM(output.content, { url }); const dom = new JSDOM(output.content, { url });
replaceHref(dom, requestUrl, engine, redirectPath); replaceHref(dom, requestUrl, engine, redirectPath);
output.content = dom.serialize();
// TODO: DomPurify const purify = DOMPurify(dom.window);
output.content = purify.sanitize(dom.serialize());
return output; return output;
} }