[{"data":1,"prerenderedAt":376},["ShallowReactive",2],{"blog-en-can-anyone-read-your-supabase-database":3},{"id":4,"title":5,"body":6,"category":337,"cover":338,"coverAlt":338,"description":339,"draft":340,"extension":341,"faq":342,"image":358,"keywords":359,"meta":365,"navigation":366,"ogTitle":30,"path":367,"published":368,"seo":369,"stem":370,"tldr":371,"updated":368,"__hash__":375},"blog_en\u002Fblog\u002Fcan-anyone-read-your-supabase-database.md","Can anyone read your Supabase database? We checked 3,680 apps",{"type":7,"value":8,"toc":325},"minimark",[9,13,20,23,26,31,34,43,46,49,53,56,116,122,125,131,137,148,152,155,160,185,192,200,204,207,210,218,222,225,232,236,239,245,251,260,264,298,301,306,313],[10,11,12],"p",{},"Your app has a login screen. Behind it sit your users, their messages, maybe\ntheir orders. It looks private, and there is no obvious way to find out whether\nit actually is, because the Supabase console is not somewhere you have ever\nneeded to go.",[10,14,15,16],{},"So we went and measured it on other people's apps. In August 2026 we scanned\n30,998 live apps published from Lovable, Base44, Replit, v0 and Bolt, and asked\none question of each: ",[17,18,19],"strong",{},"can anyone read your Supabase database without logging\nin?",[10,21,22],{},"For 2,096 of the 3,680 apps where we could get a straight answer, yes.",[10,24,25],{},"Here is the part that both the alarming version of this story and the\nreassuring one get wrong. An open table is not automatically a leak. Plenty of\ntables are meant to be read by everyone. Which table it is decides everything,\nand that is a question only the person who built the app can answer. It is also\nwhy nobody catches this: the app works perfectly either way.",[27,28,30],"h2",{"id":29},"can-anyone-read-your-supabase-database","Can anyone read your Supabase database?",[10,32,33],{},"For more than half of the apps we could check, yes: at least one table returned\nrows to a request carrying no login at all.",[10,35,36,37,42],{},"The reason this is possible has nothing to do with anything being broken. Your\napp talks to Supabase from your visitor's browser, so it carries a key that\nevery visitor can read, and that key is\n",[38,39,41],"a",{"href":40},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","meant to be public",". It names\nyour project. It grants nothing by itself.",[10,44,45],{},"What decides whether a stranger gets your data is Row Level Security: a rule on\neach table saying who may read which rows. With no rule, the key is the only\nthing standing between the internet and that table, and the key is written in\nyour page.",[10,47,48],{},"That is what we were measuring. Not whether a key was visible (it always is),\nbut what the database does when somebody uses it.",[27,50,52],{"id":51},"what-the-57-is-a-share-of","What the 57% is a share of",[10,54,55],{},"It is a share of a base we narrowed three times, and the narrowing matters more\nthan the headline.",[57,58,59,72],"table",{},[60,61,62],"thead",{},[63,64,65,69],"tr",{},[66,67,68],"th",{},"What we counted",[66,70,71],{},"Apps",[73,74,75,84,92,100,108],"tbody",{},[63,76,77,81],{},[78,79,80],"td",{},"Live apps scanned and classified",[78,82,83],{},"30,998",[63,85,86,89],{},[78,87,88],{},"Named a Supabase project in the page",[78,90,91],{},"8,435",[63,93,94,97],{},[78,95,96],{},"Where we could confirm a table and get an answer",[78,98,99],{},"3,680",[63,101,102,105],{},[78,103,104],{},"At least one table readable with no login",[78,106,107],{},"2,096",[63,109,110,113],{},[78,111,112],{},"…and one of those was named after people",[78,114,115],{},"394",[117,118],"diagram",{"alt":119,"caption":120,"src":121},"Four bars scaled against the same total, each narrower than the last: 30,998 apps scanned, 8,435 using Supabase, 3,680 where the check could complete, 2,096 with a table anyone could read. The right-hand column reads 27%, 44% and 57%, each step's share of the step above it.","Every bar is measured against the same total. The 57% is a share of the 3,680 apps we could actually check, not of every app we scanned.","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fwhat-we-measured-1600x700.png",[10,123,124],{},"Three things we did not do, each of which pushes the real figure one way or the\nother and is worth stating rather than burying.",[10,126,127,130],{},[17,128,129],{},"We only asked about table names we could see or guess."," Supabase no longer\nlets a publishable key list the tables in a project, so we read the names an\napp mentions in its own code and added a couple of dozen ordinary ones, capped\nat thirty per app. An app whose tables are named something we did not think of\nlooks clean to us and might not be.",[10,132,133,136],{},[17,134,135],{},"We counted rows, we never read them."," Every probe asked the database how many\nrows it would hand over and stopped there. Nobody's data was downloaded, and no\napp is named anywhere in this article or in anything we publish.",[10,138,139,142,143,147],{},[17,140,141],{},"Nearly all of the apps we could check were Lovable apps."," They are the\nlargest share of what we scanned and the most likely to name their Supabase\nproject in the page, so read this as a measurement of\n",[38,144,146],{"href":145},"\u002Fis-your-lovable-app-safe","Lovable apps using Supabase"," rather than of every\nbuilder. Where the check could not finish, we recorded that it could not finish.\nAn app we failed to check is unknown, not clean.",[27,149,151],{"id":150},"an-open-table-is-not-automatically-a-hole","An open table is not automatically a hole",[10,153,154],{},"From outside, a table anyone can read looks identical whether it holds your\nproduct catalogue or your customers. The response is the same. The name is the\nonly thing that differs.",[117,156],{"alt":157,"caption":158,"src":159},"Two identical request paths drawn one above the other. Both send a table name, both get a 200 response, both get five rows back. The upper path is labelled products and ends in a green tick; the lower is labelled profiles and ends in a red cross.","Same request, same answer, opposite verdicts. Only the owner of the app knows which of these two their open table is.","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fsame-answer-different-table-1600x600.png",[10,161,162,163,167,168,171,172,171,175,171,178,171,181,184],{},"This is why we split the finding in two. In 394 of those apps, one of the\nreadable tables carried a name from a short list we treat as people: ",[164,165,166],"code",{},"users",",\n",[164,169,170],{},"profiles",", ",[164,173,174],{},"customers",[164,176,177],{},"orders",[164,179,180],{},"messages",[164,182,183],{},"invoices",". That is a stranger\nreading your customers, and it needs fixing today.",[10,186,187,188,191],{},"The other 1,702 we cannot judge from outside, and neither can any other scanner.\nA ",[164,189,190],{},"posts"," table might be a public blog, or it might be private notes. You know\nwhich. Nobody looking at your app from the internet does.",[10,193,194,195,199],{},"If you would rather not guess at your own, our free scan checks your live site\nfrom outside and tells you which tables answered. It takes about 20 seconds and\nneeds no account: ",[38,196,198],{"href":197},"\u002F#scan","scan your app",".",[27,201,203],{"id":202},"why-this-happens-to-apps-nobody-opened-up-on-purpose","Why this happens to apps nobody opened up on purpose",[10,205,206],{},"Because the fix that makes a broken app work again is usually the one that opens\nthe table.",[10,208,209],{},"The sequence goes like this. Row Level Security gets switched on, either by you\nor by the builder. Your app immediately stops showing data, because switched on\nwith no rules means the database refuses everybody, including you. You paste the\nerror to your assistant, it writes a policy allowing every request, and the app\nworks again. Nothing about it looks wrong afterwards.",[10,211,212,213,217],{},"That policy is the one we find. The dashboard reports the table as protected,\nbecause the switch is on and a policy exists. The article on\n",[38,214,216],{"href":215},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","why Row Level Security being on is not the same as being protected","\nwalks through the four states a table can be in and how to tell yours apart.",[27,219,221],{"id":220},"the-leak-you-have-been-warned-about-was-the-rare-one","The leak you have been warned about was the rare one",[10,223,224],{},"Across all 30,998 apps, a Supabase secret key sitting in the browser (the key\nthat ignores every rule you have written) turned up 3 times.",[10,226,227,228,231],{},"It is the leak owners hear about constantly and the one we found least often. It\nis serious when it happens, and\n",[38,229,230],{"href":40},"worth knowing how to spot",", but\nworry spent there is guarding a door that is almost always shut. The common\nopening in these apps is an ordinary table with no rule on it.",[27,233,235],{"id":234},"how-to-check-your-own-app","How to check your own app",[10,237,238],{},"Two places to look inside your Supabase database, and one way to see it from\nwhere a stranger stands.",[10,240,241,244],{},[17,242,243],{},"Open the Security Advisor in your Supabase dashboard."," It lists every table\nwith Row Level Security switched off, which is the clearest version of this\nproblem. Supabase is good at flagging it, and if your project is on that list\nyou have your answer without reading a line of SQL.",[10,246,247,250],{},[17,248,249],{},"Then read the policies on any table that holds people."," The Advisor cannot\ndecide whether a permissive policy is intentional, because for a product\ncatalogue it would be correct. Open the table, look at the policy, and see\nwhether it names a condition or allows everyone.",[10,252,253,256,257,259],{},[17,254,255],{},"Or check it from outside, which is where the risk lives."," A stranger does not\nopen your dashboard. Our free scan makes the same anonymous request an outsider\nwould and reports which tables answered: ",[38,258,198],{"href":197},", no account, no\ninstall.",[27,261,263],{"id":262},"what-to-do-about-a-table-that-should-not-be-readable","What to do about a table that should not be readable",[265,266,267],"key-takeaways",{},[268,269,270,286,289,292,295],"ul",{},[271,272,273,274,171,276,171,278,171,280,282,283,285],"li",{},"Start with the tables holding people. ",[164,275,166],{},[164,277,170],{},[164,279,174],{},[164,281,177],{}," and ",[164,284,180],{}," are where somebody else's data lives, and they are the ones worth an evening.",[271,287,288],{},"Write the rule before you widen anything else. A policy that names a condition (this row belongs to this signed-in user) is what makes the publishable key in your app safe to be there.",[271,290,291],{},"Check the policy, not the toggle. Switched on with a rule that allows everybody looks the same from outside as switched off, and your dashboard shows the first one as protected.",[271,293,294],{},"Leave genuinely public tables alone. A product list or a published article being readable is correct, and turning it off breaks your app for no gain.",[271,296,297],{},"Test it the way a stranger would, after the change. Your app showing the right thing proves what your app requests, not what your database will hand over.",[10,299,300],{},"Checking this once is an evening. Keeping the answer true next month is the part\nthat does not fit in one, and it is what we built Reeve Care to do. It re-runs\nthis same check on your app on a schedule and emails you when the answer gets\nworse, because a table that was closed in March and open in June is not\nsomething anyone notices from inside their own app.",[117,302],{"alt":303,"caption":304,"src":305},"The Reeve Care logo beside two rows. In the upper row a strip of table rows is read by a magnifier and marked with a repeat arrow. In the lower row a database inside a dashed boundary is copied to a file outside it, with a magnifier beside the copy.","The two jobs: the check runs again on a schedule, and a copy of your database leaves your Supabase account and is read back before it counts.","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcare-watch-and-backup-1600x520.png",[10,307,308,309,199],{},"It also keeps its own backups of your Supabase database, taken on a schedule,\nstored outside your Supabase account and read back to verify before they count,\nwith a restore that snapshots the current state before it replays anything. That\nsecond half matters here because we only ever check reading. The same permissive\nrule can allow writing, and a stranger writing to your table is the version that\nempties it, at which point a copy from before is the only thing that puts the\nrows back. Care covers your database, and the files your users uploaded once you\nconnect them, on Supabase rather than every kind of database: ",[38,310,312],{"href":311},"\u002F#pricing","what it watches\nand what it costs",[10,314,315,316,320,321,199],{},"If you would rather work through this as a list, the\n",[38,317,319],{"href":318},"\u002Fchecklist","10-minute security checklist"," covers this alongside the other\nthings worth closing in a newly launched app. And if a table was open for a\nwhile, what you can undo later depends entirely on\n",[38,322,324],{"href":323},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","what you were backing up",{"title":326,"searchDepth":327,"depth":327,"links":328},"",3,[329,331,332,333,334,335,336],{"id":29,"depth":330,"text":30},2,{"id":51,"depth":330,"text":52},{"id":150,"depth":330,"text":151},{"id":202,"depth":330,"text":203},{"id":220,"depth":330,"text":221},{"id":234,"depth":330,"text":235},{"id":262,"depth":330,"text":263},"Security basics",null,"Can anyone read your Supabase database without logging in? We scanned 30,998 live apps built with AI builders and measured how often the answer is yes.",false,"md",[343,346,349,352,355],{"q":344,"a":345},"How do I find out if anyone can read my Supabase database?","Two checks answer most of it. In your Supabase dashboard, open the Security Advisor: it lists every table with Row Level Security switched off, and those are readable by anyone holding the key that ships in your app. Then open the policies on any table that holds people, because a table can pass the first check and still be open. A policy that allows everybody is switched on, valid, and reads to the dashboard as protected. If you would rather see it from outside, our free scan reads your live site the way a stranger would.",{"q":347,"a":348},"Is it bad if one of my tables is readable by anyone?","It depends on the table, and you are the only person who can decide. A list of products, published articles or venues on a map is meant to be readable by everyone, and a policy allowing that is correct. The same setting on a table of users, orders or messages means strangers can read your customers. Ask whether you would be comfortable posting that table on a public page, and let the answer decide.",{"q":350,"a":351},"I have Row Level Security turned on. Does that mean my tables are protected?","Not on its own. The switch and the rules are two separate things: switched on with no rule blocks everybody including your own app, and switched on with a permissive rule blocks nobody. The rule that gets written when an app breaks after Row Level Security goes on is usually the one that allows every request from anyone, which makes the app work and leaves the table open. Read the policy on the table, not the toggle.",{"q":353,"a":354},"My app has a login screen. Doesn't that keep people out of the database?","No. Your login screen decides what your app shows. It does not decide what your database hands over, because a request does not have to come from your app at all. The key your app carries is readable by any visitor, and it can be used against your database directly. What decides the answer is Row Level Security on each table.",{"q":356,"a":357},"What should I do first if I find a table that strangers can read?","Fix the policy on that table before anything else, then look at what was reachable while it was open. Start with the tables holding people, since those are the ones with someone else's data in them. If the table was open and holds personal data, check whether your local rules require you to tell anyone; that is a question for a lawyer rather than a scanner.","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",[360,361,362,363,364],"can anyone read my supabase database","supabase database public","supabase table readable by anyone","lovable supabase security","supabase rls exposed table",{},true,"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","2026-08-18",{"title":5,"description":339},"blog\u002Fcan-anyone-read-your-supabase-database",[372,373,374],"Can anyone read your Supabase database without logging in? For 2,096 of the 3,680 apps where we could complete the check (57%), at least one table said yes.","That is not automatically a leak. Some tables are meant to be public. But 394 of those apps had an open table named after people: users, profiles, customers, orders.","The thing owners are usually warned about, a secret key sitting in the app, turned up 3 times in 30,998 apps. The open table is the common one.","TBeIM-9ndv2WfaRU7W5Gc6sSPN7chtF1iUrCqiA2nGw",1787826048204]