diff --git a/src/node/routes/errors.ts b/src/node/routes/errors.ts
index 757e9f7449d5e62df955bfd9cce12d4f446ac153..66f424ac27110dcdc1120f259353fdf8c58b27ef 100644
--- a/src/node/routes/errors.ts
+++ b/src/node/routes/errors.ts
@@ -6,7 +6,7 @@ import { WebsocketRequest } from "../../../typings/pluginapi"
import { HttpCode } from "../../common/http"
import { rootPath } from "../constants"
import { replaceTemplates } from "../http"
-import { getMediaMime } from "../util"
+import { escapeHtml, getMediaMime } from "../util"
const notFoundCodes = ["ENOENT", "EISDIR", "FileNotFound"]
export const errorHandler: express.ErrorRequestHandler = async (err, req, res, next) => {
@@ -29,7 +29,7 @@ export const errorHandler: express.ErrorRequestHandler = async (err, req, res, n
replaceTemplates(req, content)
.replace(/{{ERROR_TITLE}}/g, status)
.replace(/{{ERROR_HEADER}}/g, status)
- .replace(/{{ERROR_BODY}}/g, err.message),
+ .replace(/{{ERROR_BODY}}/g, escapeHtml(err.message)),
)
} else {
res.json({
diff --git a/test/unit/node/routes/errors.test.ts b/test/unit/node/routes/errors.test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ffa8f479111c53fedeedb8d3548c3a85775d5fb3
--- /dev/null
+++ b/test/unit/node/routes/errors.test.ts
@@ -0,0 +1,35 @@
+import express from "express"
+import { errorHandler } from "../../../../src/node/routes/errors"
+
+describe("error page is rendered for text/html requests", () => {
+ it("escapes any html in the error messages", async () => {
+ const next = jest.fn()
+ const err = {
+ code: "ENOENT",
+ statusCode: 404,
+ message: ";>hello",
+ }
+ const req = createRequest()
+ const res = {
+ status: jest.fn().mockReturnValue(this),
+ send: jest.fn().mockReturnValue(this),
+ set: jest.fn().mockReturnValue(this),
+ } as unknown as express.Response
+
+ await errorHandler(err, req, res, next)
+ expect(res.status).toHaveBeenCalledWith(404)
+ expect(res.send).toHaveBeenCalledWith(expect.not.stringContaining("