Published: June 1, 2025
56
167
2.2k

I vibe coded and shipped an app in three days. It got hacked. Twice. Here’s what I learned. 🧵

The app is a directory that aggregates security research profiles across various platforms like @Hacker0x01 , @Bugcrowd , @github , and more. The frontend connects to a Supabase instance, and I built it using Lovable and Cursor. All automation that feeds data into the database is

Originally, I planned to allow users to self-register using Supabase Auth and submit the profiles they wanted aggregated. As I started implementing this, I realized it would introduce risk as I'd need to manage both authentication (who users are) and authorization (what they're

Bug #1: Leaking Emails: In my first test, users were authenticated via Supabase, which required real email addresses. While inspecting network requests, I discovered that responses from the profiles table were exposing user email addresses, which is obviously bad if users ever

To fix it, I created a PostgreSQL view that queried only the fields I needed from profiles, excluding email. I updated the frontend to query that view instead. Seemed more secure… but I accidentally made things worse. (More on that soon.)

Launch & First Compromise: After switching to the view and removing frontend insertion, I launched the app. I had Row-Level Security (RLS) enabled and thought read-only access meant I was safe.

Within 24 hours, a researcher showed they could insert, update, and delete records, even though the frontend didn’t expose those endpoints and RLS should have blocked it.

Why? The view I created didn’t respect RLS. By default, PostgreSQL views execute with the privileges of the view owner. In my case, this was an admin role. Unless you define the view as SECURITY INVOKER, or apply extra guards, RLS policies on underlying tables are bypassed. That

Second Compromise: A day later, another researcher (@Kr1shna4garwal) reached out: they were able to create new profiles in the database, though (thankfully) they couldn’t modify or delete existing ones.

This wasn’t due to the view. Instead, I had left Supabase Auth enabled, even though I had removed self-registration from the frontend. That meant attackers could still register via email/password and act as authenticated users, subject to whatever RLS rules existed. After

Key Takeaways: Vibe coding ships fast, but security holes are the default. Supabase + Postgres are powerful, but it’s easy to misconfigure them if you don’t understand their security model, especially around views and RLS. If you use PostgreSQL views, remember: they don’t

If you enjoyed this post, check out my newsletter: weekly bug bounty writeups, tools, and more: https://getdisclosed.com.

Share this thread

Read on Twitter

View original thread

Navigate thread

1/12