PopKoren introduces Rowly, a security scanner for auditing Row Level Security (RLS) policies in Supabase projects. It analyzes policy logic across tables, views, functions, and roles, providing SQL fixes. PeterBuildsSecure suggests improvements, questioning if Rowly checks for FORCE RLS settings and SECURITY DEFINER functions, which are critical for preventing data leaks.
PopKoren introduces Rowly, a free open-source security scanner for auditing Row Level Security policies in Supabase projects. Rowly analyzes policy logic across tables, views, functions, and roles, and provides ready-to-run SQL fixes. The tool is open source and runs without storing connection strings.
PopKoren introduces Rowly, a free open source security scanner for auditing Row Level Security policies in Supabase projects. Rowly analyzes policy logic across tables, views, functions, and roles, providing SQL fixes without storing connection strings. The scanner is open source and runs in memory.
[ Removed by Reddit ]
[ Removed by Reddit ]
[ Removed by Reddit ]
[ Removed by Reddit ]
[ Removed by Reddit ]
Good clarification that single-part upsert already takes the UPDATE path, so the missing UPDATE policy bites even without multipart. Storage RLS surprises like this are why I also want a stranger-view of the whole deploy, not only the one bucket policy I just edited: auth, APIs, storage, and DB rules. [https://rowly.me](https://rowly.me) scans that full external attack surface.
[ Removed by Reddit ]
[ Removed by Reddit ]
[ Removed by Reddit ]
[ Removed by Reddit ]
[ Removed by Reddit ]
Silent wrongness is worse than a loud 500. I have had the same class of bug where RLS or a trigger "looked fine" while the data path quietly did the wrong thing for days. Beside reviewing triggers, I still hit the live app from a second session and check auth, APIs, storage, and policies from outside. [https://rowly.me](https://rowly.me) is the scanner I use for that stranger-view pass.
[ Removed by Reddit ]
[ Removed by Reddit ]
For hackathon demos I treat ship day as the real test: anon key misuse, open buckets, weak RLS, and public APIs a stranger can hit. After deploy, scan the full external attack surface, not only the DB rules. I built https://rowly.me for that live-app check on vibe-coded stacks including Supabase when it is in play.
I landed on Supabase for auth plus Postgres without running my own stack. The first annoyance was realizing generated RLS can look correct and still leave a path open once the app is public. After every deploy I scan auth, APIs, storage, and DB rules from the outside. https://rowly.me is the tool I use for that.
Local policy tests are a good start for RLS and schema assumptions. I still treat the deployed app as a separate check: anonymous access, second-user reads, storage exposure, and any API that bypasses the policies you tested in CI. https://rowly.me scans the full external attack surface, including Supabase/Postgres rules when they are in the stack.
Splitting app reads from analytics is the right instinct. While you are drawing those boundaries, also check which roles and RLS policies the dashboard client actually uses in prod. A pooling fix does not help if a stranger can still hit broad APIs or storage. https://rowly.me scans that live external surface on vibe-coded apps.
Agree the authority boundary has to live server-side. An expected-version RPC helps concurrency, but also assume a modified client will try write paths you did not intend. Before you ship multiplayer, probe the live app for auth, APIs, storage, and DB rules a stranger can hit. https://rowly.me does that external attack-surface scan on vibe-coded deploys.
Rate exceeded on a Replit front end often means anonymous traffic or a leaked client path is hammering Auth or the DB. Cap public endpoints, keep the service role server-side, and verify what an outsider can hit without a session. Rowly scans the full external attack surface of a deployed vibe-coded app, including auth, APIs, storage, and DB rules such as Supabase or Postgres when present: https://rowly.me
Two platforms is fine if you keep one clear trust boundary: the Python service holds secrets and the client only talks through authenticated APIs. Just make sure Supabase RLS, storage, and any direct client routes cannot bypass that. Rowly scans the full external attack surface of a deployed vibe-coded app, including auth, APIs, storage, and DB rules such as Supabase or Postgres when present: https://rowly.me
LLMs can spit out a backend fast, but the risky part is usually the deployed boundaries, not the framework choice. Whatever stack you pick, test auth, API authorization, storage exposure, and database rules from an untrusted account. Rowly scans the full external attack surface of a deployed vibe-coded app, including auth, APIs, storage, and DB rules such as Supabase or Postgres when present: https://rowly.me
A WAF helps with noisy scanning, but it does not replace checking what an anonymous client can still reach through your public APIs and storage. RLS matters, and you still want to verify auth paths, bucket policies, and any service-role misuse from outside. Rowly scans the full external attack surface of a deployed vibe-coded app, including auth, APIs, storage, and DB rules such as Supabase or Postgres when present: https://rowly.me
RLS is confusing because it has to be correct at both the policy and application boundaries. A practical audit is to test as anon, normal user, and a second user, then probe storage, RPCs, and server routes separately from table reads. That outside-in pass is what I’m trying to cover with Rowly across auth, APIs, storage, and DB rules: https://rowly.me
The per-project isolation and dropping the OAuth token are good defaults. I’d still test callback handling, anon-key exposure, storage policies, and migration drift from an external user’s perspective, since a strong RLS suite can miss a public endpoint or bucket. I built Rowly to scan the full external attack surface of deployed vibe-coded apps, including auth, APIs, storage, and DB rules: https://rowly.me
Right, separating the server key from the client is the non-negotiable baseline, while encryption and backup exposure cover a different failure mode. I’d also verify the deployed app cannot reach admin-only paths with the public key and that storage and API rules match the intended tenant boundaries. That kind of outside-in check is what Rowly scans: https://rowly.me
Exactly, service_role should stay server-side and a separate backend reduces accidental exposure, but it still deserves a deployment check for leaked envs, reachable admin endpoints, storage buckets, and database policies. Encryption key custody is another layer, not a replacement for testing auth and authorization paths. I’m building Rowly to scan that full external surface: https://rowly.me
Exactly. RLS is a row boundary, but grants and writable columns can still expand what a valid row update changes. I like pairing policy tests with actual API calls under several identities, which is the approach I’m taking in Rowly’s broader scan: https://rowly.me
The key thing here is that RLS correctness can still leave a table-wide grant or writable column as the escape hatch. I’d keep the revoke and grant audit in migrations and test the deployed API with anon, authenticated, and cross-tenant IDs, plus storage paths if present. That broader external pass is what I’m building with Rowly: https://rowly.me
Turnstile on signup and recovery is useful, but rate-limit every auth path and avoid revealing account state. Before launch, test what an unauthenticated session can reach in the app, APIs, storage, and database rules. https://rowly.me checks the full external surface of a deployed vibe-coded app, including Supabase/Postgres when used.
Before App Store review, treat OTP as one slice of the live surface. From a stranger device, poke auth flows, APIs, storage, and DB rules (Supabase RLS if that is your backend). I built https://rowly.me for that full external attack-surface pass on vibe-coded apps.
Project count matters less than whether each live app is locked down. After you spin them up, poke auth, APIs, storage, and DB rules from outside. https://rowly.me does that stranger-view scan on deployed vibe-coded apps.
Interview tip from the builder side: know how loose RLS, open buckets, and public keys look from outside the project. I built https://rowly.me to scan the full external attack surface of vibe apps that use Supabase/Postgres among other things.
Sustained 100% I/O often means something is hammering tables or storage harder than you expect. While you dig into queries, also confirm anon clients cannot abuse auth, APIs, storage, or DB rules from outside. https://rowly.me is my outside-in pass for that.
Local migrate tooling is handy. Once you push back to a public URL, re-check RLS, keys, and storage from a logged-out browser. Cloud and local drift is a common way loose policies ship. https://rowly.me does that outside check for vibe-coded apps.
Anomaly detection on Supabase is useful, but it still helps to know what an unauthenticated stranger can already reach. Auth holes, open buckets, and loose RLS show up before fancy alerts. That first outside pass on vibe-coded apps is what https://rowly.me is for.
If rows vanish with no delete in the audit trail, check RLS, soft deletes, and whether another role or Edge Function is rewriting data. Also confirm nothing public can TRUNCATE or overwrite via a wide policy. https://rowly.me is what I built to poke that external surface on deployed vibe apps.
That revoke-columns gotcha is nasty because .update().select() suddenly fails while the write itself may still go through. Worth testing with the anon key from a clean browser, not only the SQL editor. I use https://rowly.me for a full outside pass on auth, APIs, storage, and policies.
For multi-tenant Supabase, start with tenant_id on every row and RLS that never trusts the client beyond auth.uid(). Also lock storage paths the same way. Once it is deployed, verify what a stranger can hit from outside. https://rowly.me is the check I run for that.
Google auth is fine; the painful part is what the session can reach after login. Make sure RLS and API routes still assume a hostile client with a valid token. Before calling a vibe app done I scan the live external surface (auth, APIs, storage, DB rules) with https://rowly.me.
For AI artifacts I usually separate public vs private buckets and never rely on a secret path. Treat every object URL as something a stranger might guess or scrape. After you wire storage, run an outside check on auth, APIs, buckets, and policies. https://rowly.me is what I use for that on vibe-coded deploys.
Yeah this is a classic trap. A tight SELECT policy can make an open UPDATE look fine in the dashboard until someone hits the table with the anon key. Before you ship, poke the live app from outside for auth, APIs, storage, and DB rules. I use https://rowly.me for that stranger-view pass.
Silent insert weirdness is often RLS or a policy that allows read but not write under the role you expect, so trace which JWT role the client actually uses. Once it works, I still like an outside-in scan of the live app with https://rowly.me for vibe-coded apps.
Static egress helps when a partner allowlists your IP, but it does not replace locking down what those functions can do with your keys. I still verify auth, APIs, storage, and DB rules on the live app from outside with https://rowly.me.
For features like RPC and full-text search, keep the database functions narrow and enforce authorization inside them rather than trusting only the client. I also test the deployed surface from outside for auth, APIs, storage, and DB rules with https://rowly.me.
Second-pass migrations usually mean the first change missed a dependent policy, view, or grant. After schema churn, re-check RLS and storage policies on the live project. I use https://rowly.me to scan the external attack surface (auth, APIs, storage, DB rules) after deploys.
2 vCPU / 8 GB can work for a small production box if you leave headroom for Postgres and storage IO. After it is up, still verify what a stranger can hit from outside: auth, APIs, buckets, and policies. That outside pass is what I built https://rowly.me for.
If the game client talks to Supabase directly, assume a reverse engineer will pull the anon key and hit your tables. Lock everything with RLS and never put the service role in the build. For a stranger-view check of auth, APIs, storage, and DB rules, I run https://rowly.me.
Dry-running agent writes before they land is a smart gate. Pair that with checking what the deployed app already exposes from outside. I use https://rowly.me for that live external pass after the agent ships a change.
Self-hosting is fine, but once it is reachable from the internet the same outside-in checks still matter: auth paths, open APIs, storage, and DB rules. I built https://rowly.me for that full external pass on vibe-coded deploys (Pro is 50% off through today).