Thanks for taking the time to look at the security of CloudCertPrep.
Only the version currently deployed at cloudcertprep.io and the main branch of this repository are supported. Older branches and tags are not patched.
Please do not file a public GitHub issue for security problems.
Instead, email me directly:
- Contact: alex@cloudcertprep.io
- Subject prefix:
[security]
Include in the report:
- A description of the issue and the impact you believe it has.
- Step-by-step reproduction (URLs, payloads, account state).
- The affected component or page if you can identify it.
- Optionally, suggested mitigation.
- I will acknowledge your report within 5 working days.
- I will keep you informed about the fix progress.
- I will credit you in the release notes when the fix ships, unless you ask not to be named.
- I will let you know when you can publicly disclose the issue (usually after a fix is deployed).
- The production site
cloudcertprep.ioand any subdomains. - The contents of this GitHub repository, including the email templates, CI workflows, and database SQL surfaced in documentation.
- Authentication and session handling via Supabase.
- Cross-site scripting, SQL injection, privilege escalation, data exposure, or anything that could let one user read or modify another user's data.
- Social engineering of the maintainer.
- Denial-of-service attacks against the live site.
- Issues in third-party services (Supabase, Netlify, Brevo, Google Analytics, Umami) that are not specific to how CloudCertPrep configures them.
- Missing security headers that do not lead to a concrete exploit.
- Theoretical issues without a working proof-of-concept.
CloudCertPrep is a free, open-source side project with no revenue. I cannot pay for vulnerability reports. I will credit you publicly (with your permission) and thank you sincerely, but please do not expect financial compensation.
CloudCertPrep is a static SPA backed by Supabase Postgres:
- All Supabase tables that contain user data have Row Level Security (RLS) enabled with the policy
auth.uid() = user_id. - The Supabase anon key is intentionally public (inlined into the browser bundle). Security is enforced server-side via RLS, not by hiding the key.
- The service role key is never present in any client code, repository, or build output.
- Aggregate community statistics are exposed via a
SECURITY DEFINERRPC that returns only aggregates, never raw rows. - The
question_masteryview usesSECURITY INVOKERso that RLS on the underlying table is enforced when the view is queried.
Reports demonstrating that any of these assumptions are wrong are particularly welcome.