diff --git a/tests/worker/dsar.test.ts b/tests/worker/dsar.test.ts index cf0fbce..35bc83e 100644 --- a/tests/worker/dsar.test.ts +++ b/tests/worker/dsar.test.ts @@ -71,4 +71,43 @@ describe("dsar", () => { assert.deepEqual(emailPayload?.to, ["contact@oyme.site"]); assert.match(String(emailPayload?.subject), /DSAR delete request/); }); + + it("escapes user-controlled HTML in the staff email body", async (t) => { + const { env, db } = createTestEnv(); + const user = seedUser(db, { username: "DsarUser", email: "u@example.com" }); + seedSession(db, user.id, "dsar-token"); + + let emailPayload: Record | null = null; + const originalFetch = globalThis.fetch; + globalThis.fetch = async (_input, init) => { + if (init?.body && typeof init.body === "string") { + emailPayload = JSON.parse(init.body) as Record; + } + return { ok: true, json: async () => ({ id: "email_123" }) } as Response; + }; + t.after(() => { + globalThis.fetch = originalFetch; + }); + + const { res, json } = await jsonRequest(env, "/api/dsar", { + method: "POST", + headers: { "x-session-token": "dsar-token" }, + body: { + requestType: "access", + jurisdiction: "", + details: "", + }, + }); + + assert.equal(res.status, 200); + assert.equal(json.success, true); + assert.ok(emailPayload); + const html = String(emailPayload?.html); + // Escaped forms are present. + assert.ok(html.includes("<script>alert(1)</script>")); + assert.ok(html.includes("<img src=x onerror=alert(1)>")); + // Raw markup is not. + assert.ok(!html.includes("