Skip to content

Pentest 2026 07 14

mdeguzis edited this page Jul 14, 2026 · 3 revisions

Pentest: 2026-07-14

Initial comprehensive manual security audit of proton-pulse-web covering auth, RLS, XSS, edge functions, and the data pipeline.

Scope

  • All client-side JavaScript (app pages, shared libs, search, game pages)
  • Supabase Edge Functions (steam-callback, plugin-link, steam-appdetails, etc.)
  • Supabase RLS policies (all migration files)
  • Data pipeline Python scripts
  • GitHub Actions workflows

References used

Findings

# Severity Finding CWE/Standard Fix applied Issue
1 CRITICAL Weak password derivation (8 chars of service key + public Steam ID) CWE-916: Use of Password Hash With Insufficient Computational Effort HMAC-SHA256 with full key per OWASP Password Storage Cheat Sheet #291
2 HIGH No Content Security Policy CWE-1021: Improper Restriction of Rendered UI Layers CSP meta tag per OWASP CSP Cheat Sheet #292
3 HIGH No rate limiting on public edge function proxies CWE-770: Allocation of Resources Without Limits Per-IP rate limiting per OWASP Rate Limiting guidance #293
4 HIGH report_approvals RLS grants all authenticated users write access CWE-862: Missing Authorization Revoked grants, admin-only policy per OWASP Access Control Cheat Sheet #294
5 HIGH Delete operations use anon key instead of user session token CWE-306: Missing Authentication for Critical Function Bearer token from user session per OWASP AuthN Cheat Sheet #295
6 MEDIUM renderPermalink appId interpolation without JS-escaping CWE-79: Cross-site Scripting (XSS) Input escaped for JS string context per OWASP XSS Prevention Cheat Sheet #296
7 MEDIUM plugin-link-start no auth, no rate limiting CWE-307: Improper Restriction of Excessive Authentication Attempts 10 req/IP/min rate limit #297
8 MEDIUM markdown-it linkify missing rel="noopener noreferrer" CWE-1022: Use of Web Link to Untrusted Target with window.opener Access Added via renderer rule per MDN rel=noopener #298

Methodology

Audit covered:

  1. Auth flow trace from Steam OpenID through token issuance and session storage
  2. API key inventory (confirmed only anon/publishable keys in client code)
  3. XSS vector search across all innerHTML usage and template interpolation
  4. RLS policy review for every table in the migration history
  5. Edge function analysis for auth bypass, input validation, and rate limiting
  6. Privacy data inventory (what is stored, retention)
  7. CSP and security headers check
  8. Dependency audit (package.json, pip deps)
  9. Data pipeline input sanitization (subprocess calls, API response handling)

Positive findings (already in good shape)

  • HTML escaping via esc() function uses the DOM textContent/innerHTML pattern (OWASP XSS Rule #1)
  • No service role keys in client code (only anon key, per Supabase client-side auth docs)
  • Open redirect mitigated via origin validation (CWE-601 addressed)
  • PostgREST parameterized queries prevent SQL injection (CWE-89 not applicable)
  • subprocess.run uses list args, not shell=True (CWE-78 not applicable)
  • Session token stripped from URL hash immediately via history.replaceState (per OWASP Session Management Cheat Sheet)
  • markdown-it html:false blocks raw HTML injection in user notes

Remediation

All 8 findings were fixed in the same session as the audit (2026-07-14). Fixes are on the staging branch pending review and production deploy. The password derivation migration is backward-compatible: returning users are transparently migrated to the stronger HMAC on their next login.

Clone this wiki locally