From b676888242f537989e7d00cc26197c40d1137409 Mon Sep 17 00:00:00 2001 From: shankar0123 Date: Mon, 27 Apr 2026 03:03:57 +0000 Subject: [PATCH] =?UTF-8?q?M-029=20Pass=203=20batch=20A:=20T-1=20page=20te?= =?UTF-8?q?sts=20for=205=20simpler=20pages=20=E2=80=94=20XSS=20hardening?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass 3 of M-029 ships per-page render + XSS-hardening test suites for the 14 T-1-deferred pages. Each test: - Renders the page with mock data containing '; + +const xssEvent = { + id: 'ae-xss-001', + action: xssPayload, + actor: xssPayload, + actor_type: xssPayload, + resource_type: xssPayload, + resource_id: xssPayload, + details: { note: xssPayload }, + timestamp: new Date().toISOString(), +}; + +describe('AuditPage — render + XSS hardening (M-026 / M-029 Pass 3)', () => { + beforeEach(() => { + vi.clearAllMocks(); + cleanup(); + delete (window as unknown as { __xss_pwned__?: number }).__xss_pwned__; + }); + + it('renders the page header when audit events resolve', async () => { + vi.mocked(client.getAuditEvents).mockResolvedValue({ data: [], total: 0, page: 1, per_page: 50 } as never); + renderWithQuery(); + await waitFor(() => { + expect(screen.getByText(/Audit/)).toBeInTheDocument(); + }); + }); + + it('does NOT execute '; + vi.mocked(client.previewDigest).mockResolvedValue(xssPayload as never); + + renderWithQuery(); + await waitFor(() => { + // Wait for the preview surface to render (the page settles into + // either the preview pane or an error pane — either way the + // page-load cycle is done by the time the header text appears). + expect(screen.getByText('Certificate Digest')).toBeInTheDocument(); + }); + + // No live script with our marker may be attached to the DOM, AND no + // global side-effect from the script body may have run. + const liveScripts = document.querySelectorAll('script[data-xss="digest-preview"]'); + expect(liveScripts.length, 'previewDigest payload must not inject a live ` as the key. +// React's JSX text-interpolation escapes by default, so the payload should +// render as literal text with no script execution; this test pins that +// invariant against future refactors that might switch to +// dangerouslySetInnerHTML or v-html-style rendering. +// +// Pins: +// 1. The login form renders. +// 2. An auth error containing a literal '; +let mockError: string | null = null; + +vi.mock('../components/AuthProvider', () => ({ + useAuth: () => ({ + loading: false, + authRequired: true, + authenticated: false, + authType: 'api-key', + user: '', + admin: false, + login: vi.fn(), + logout: vi.fn(), + error: mockError, + }), +})); + +import LoginPage from './LoginPage'; + +function renderWithRouter(ui: ReactNode) { + return render({ui}); +} + +describe('LoginPage — render + XSS hardening (M-026 / M-029 Pass 3)', () => { + beforeEach(() => { + vi.clearAllMocks(); + cleanup(); + mockError = null; + delete (window as unknown as { __xss_pwned__?: number }).__xss_pwned__; + }); + + it('renders the login form', () => { + renderWithRouter(); + expect(screen.getByLabelText('API Key')).toBeInTheDocument(); + expect(screen.getByRole('button', { name: /Sign In/i })).toBeInTheDocument(); + }); + + it('does NOT execute a '; + +describe('ObservabilityPage — render + XSS hardening (M-026 / M-029 Pass 3)', () => { + beforeEach(() => { + vi.clearAllMocks(); + cleanup(); + delete (window as unknown as { __xss_pwned__?: number }).__xss_pwned__; + }); + + it('renders the page header when metrics + health resolve', async () => { + vi.mocked(client.getMetrics).mockResolvedValue({ + uptime: { uptime_seconds: 3600, server_started: new Date().toISOString() }, + } as never); + vi.mocked(client.getHealth).mockResolvedValue({ status: 'ok' } as never); + vi.mocked(client.getPrometheusMetrics).mockResolvedValue('# HELP up The current up state\nup 1\n' as never); + + renderWithQuery(); + await waitFor(() => { + expect(screen.getByText('Observability')).toBeInTheDocument(); + }); + }); + + it('does NOT execute '; + +const xssCert = { + id: 'mc-xss-001', + name: xssPayload, + common_name: xssPayload, + status: 'Active', + environment: xssPayload, + issuer_id: xssPayload, + certificate_profile_id: 'cp-shortlived', + expires_at: inOneHour, + created_at: new Date().toISOString(), +}; + +describe('ShortLivedPage — render + XSS hardening (M-026 / M-029 Pass 3)', () => { + beforeEach(() => { + vi.clearAllMocks(); + cleanup(); + delete (window as unknown as { __xss_pwned__?: number }).__xss_pwned__; + }); + + it('renders the page header when certs resolve', async () => { + vi.mocked(client.getCertificates).mockResolvedValue({ data: [], total: 0, page: 1, per_page: 50 } as never); + vi.mocked(client.getProfiles).mockResolvedValue({ data: [], total: 0, page: 1, per_page: 50 } as never); + renderWithQuery(); + await waitFor(() => { + expect(screen.getByText('Short-Lived Credentials')).toBeInTheDocument(); + }); + }); + + it('does NOT execute