From 8818535207c86074eba39e565321c6ec2ac74abf Mon Sep 17 00:00:00 2001 From: TurtleWolfe Date: Sun, 5 Jul 2026 04:34:58 +0000 Subject: [PATCH] fix(review): security hardening + dead-code cleanup from systematic review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Security: - send-payment-email (edge fn): replace the broken auth check `authHeader.includes(serviceRoleKey)` — a non-constant-time SUBSTRING match that, with an unset key, coerced to `includes("undefined")` and matched any header — with a guarded, exact, constant-time Bearer-token comparison. This closed an arbitrary-email-send bypass (phishing from the app domain). NOTE: this fn is deployed; needs redeploy via the Management API. - group-service.createGroup: validate every member_id is a well-formed UUID before it reaches getConnectedUserIds' PostgREST `.or(...)` interpolation (filter-injection guard), matching the validateUUID pattern used across connection-service / gdpr-service. Placed after the cheap structural checks so their specific errors still surface first. - SignInForm: remove the fail-OPEN try/catch around checkRateLimit. The wrapper is fail-CLOSED by design (returns allowed:false on infra outage to stop brute force); the catch silently defeated that on sign-in — the highest-value brute-force target — while SignUp/ForgotPassword already call it directly. XSS defense-in-depth: - markdown-processor: neutralize dangerous RAW HTML in blog prose ( world'); + expect(html).not.toContain(',
' + ); + expect(html).not.toMatch(/<(iframe|style|object|form)\b/i); + }); + + it('removes inline event-handler attributes', () => { + const { html } = process(' text'); + expect(html.toLowerCase()).not.toContain('onerror'); + expect(html).not.toContain('alert(1)'); + }); + + it('neutralizes javascript: URIs in raw href/src', () => { + const { html } = process('x'); + expect(html.toLowerCase()).not.toContain('javascript:'); + }); + + it('does NOT strip the benign structural tags the blog authors use', () => { + const md = + '
hi
\n
morebody
\nline
break'; + const { html } = process(md); + expect(html).toContain(''); + expect(html).toContain('
'); + expect(html).toContain(''); + expect(html).toContain(' sample', () => { + const { html } = process('```html\n\n```'); + // A