import { chromium, test, expect, BrowserContext } from "@playwright/test"; import { fileURLToPath } from "url"; import { dirname, join } from "path"; import os from "os"; import fs from "fs/promises"; import { EXTENSION_PATH, UNLOCKED, createEntryViaForm, lockVault, makeContext, listSearch, openList, openSettings, setupVault, waitForSW, } from "./helpers/vault"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); // Real vault creation runs Argon2id (≈12s with the recovery confirmation). test.describe.configure({ timeout: 90_000 }); /** The generator drawer lives inside the new-entry form. */ async function openGenerator(popup: import("@playwright/test").Page) { await openList(popup); await popup.locator(".peach-new-entry-row").click(); await popup.locator(".peach-generate-toggle-link").click(); await expect(popup.locator(".peach-pwgen-compact-output")).toBeVisible({ timeout: 5000 }); } test.describe("XSS Prevention", () => { let ctx: BrowserContext; test.afterEach(async () => { await ctx.close(); }); test.beforeEach(async () => { ctx = await makeContext(); }); test("SECX01 - entry titles are escaped in DOM", async () => { const { popup } = await setupVault(ctx); await createEntryViaForm(popup, { title: '', url: "https://xss.com", username: "xss@user.com", password: "xss" }); // The old assertion demanded the title NOT contain "'); await popup.waitForTimeout(300); // An input legitimately holds whatever was typed; what must not happen is // the query becoming markup somewhere in the list. expect(await searchInput.inputValue()).toContain("