[{"data":1,"prerenderedAt":732},["ShallowReactive",2],{"blog-en-supabase-rls-disabled-in-public":3,"blog-index-en":491},{"id":4,"title":5,"body":6,"category":447,"cover":448,"coverAlt":449,"description":450,"draft":451,"extension":452,"faq":453,"image":469,"keywords":470,"meta":479,"navigation":480,"ogTitle":481,"path":482,"published":483,"seo":484,"stem":485,"tldr":486,"updated":483,"__hash__":490},"blog_en\u002Fblog\u002Fsupabase-rls-disabled-in-public.md","Supabase \"RLS disabled in public\": what the warning misses",{"type":7,"value":8,"toc":435},"minimark",[9,18,29,36,41,44,55,58,61,65,68,71,77,80,83,87,98,101,107,110,117,212,215,221,235,239,242,249,252,255,261,271,275,278,281,286,299,306,310,313,316,329,335,348,352,355,362,365,370,373,385,389,422],[10,11,12,13,17],"p",{},"You opened the Security Advisor in your Supabase dashboard, or something pasted\nits output at you, and there it is in red: ",[14,15,16],"strong",{},"RLS disabled in public",". Under it,\none line per table, in Supabase's own words:",[19,20,25],"pre",{"className":21,"code":23,"language":24},[22],"language-text","Table public.profiles is public, but RLS has not been enabled.\n","text",[26,27,23],"code",{"__ignoreMap":28},"",[10,30,31,32,35],{},"Here is the part that guide after guide gets wrong: ",[14,33,34],{},"clearing that list does\nnot mean nobody can read your data."," The advisor has a separate rule for a\npolicy that lets everyone in, and that rule skips the exact shape an AI builder\nwrites when it unbreaks your app. So the list you just fixed and the list of\ntables a stranger can read are two different lists, and one of them is not\nprinted anywhere in your dashboard.",[37,38,40],"h2",{"id":39},"what-does-rls-disabled-in-public-mean","What does \"RLS disabled in public\" mean?",[10,42,43],{},"One table in your public schema has row level security switched off, and the\nconsequence is that anyone holding your project address can read every row in\nit.",[10,45,46,47,50,51,54],{},"Both halves of that need unpacking. The ",[14,48,49],{},"public schema"," is the default place a\ntable goes when nobody says otherwise, and it is the part of your database\nSupabase publishes on the web: every project answers requests at an address of\nits own, and the key needed to talk to it is in the code your site sends to\nevery visitor. ",[14,52,53],{},"Row level security"," is the switch that decides whether your\nrules get consulted before rows are handed over. With it off, there is nothing\nto consult, so the answer is always yes.",[10,56,57],{},"That combination is why this one is reported as an error rather than a warning.\nThe advisor grades its findings, and this is the top of the scale.",[10,59,60],{},"Think of the advisor as an inspector with a clipboard. It reads your paperwork\ncarefully and it is good at it. It never tries the handle. Nothing in that panel\nis the result of a request anybody made to your database.",[37,62,64],{"id":63},"will-enabling-rls-break-my-app","Will enabling RLS break my app?",[10,66,67],{},"Yes, straight away, and that is the setting working.",[10,69,70],{},"The fix Supabase gives you is one line, and you run it in the SQL Editor:",[19,72,75],{"className":73,"code":74,"language":24},[22],"alter table public.profiles enable row level security;\n",[26,76,74],{"__ignoreMap":28},[10,78,79],{},"Supabase's own documentation is direct about what happens next: data becomes\ninaccessible through the API using a publishable key until policies are\ndefined. So your lists come back empty, your screens go blank, and the error in\nthe advisor is replaced by a quieter entry saying the table has RLS enabled but\nno policies exist.",[10,81,82],{},"That is the door shut with nobody on the list yet. The next thing most people do\nis add a policy letting everyone read, because that is what makes the screens\ncome back.",[37,84,86],{"id":85},"the-failure-the-warning-is-not-looking-for","The failure the warning is not looking for",[10,88,89,90,93,94,97],{},"A table with row level security ",[14,91,92],{},"on",", and a read policy whose condition is\n",[26,95,96],{},"USING (true)",", hands over exactly the same rows to exactly the same stranger.\nThe advisor does not flag it.",[10,99,100],{},"That is not an oversight. Supabase does have a rule for always-true policies,\nand it leaves read policies out of that rule on purpose. Their own description\nof it says so:",[19,102,105],{"className":103,"code":104,"language":24},[22],"SELECT policies with `USING (true)` are intentionally excluded as this\npattern is often used deliberately for public read access.\n",[26,106,104],{"__ignoreMap":28},[10,108,109],{},"The rule is right about the general case. A product catalogue, a list of\npublished articles, a map of venues: those are meant to be readable by anyone,\nand flagging them would train every developer on the platform to ignore the\npanel. What no linter can know is whether the table it is looking at holds\nvenues or customers.",[10,111,112,113,116],{},"And a policy allowing everyone to read is the fastest way to make a broken app\nwork again, which is why an AI builder reaches for it. Ask Cursor or Lovable to\nfix the empty screens and ",[26,114,115],{},"FOR SELECT USING (true)"," is a common answer. Your app\nloads, the error clears, the panel goes quiet, and the table is as readable as\nit was before you started.",[118,119,120,136],"table",{},[121,122,123],"thead",{},[124,125,126,130,133],"tr",{},[127,128,129],"th",{},"What the advisor can see",[127,131,132],{},"How it reports it",[127,134,135],{},"What a stranger with your publishable key gets",[137,138,139,155,169,183,198],"tbody",{},[124,140,141,145,148],{},[142,143,144],"td",{},"RLS switched off",[142,146,147],{},"Error",[142,149,150],{},[151,152,154],"key-verdict",{"type":153},"danger","Every row",[124,156,157,160,163],{},[142,158,159],{},"RLS on, no policies at all",[142,161,162],{},"Info",[142,164,165],{},[151,166,168],{"type":167},"safe","Nothing",[124,170,171,176,179],{},[142,172,173,174],{},"RLS on, ",[26,175,115],{},[142,177,178],{},"Nothing at all",[142,180,181],{},[151,182,154],{"type":153},[124,184,185,190,193],{},[142,186,173,187],{},[26,188,189],{},"FOR ALL USING (true)",[142,191,192],{},"Warning",[142,194,195],{},[151,196,197],{"type":153},"Every row, and can change them",[124,199,200,205,207],{},[142,201,173,202],{},[26,203,204],{},"USING (auth.uid() = user_id)",[142,206,178],{},[142,208,209],{},[151,210,211],{"type":167},"Only their own",[10,213,214],{},"The two rows that report nothing at all are the pair worth sitting with. One of\nthem is a table nobody outside your app can touch. The other is a table anybody\ncan read. Your dashboard is equally quiet about both.",[216,217],"diagram",{"alt":218,"caption":219,"src":220},"Two lanes ending in the same four rows, all of them lit. The upper lane has the row level security switch off and carries a warning mark. The lower lane has the switch on, a policy reading USING (true), and an empty dashed circle where a mark would be.","Same four rows handed to the same stranger. The difference between the lanes is which one your dashboard says anything about.","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Ftwo-tables-one-outcome-1600x640.png",[10,222,223,224,229,230,234],{},"How that policy came to be written, and what to replace it with table by table,\nis the subject of\n",[225,226,228],"a",{"href":227},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","Row Level Security is on and your table is still public",".\nIf the same policy also has to let your app save data, the error you meet next\nis ",[225,231,233],{"href":232},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","new row violates row-level security policy",".",[37,236,238],{"id":237},"why-the-table-you-made-with-a-migration-never-warned-you","Why the table you made with a migration never warned you",[10,240,241],{},"Because the Table Editor switches row level security on for you, and SQL does\nnot.",[10,243,244,245,248],{},"Supabase documents the split plainly: tables created with the dashboard's Table\nEditor have RLS enabled by default, and tables created with raw SQL have to have\nit enabled explicitly. A table you clicked into being starts protected. A table\nthat arrived through a migration file, a ",[26,246,247],{},"supabase db push",", a snippet in the\nSQL Editor, or a statement your AI builder ran on your behalf starts open.",[10,250,251],{},"That second route is how an AI builder makes a table. It writes the SQL and runs\nit for you, so you never saw the checkbox and never saw it unticked.",[10,253,254],{},"The habit that closes it is putting the line in the migration next to the thing\nit protects:",[19,256,259],{"className":257,"code":258,"language":24},[22],"create table public.profiles (\n  id uuid primary key references auth.users,\n  full_name text\n);\n\nalter table public.profiles enable row level security;\n",[26,260,258],{"__ignoreMap":28},[262,263,265],"callout",{"type":264},"warn",[10,266,267,270],{},[14,268,269],{},"The advisor is a snapshot, not a monitor."," It reports what your database\nlooked like when it last ran, and it will happily go on showing you a clean\npanel from before this morning's migration. Re-run it after any change that\ncreates a table or touches a policy, which in an AI-built project is most\nchanges.",[37,272,274],{"id":273},"how-to-check-the-tables-the-advisor-cleared","How to check the tables the advisor cleared",[10,276,277],{},"Ask your database the question a stranger asks: send a request from outside,\nusing the publishable key that ships in your app, and see what comes back.",[10,279,280],{},"This is the difference the whole article turns on. The advisor reads your\nconfiguration. A request reads your rows. Those are two different questions, and\na table can pass the first while failing the second, which is exactly what a\npermissive read policy does.",[216,282],{"alt":283,"caption":284,"src":285},"Two readers outside a dashed project boundary. A magnifier reaches only the settings panel inside it and comes back to an empty dashed circle. A person's request reaches past it to the table's rows and comes back holding them.","The advisor stops at your settings. A request from outside carries on to the rows, which is why the two can disagree about the same table.","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fsettings-versus-answer-1600x600.png",[10,287,288,289,293,294,298],{},"We ran that request at scale. Between 12 and 14 August 2026 we ran nine external\nchecks over 30,998 live apps published from Lovable, Base44, Replit, v0 and\nBolt. Of the 3,680 Supabase-backed apps where the check could complete, 2,096\nhad at least one table that answered an anonymous request with rows. That is\n57%, and it is a share of the apps we could get a straight answer from rather\nthan of everything we scanned. Among Bolt-built apps the figure was 27 of 35,\nwhich is a small enough sample to read as a direction rather than a rate. The\n",[225,290,292],{"href":291},"\u002Fresearch\u002Fvibe-coded-app-security-2026","full dataset is published",", and\n",[225,295,297],{"href":296},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","what the 57% is a share of"," walks\nthrough the counting.",[10,300,301,302,234],{},"You can run the same request yourself against one table with a browser and your\nown publishable key. If you would rather not do it table by table, our free scan\nasks your live app from outside and tells you which tables answered. It takes\nabout 20 seconds and needs no account: ",[225,303,305],{"href":304},"\u002F#scan","scan your app",[37,307,309],{"id":308},"do-i-need-a-backup-before-i-change-rls-policies","Do I need a backup before I change RLS policies?",[10,311,312],{},"For any table your app writes to, yes. For a read-only table you are only\ntightening, the risk is your app going blank rather than your data going\nmissing.",[10,314,315],{},"Two different things are worth separating here, because only one of them is\nabout the repair.",[10,317,318,321,322,324,325,328],{},[14,319,320],{},"What a permissive policy already allowed."," If the rule on the table was\n",[26,323,189],{}," rather than ",[26,326,327],{},"FOR SELECT",", then anyone who found it could\nchange and delete rows as well as read them, and tightening the policy today\ndoes nothing about yesterday. That version of this usually surfaces as a support\nmessage about data that changed on its own, or as a table that is suddenly\nempty.",[10,330,331,334],{},[14,332,333],{},"The repair itself."," Rewriting policies across a dozen tables is a change to a\nlive database, written by the same tools that produced the problem. A migration\nthat drops a policy and recreates it wrongly is an ordinary Tuesday, and the way\nback is a copy of how things were an hour ago.",[10,336,337,338,342,343,347],{},"On a paid Supabase plan you have last night's copy sitting in the console. On\nthe free plan there is nothing to fall back to, because\n",[225,339,341],{"href":340},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","the free plan takes no automatic backups at all",".\nIf that is you, take one before you touch a policy:\n",[225,344,346],{"href":345},"\u002Fblog\u002Fback-up-supabase-free-tier","how to back up a Supabase database on the free tier","\nis the ten-minute version.",[37,349,351],{"id":350},"what-reeve-care-keeps-a-copy-of","What Reeve Care keeps a copy of",[10,353,354],{},"Your Supabase database, copied on a schedule, held outside your Supabase\naccount, encrypted, and read back before the date on your dashboard moves. The\nfiles your users uploaded travel with it once you connect a Storage key.",[10,356,357,358,361],{},"Two limits, said up front. Backups are ",[14,359,360],{},"Supabase only",": if your data lives\nsomewhere else we say so rather than sell you a subscription that watches an\nempty box. And the Storage key is asked for separately, because Supabase issues\nno read-only key for files, so the one that copies your uploads can also write.\nThe key that copies your database cannot. Connecting it is optional, and the\ndatabase is backed up either way.",[10,363,364],{},"The restore is the part that matters for this article. Putting an old copy back\nover a live database is the scariest button in the product, so Care takes a copy\nof the current state first, and only then replays the one you picked. The\nrestore has an undo of its own.",[216,366],{"alt":367,"caption":368,"src":369},"A dashed boundary around a database, with the Reeve Care mark beside it. Step one is an arrow leaving the boundary to a fresh copy. Step two is an arrow bringing the stored copy back in.","What happens when you press restore. The current state is copied out before anything is replayed, so pressing the button is reversible too.","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Frestore-takes-a-copy-first-1600x520.png",[10,371,372],{},"Care's other half is the one this article keeps pointing at. A policy that\nloosened during a migration is not a thing you find by looking, so the same\nexternal check runs again on a schedule and tells you when the answer changes.\nUptime, a monthly report and the scan sit on the same subscription.",[10,374,375,376,380,381,234],{},"What a copy does not do is write your policies for you, and no backup makes an\nopen table closed. Those tables are still yours to fix. What the copy changes is\nwhat happens when the fix goes sideways.\n",[225,377,379],{"href":378},"\u002Fsupabase-backups","What Reeve backs up on Supabase, how often, and what a restore does","\ndraws the whole cycle, and the plans and their prices are on the\n",[225,382,384],{"href":383},"\u002Fpricing","pricing page",[37,386,388],{"id":387},"what-to-do-this-week","What to do this week",[390,391,392],"key-takeaways",{},[393,394,395,403,409,412,419],"ul",{},[396,397,398,399,402],"li",{},"Clear the \"RLS disabled in public\" entries first. They are the tables where nothing is being consulted at all, and the fix is one ",[26,400,401],{},"alter table"," line each.",[396,404,405,406,408],{},"Then open Authentication → Policies and read the condition on every policy that survived. A ",[26,407,96],{}," on a read policy is invisible to the advisor and wide open to a stranger.",[396,410,411],{},"Decide table by table whether you would be comfortable publishing its contents on a page. That is the question the linter cannot answer for you, and it is the only one that matters for a permissive read policy.",[396,413,414,415,418],{},"Put ",[26,416,417],{},"alter table ... enable row level security;"," into every migration that creates a table, and re-run the advisor after each one. The dashboard's default only applies to tables you make by clicking.",[396,420,421],{},"Take a copy of your database before you rewrite policies on a live table, and check which Supabase plan you are on so you know whether you already have one.",[10,423,424,425,429,430,434],{},"Start with the table that would embarrass you most as a public page. The\n",[225,426,428],{"href":427},"\u002Fchecklist","10-minute security checklist"," covers this alongside the rest of\nwhat is worth confirming in a newly launched app, and the\n",[225,431,433],{"href":432},"\u002Fis-your-supabase-app-safe","Supabase safety guide"," goes through what else tends\nto be left open.",{"title":28,"searchDepth":436,"depth":436,"links":437},3,[438,440,441,442,443,444,445,446],{"id":39,"depth":439,"text":40},2,{"id":63,"depth":439,"text":64},{"id":85,"depth":439,"text":86},{"id":237,"depth":439,"text":238},{"id":273,"depth":439,"text":274},{"id":308,"depth":439,"text":309},{"id":350,"depth":439,"text":351},{"id":387,"depth":439,"text":388},"Security basics","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcover-1200x630.png","A dashboard panel listing several tables, with a warning mark beside one of them and nothing beside the others.","Supabase reports \"RLS disabled in public\" as an error. It says nothing about the read policy that leaves your table just as open to strangers.",false,"md",[454,457,460,463,466],{"q":455,"a":456},"Is \"RLS disabled in public\" an error or a warning?","An error, and it is the highest level the advisor uses. The entry reads \"Table public.\u003Cname> is public, but RLS has not been enabled.\" The two related entries are quieter: a table with the setting on and no policies at all is reported as INFO, and a policy whose condition is always true is reported as WARN. Those levels describe how confident the linter is about what it can see in your configuration, not how much trouble you are in.",{"q":458,"a":459},"Will enabling Row Level Security break my app?","Immediately, yes, and that is the setting doing its job. Supabase documents that data becomes inaccessible through the API with a publishable key until policies are defined, so the moment you run the enable line your lists come back empty and your screens go blank. The app comes back when you add a policy saying who may see which rows. The mistake to avoid is adding one that allows everybody, because that version also makes the app work.",{"q":461,"a":462},"I enabled RLS and now nothing loads. What happened?","Nothing broke. With row level security on and no policies written, Postgres (the database engine underneath Supabase) refuses every request, including the ones from your own app, and the advisor swaps its error for an INFO entry saying the table has RLS enabled but no policies exist. Write a policy for the rows your app is supposed to show, starting with one that compares the signed-in visitor to the owner column on the row.",{"q":464,"a":465},"My table is not flagged but anyone can read it. Why?","Most likely because row level security is on and there is a read policy whose condition is USING (true). The advisor does have a rule for always-true policies, and it deliberately skips read policies, because public read access is a reasonable thing to want for a product catalogue or a list of published articles. Nothing in your dashboard knows whether your table holds venues or customers, so that one is yours to check.",{"q":467,"a":468},"Do I need Row Level Security if my app only talks to my own server?","If the browser genuinely never talks to Supabase, and no publishable key is in the code your site sends to visitors, then the Data API is not a way in and policies are not the thing protecting those tables. That is rare in an app built with Lovable, Bolt or v0, because those builders wire the browser straight to Supabase by default. Open your own site, check whether your project URL and publishable key are in the page, and let that answer decide it.","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",[471,472,473,474,475,476,477,478],"rls disabled in public","supabase rls disabled warning","supabase security advisor","supabase database linter","supabase lint 0013","table is public but rls has not been enabled","supabase enable rls","rls policy always true",{},true,"Supabase: RLS disabled in public","\u002Fblog\u002Fsupabase-rls-disabled-in-public","2026-09-09",{"title":5,"description":450},"blog\u002Fsupabase-rls-disabled-in-public",[487,488,489],"\"RLS disabled in public\" means one thing: a table in your public schema has row level security switched off, so anyone holding your project address and publishable key can read it.","It says nothing about a table where you switched the setting on and then wrote a policy that lets everyone read. The advisor has a rule for always-true policies and that rule skips read policies on purpose.","Clear the flagged tables, then check the rest from outside, because the advisor reads your settings and never asks your database what a stranger actually gets back.","RtIabfkjTjO3TIqJmxJJlAf03W0DsGLyWnh_YJdSehg",[492,499,505,511,517,523,529,535,541,547,553,559,565,571,577,578,584,590,596,602,608,614,620,626,632,637,643,649,654,660,666,672,678,684,690,695,700,706,711,716,721,727],{"path":493,"title":494,"description":495,"published":496,"category":497,"image":498,"draft":451},"\u002Fblog\u002Fsupabase-backup-auth-users","Why your Supabase dump has no users in it","Run supabase db dump on its own and you get the shape of your database and none of its rows, with the auth schema your users live in left out entirely.","2026-09-23","Backups","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":500,"title":501,"description":502,"published":503,"category":447,"image":504,"draft":451},"\u002Fblog\u002Fdomain-and-certificate-expiry","Domain expired, website down: what actually happens next","Your domain expired and your website is down. Here is the clock you are on, why a lapsed certificate is the easier of the two, and how to check both.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":506,"title":507,"description":508,"published":509,"category":447,"image":510,"draft":451},"\u002Fblog\u002Fis-lovable-safe","Is Lovable safe? What 18,554 live Lovable apps showed","Is Lovable safe? We ran nine checks on 18,554 live Lovable apps. The platform was the cleanest of five builders. Every finding was inside the app itself.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":512,"title":513,"description":514,"published":515,"category":447,"image":516,"draft":451},"\u002Fblog\u002Fvibe-coded-app-security-checklist","The vibe coding security checklist, in nine checks","A vibe coding security checklist with nine items, each one something anyone can verify about your live app from outside, and each with a one-line test.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":518,"title":519,"description":520,"published":521,"category":447,"image":522,"draft":451},"\u002Fblog\u002Fstripe-secret-key-in-frontend","A Stripe secret key exposed in your frontend can move money","A Stripe secret key exposed in your frontend can refund, charge and read every customer record you hold. Your pk_live_ key is meant to be there.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":524,"title":525,"description":526,"published":527,"category":447,"image":528,"draft":451},"\u002Fblog\u002Fvite-and-next-public-env-vars","Vite env variables exposed: VITE_ and NEXT_PUBLIC_ mean publish this","Vite env variables exposed in your app did what the prefix asked. VITE_ and NEXT_PUBLIC_ mean publish this, and the AI that added one never knew the cost.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":530,"title":531,"description":532,"published":533,"category":447,"image":534,"draft":451},"\u002Fblog\u002Fbase44-source-maps","Base44 security: what a scan flags, and what is yours to fix","Base44 security on 5,438 scanned apps: three findings on nearly every one are the platform's, the source map is Base44's badge, and what is yours is short.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":536,"title":537,"description":538,"published":539,"category":447,"image":540,"draft":451},"\u002Fblog\u002Fis-cursor-ai-safe","Is Cursor AI safe? The editor, the code, and the app you shipped","Is Cursor AI safe? Three questions in one search: what Cursor keeps, what the code it writes gets wrong, and whether the app you shipped is open.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":542,"title":543,"description":544,"published":545,"category":447,"image":546,"draft":451},"\u002Fblog\u002Fis-replit-safe","Is Replit safe? What we found in 3,042 live Replit apps","Is Replit safe? We ran nine external checks on 3,042 live Replit apps. The host was not where the findings were. The app each owner published was.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":548,"title":549,"description":550,"published":551,"category":497,"image":552,"draft":451},"\u002Fblog\u002Fsupabase-storage-backup","Supabase storage backup: why your database copy has no files","A Supabase storage backup is a separate job. Database backups keep the list of your files and none of the files, so a restore leaves every upload broken.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":554,"title":555,"description":556,"published":557,"category":497,"image":558,"draft":451},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Supabase point-in-time recovery: what it costs, what it misses","Supabase point-in-time recovery rewinds your database to any second in the last week. It costs $100 a month on top of Pro, and it covers your database only.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":560,"title":561,"description":562,"published":563,"category":497,"image":564,"draft":451},"\u002Fblog\u002Fsupabase-project-paused-recover","Supabase project paused? Your data is still there","Supabase paused your project after a week of inactivity. Nothing is deleted, Restore sits beside the project name, and you have a year before that changes.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":566,"title":567,"description":568,"published":569,"category":447,"image":570,"draft":451},"\u002Fblog\u002Fsafest-ai-app-builder","Which AI app builder is safest? We scanned 30,998 apps","Which AI app builder is safest? We scanned 30,998 live apps from Lovable, Base44, Replit, v0 and Bolt. The builder is not what decides your grade.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":572,"title":573,"description":574,"published":575,"category":447,"image":576,"draft":451},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Enable Row Level Security on every Supabase table, then prove it","Enabling Row Level Security in Supabase with no policy locks a table completely. A policy without the setting does nothing. Here is the SQL, and the test.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":482,"title":5,"description":450,"published":483,"category":447,"image":469,"draft":451},{"path":579,"title":580,"description":581,"published":582,"category":447,"image":583,"draft":451},"\u002Fblog\u002Frotate-supabase-service-role-key","How to rotate a leaked Supabase service_role key","Supabase says fix the leak first. Other guides say rotate now. Which is right depends on where your service_role key leaked.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":585,"title":586,"description":587,"published":588,"category":447,"image":589,"draft":451},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Vibe coding security scanners compared, including ours","The best vibe coding security scanner comes down to three questions no feature list answers. Ten tools compared, with prices, and the jobs Reeve does not do.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":591,"title":592,"description":593,"published":594,"category":447,"image":595,"draft":451},"\u002Fblog\u002Fsupabase-security-checker","Supabase security checker: run the five checks yourself","A Supabase security checker reads your published app instead of your project settings. Here are the five checks it runs, and how to run each one yourself.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":597,"title":598,"description":599,"published":600,"category":447,"image":601,"draft":451},"\u002Fblog\u002Fvibe-coding-security-scanner","Vibe coding security scanner: what a URL scan misses","A vibe coding security scanner reads your live app from outside. Here is what that covers, the four things it cannot see, and how to read the result.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":603,"title":604,"description":605,"published":606,"category":447,"image":607,"draft":451},"\u002Fblog\u002Fmissing-security-headers","Missing security headers: when it actually matters","Missing security headers is the finding our scanner prints most. Here is what it protects against, and when it is the least urgent line on your report.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":609,"title":610,"description":611,"published":612,"category":447,"image":613,"draft":451},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","Your OpenAI API key is exposed in your frontend. Rotate it.","An OpenAI API key exposed in your frontend cannot be locked to a domain. Rotate it today, move the call behind your own endpoint, and cap the spend.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":615,"title":616,"description":617,"published":618,"category":447,"image":619,"draft":451},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","An API key exposed in your frontend: what 30,998 apps shipped","An API key exposed in your frontend is usually a Google Maps key. We scanned 30,998 live vibe-coded apps and counted which secrets actually leak.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":621,"title":622,"description":623,"published":624,"category":497,"image":625,"draft":451},"\u002Fblog\u002Fsupabase-backup-tools-compared","Supabase backup tools compared, including ours","Four kinds of Supabase backup tool, what each one actually copies, and the case where a free GitHub Action beats paying anyone, us included.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":627,"title":628,"description":629,"published":630,"category":447,"image":631,"draft":451},"\u002Fblog\u002Freplit-secrets-explained","How to use secrets in Replit, and what still gets published","How to use secrets in Replit: add one, read it back, and fix the two reasons it comes back undefined. Plus the keys the Secrets tool cannot keep private.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":345,"title":633,"description":634,"published":635,"category":497,"image":636,"draft":451},"Supabase free tier backups: how to make one without a terminal","There are no Supabase free tier backups, so the copy has to come from you. How to make one from the dashboard, and what CSV leaves out.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":638,"title":639,"description":640,"published":641,"category":447,"image":642,"draft":451},"\u002Fblog\u002Fis-supabase-secure","Is Supabase secure? Yes. Your project is a separate question","Is Supabase secure? The platform is audited, encrypted and pen-tested. Their own compliance documents say where that stops and your settings begin.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":644,"title":645,"description":646,"published":647,"category":447,"image":648,"draft":451},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Where to find your Supabase API keys: anon, service_role and the URL","Your Supabase project URL, anon key and service_role key are on one dashboard page. Here is where that page is, and which of the four belongs in your app.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":232,"title":650,"description":651,"published":652,"category":447,"image":653,"draft":451},"New row violates row-level security policy in Supabase. Now what?","\"New row violates row-level security policy\" means Supabase refused a write. The fix that clears it in ten seconds also reopens the table to everyone.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":655,"title":656,"description":657,"published":658,"category":447,"image":659,"draft":451},"\u002Fblog\u002Fcors-wildcard-security-risk","Is a CORS wildcard a security risk? Usually not.","Is a CORS wildcard a security risk? Usually it is your builder default, and it gives away nothing your server was not already handing to anyone who asked.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":661,"title":662,"description":663,"published":664,"category":497,"image":665,"draft":451},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Supabase branching is not a backup. It only goes forwards.","Supabase branching is not a backup: a branch starts with none of your data, and merging only moves schema. What it is for, and what to use instead.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":667,"title":668,"description":669,"published":670,"category":497,"image":671,"draft":451},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","How to restore a Supabase backup, and what breaks after","How to restore a Supabase backup from the dashboard or from a dump file, what the restore replaces, and why your app can still be broken when it finishes.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":673,"title":674,"description":675,"published":676,"category":447,"image":677,"draft":451},"\u002Fblog\u002Fsupabase-storage-bucket-public","Your Supabase storage bucket is public. Is that a problem?","A public Supabase storage bucket means anyone with a file URL can open it. It does not mean anyone can list what is in there. Two different settings.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":679,"title":680,"description":681,"published":682,"category":447,"image":683,"draft":451},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Is a Google API key exposed in your frontend a problem?","A Google API key exposed in your frontend is the key our scanner finds most often, and usually it is fine. One free setting decides which it is.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":685,"title":686,"description":687,"published":688,"category":497,"image":689,"draft":451},"\u002Fblog\u002Fai-agent-deleted-my-database","An AI agent deleted my Supabase data. What can I recover?","An AI agent deleted your database data. What you can recover was decided before it ran, and the next few minutes decide how much of it survives.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":296,"title":691,"description":692,"published":693,"category":447,"image":694,"draft":451},"Can anyone read your Supabase database? We checked 3,680 apps","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.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":696,"title":697,"description":698,"published":693,"category":447,"image":699,"draft":451},"\u002Fblog\u002Fsource-maps-exposed-in-production","Source maps exposed: your app is publishing its original code","An exposed source map lets anyone read your app's original code, comments included. The 30-second check, and what actually matters if yours are public.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":701,"title":702,"description":703,"published":704,"category":447,"image":705,"draft":451},"\u002Fblog\u002Fsupabase-new-api-keys","Supabase's new API keys: which one is safe in your app?","Supabase replaced anon and service_role with publishable and secret keys. Which one belongs in your app, and which never does?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":340,"title":707,"description":708,"published":709,"category":497,"image":710,"draft":451},"Does Supabase back up my database? It depends on your plan.","Does Supabase back up your database? Daily on paid plans, and not at all on the free one. How to check which you have, and what that copy cannot survive.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":227,"title":712,"description":713,"published":714,"category":447,"image":715,"draft":451},"Supabase Row Level Security is on. Your table is still public.","Turning on Supabase Row Level Security does not protect a table. Your policies do, and the policy that fixed your broken app may let everyone in.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":717,"title":718,"description":719,"published":714,"category":497,"image":720,"draft":451},"\u002Fblog\u002Fversion-history-is-not-a-backup","Version history is not a backup. It cannot undo a deleted table.","Lovable and Bolt keep version history for your code. Your database is a separate service, so rolling back to this morning does not bring your data back.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":722,"title":723,"description":724,"published":725,"category":497,"image":726,"draft":451},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Three ways to back up a Supabase database, and what each misses","The dashboard, pg_dump, and a managed service. What each one actually saves, what it quietly leaves out, and which one survives losing the account.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":728,"title":729,"description":730,"published":725,"category":447,"image":731,"draft":451},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Which API keys are safe in your frontend, and which aren't","Your Supabase anon key is supposed to be public. Your service_role key is not, and it ignores every rule you set. Here is how to tell them apart.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1790150951364]