I keep hearing some version of the same line from people building apps with Bolt, Lovable, Cursor, or whatever tool they picked up this month: "it's fine, I'm using Supabase" or "Firebase handles the security side." I get why people think that. Both products come from real infrastructure companies, both have dashboards that look serious, both feel like grown-up tools. But neither one secures your data by default. They hand you the tools to secure it. Whether anyone actually uses those tools is a separate question, and it's an easy one to skip when an AI tool wrote most of your backend in an afternoon.
What these tools actually are
Strip away the branding and Supabase and Firebase are the same basic thing: a hosted database plus an API that lets your frontend talk to it directly, without you writing your own server. That's genuinely useful. It's also exactly why permissions matter so much. In a traditional app, your server code decides what a user can see before it ever touches the database. Here, the browser can often reach the database directly. Something still has to decide who's allowed to read or write what. That something is Row Level Security in Supabase, or security rules in Firebase. Skip the config and there's no gate at all. Every row and every document sits open to anyone who can reach your API, which in practice means anyone who opens your app and checks their browser's network tab.
Row Level Security, in plain English
Picture your database as a filing cabinet. Postgres, which Supabase runs on, can lock individual drawers, but out of the box the drawers just sit there once you're inside the building. Row Level Security is the lock you add to each drawer, plus the rule for who gets a key. Turn it on for a table, write a policy like "a user can only read rows where user_id matches their own ID," and the drawer only opens for the right person. Skip that step, or write a policy that's technically there but wrong (inverted logic, a missing condition, checking the wrong column), and the drawer might as well have no lock. RLS is set per table and has historically defaulted to off, which makes it easy to forget on a table you added late in a build session.
Firebase's version is the rules file for Firestore or the Realtime Database. Same idea, different name. A line like allow read, write: if true means anyone can do anything, and that line is easy to leave in because it's literally what Firebase gives you when you start a project in test mode. It's meant to be temporary. Plenty of projects ship with it still sitting there.
What actually happened in 2025
This isn't a hypothetical. In March 2025, a researcher named Matt Palmer started looking at apps built with Lovable, an AI app builder that generates a Supabase backend behind the scenes, and found that a large number of them had Row Level Security missing or set up backwards. He reported it. Lovable acknowledged the report within a few days, and the issue was publicly disclosed in late May 2025, cataloged as CVE-2025-48757.
None of that makes Lovable or Supabase the villain. The database was fine. The API was fine. The missing piece was the same one it always is: somebody has to explicitly decide and configure who's allowed to touch which row, and a tool optimized for "it works and looks right in the preview" has no built-in reason to get that part right unless it's specifically checking for it.
Why this keeps slipping through
Veracode ran a large test in 2025 across more than 100 different AI models on a range of coding tasks and found the generated code failed to defend against common flaws, the OWASP Top 10 categories, in 45% of tests. Access control is a strong candidate for exactly that kind of miss, because it's invisible in a demo. Your own login works. Your own data shows up. Everything looks correct, because you're testing as yourself, the one user the policy was probably written for by accident.
A five-minute check
- Open your Supabase dashboard, go to each table, and confirm RLS shows as enabled, not just present
- Read the actual policy text, not just its name, and check it references the right column
- In Firebase, open your rules file and search for "if true"
- Log in as a second, unrelated test account and try to read or edit another user's data
- Watch your browser's network tab. If a request returns every user's data instead of just yours, that's the bug, right there in the response
Treat it as something you revisit, not something you set once. Every new table is a new place for the same mistake to happen again, and the check above takes about as long as making coffee.