๐ŸŽ“Iris Courses
โ† Cybersecurity for Founders
Day 6 of 7

Common Vulnerabilities โ€” The OWASP Top 10

Injection, XSS, and CSRF โ€” The Classic Trio

SQL injection: occurs when user input is concatenated directly into SQL queries. 'SELECT * FROM users WHERE email = ' + userInput โ€” if userInput is "' OR '1'='1", the query returns all users. Use parameterised queries (prepared statements) without exception. ORMs like Prisma and Drizzle do this by default. Supabase's client library uses parameterised queries automatically โ€” never concatenate user input into SQL. Cross-Site Scripting (XSS): occurs when user-supplied content is rendered as HTML without escaping. If a user submits '<script>alert(document.cookie)</script>' as their name, and your app renders that in HTML without escaping, it executes in the victim's browser โ€” stealing cookies or session tokens. Use React (which escapes HTML by default), avoid dangerouslySetInnerHTML without sanitisation, and validate HTML inputs with a library like DOMPurify. Cross-Site Request Forgery (CSRF): an attacker tricks a logged-in user's browser into making a request to your API. If your API uses cookies for authentication (common with Supabase), CSRF protection is needed. Modern browsers have SameSite cookie attributes that mitigate most CSRF attacks. Supabase's default cookie configuration includes SameSite=Lax, which provides CSRF protection for most scenarios. For high-sensitivity mutations, add a CSRF token to state-changing requests.

Broken Access Control and Security Misconfiguration

Broken access control is the #1 vulnerability in OWASP Top 10. It means users can access data or functions they're not authorised for. The most common form in SaaS: IDOR (Insecure Direct Object Reference) โ€” using a sequential or guessable ID in an API endpoint without verifying ownership. Example: GET /api/assessments/1234 returns assessment 1234. If your code fetches the assessment by ID without checking that the current user owns it, any authenticated user can access any assessment by guessing IDs. The fix: always join against the current user's context in every data query. With Supabase RLS: `WHERE id = $1 AND user_id = auth.uid()` โ€” the database enforces this, not application logic. Security misconfiguration: publicly accessible S3 buckets, open MongoDB instances, Supabase tables with RLS disabled, debug mode enabled in production, unnecessary open ports, default admin credentials. Automated scanners find these within hours of deployment. Checklist before every production deployment: (1) Is RLS enabled on every Supabase table? (2) Is debug mode off? (3) Are all environment variables using production values? (4) Are storage buckets private by default (signed URLs for access)? (5) Are admin endpoints protected?

โšก Today's Action

Check your Supabase project: are Row Level Security policies enabled on every table containing user data? If not, write and enable them today. This single action fixes the most common data access vulnerability in Supabase-backed applications.

๐Ÿ’ก Pro Tip

Run OWASP ZAP (free) against your staging environment quarterly. It's an automated scanner that tests for the most common vulnerabilities including SQL injection, XSS, and broken access control. It takes 30 minutes to run and reliably finds issues that code review misses.