[{"data":1,"prerenderedAt":1005},["ShallowReactive",2],{"blog-en-is-lovable-safe":3,"blog-index-en":771},{"id":4,"title":5,"body":6,"category":724,"cover":725,"coverAlt":726,"description":727,"draft":728,"extension":729,"faq":730,"image":749,"keywords":750,"meta":760,"navigation":761,"ogTitle":5,"path":762,"published":763,"seo":764,"stem":765,"tldr":766,"updated":763,"__hash__":770},"blog_en\u002Fblog\u002Fis-lovable-safe.md","Is Lovable safe? What 18,554 live Lovable apps showed",{"type":7,"value":8,"toc":707},"minimark",[9,13,21,24,29,32,35,57,60,66,70,83,220,223,228,240,247,251,254,264,275,287,290,301,305,308,314,319,340,347,351,354,361,367,374,386,390,393,400,407,410,414,417,420,426,429,433,436,439,533,541,554,561,565,568,576,580,583,618,631,635,638,641,652,663,671,675,699],[10,11,12],"p",{},"You built something on Lovable, it works, and you are about to put real people\non it. Somewhere in that week you typed \"is lovable safe\" into a search box, and\nwhat came back was either a page about a 2025 security disclosure or a vendor\nselling you a scan. Neither one said anything about the app you are about to\npublish.",[10,14,15,16,20],{},"Here is what most of those answers get wrong: ",[17,18,19],"strong",{},"\"is Lovable safe\" is three\nquestions wearing one sentence",", and the one that decides whether strangers can\nread your users' data is the one almost nobody measures.",[10,22,23],{},"We can measure it. Between 12 and 14 August 2026 we ran the same nine external\nchecks anyone can run free on our homepage over 30,998 live apps, and 18,554 of\nthem were published on Lovable. That is the largest cohort we have, three in\nevery five apps we have ever scanned. This is what came back for those, and\nwhere our view stops.",[25,26,28],"h2",{"id":27},"is-lovable-safe","Is Lovable safe?",[10,30,31],{},"As a platform, yes, and by a wider margin than we expected. Lovable's own output\nwas the cleanest of the five builders we measured. Everything that decided a\ngrade was inside the app its owner had built.",[10,33,34],{},"Think of it as a shop with a stockroom across the street. Lovable builds the\nshop: the windows, the counter, the sign. Supabase owns the stockroom, and it\nhas its own lock on its own door. What the shop hands a passer-by is one\nquestion. What the stockroom hands anyone who walks up and asks is a completely\ndifferent one, and no amount of tidying the shop changes it.",[36,37,38,45,51],"ol",{},[39,40,41,44],"li",{},[17,42,43],{},"The platform."," Does Lovable publish your app properly: a valid\ncertificate, a domain that will not lapse, nothing leaking from the build.\nThis is the shop.",[39,46,47,50],{},[17,48,49],{},"The agent."," Is the code Lovable's AI writes sound. No scan from outside\ncan see the wiring, and this post says so rather than guessing.",[39,52,53,56],{},[17,54,55],{},"The app you published."," What a stranger can reach from the pavement: a key\nin the code a browser downloads, a storage bucket that lists its files, a\ndatabase table that answers anyone who asks.",[10,58,59],{},"Our checks read the third and two parts of the first. On the platform, the\ncertificate was valid on all 18,486 apps where we could read one, and not one\ndomain out of 18,554 was near expiry. On the agent we have nothing to measure.\nOn the app, we have 18,554 answers.",[61,62],"diagram",{"alt":63,"caption":64,"src":65},"Three panels side by side. The first holds the Lovable logo with a padlock and a certificate beside it. The second holds a code glyph with a sparkle over it. The third holds a browser page with a separate database cylinder outside it, three visitors reaching toward both, and a magnifying glass drawn over that panel alone, with the numeral 18,554 beneath it.","Three questions inside one search. A scan from outside reads the third panel and part of the first, and nothing at all in the middle one.","\u002Fblog\u002Fis-lovable-safe\u002Fthree-questions-1600x700.png",[25,67,69],{"id":68},"what-we-found-in-18554-lovable-apps","What we found in 18,554 Lovable apps",[10,71,72,73,76,77,82],{},"Nine checks, run from outside, with no login and no access to anyone's account.\nWe never read a row: where a database answered, we asked how many rows it would\nhand over and stopped there. No app is named here or anywhere else we publish.\nEvery share below is of the apps that check ",[17,74,75],{},"answered"," on, because a check\nthat could not finish is unknown rather than passed, and that rule is why the\ndenominators move. The method and the data are\n",[78,79,81],"a",{"href":80},"\u002Fresearch\u002Fvibe-coded-app-security-2026","in the report",".",[84,85,86,103],"table",{},[87,88,89],"thead",{},[90,91,92,96,100],"tr",{},[93,94,95],"th",{},"What we checked",[93,97,99],{"align":98},"right","Lovable apps",[93,101,102],{},"Who decides it",[104,105,106,118,129,139,149,160,170,180,199,210],"tbody",{},[90,107,108,112,115],{},[109,110,111],"td",{},"Browser security headers missing",[109,113,114],{"align":98},"18,539 of 18,554 (99%)",[109,116,117],{},"Lovable's hosting",[90,119,120,123,126],{},[109,121,122],{},"A database table readable with no login",[109,124,125],{"align":98},"2,017 of 3,553 (57%)",[109,127,128],{},"Your app",[90,130,131,134,137],{},[109,132,133],{},"Something key-shaped in the code a visitor downloads",[109,135,136],{"align":98},"822 of 18,554 (4%)",[109,138,128],{},[90,140,141,144,147],{},[109,142,143],{},"A storage bucket that lists its files",[109,145,146],{"align":98},"768 of 16,565 (5%)",[109,148,128],{},[90,150,151,154,157],{},[109,152,153],{},"Original source code published (source maps)",[109,155,156],{"align":98},"225 of 18,553 (1%)",[109,158,159],{},"A build setting",[90,161,162,165,168],{},[109,163,164],{},"An API route that answered a stranger with data",[109,166,167],{"align":98},"8 of 18,518",[109,169,128],{},[90,171,172,175,178],{},[109,173,174],{},"Any website allowed to call your API",[109,176,177],{"align":98},"0 of 18,518",[109,179,128],{},[90,181,182,194,197],{},[109,183,184,185,189,190,193],{},"A private file such as ",[186,187,188],"code",{},".env"," or ",[186,191,192],{},".git\u002Fconfig"," at a public URL",[109,195,196],{"align":98},"0 of 18,442",[109,198,128],{},[90,200,201,204,207],{},[109,202,203],{},"Certificate expired or untrusted",[109,205,206],{"align":98},"0 of 18,486",[109,208,209],{},"Lovable",[90,211,212,215,218],{},[109,213,214],{},"Domain about to lapse",[109,216,217],{"align":98},"0 of 18,554",[109,219,209],{},[10,221,222],{},"The grades: 15,963 A, 370 B, 1,814 C, 402 D and 5 F. Nine apps had no finding at\nall.",[61,224],{"alt":225,"caption":226,"src":227},"Six horizontal bars on one scale, each headed by a small glyph and ending in a numeral: 18,539 for headers, 2,017 for exposed tables, 822 for keys, 768 for storage buckets, 225 for source maps and 8 for open routes. The top bar is drawn in a faint grey and the rest in teal, with the 8 drawn as a hairline with a ring around it.","Numbers of apps, not rates: one scale, six findings. The grey bar is decided by the hosting. Every teal bar followed from something in the app. The exposed-table row is measured against a smaller base, which the next picture takes apart.","\u002Fblog\u002Fis-lovable-safe\u002Fwhat-we-found-1600x680.png",[10,229,230,231,234,235,239],{},"That first row is the reason \"99% of Lovable apps have a security issue\" is a\nsentence you will see somewhere and should ignore. Browser security headers are\nsent by whatever serves your page, which on ",[186,232,233],{},"yourapp.lovable.app"," is Lovable,\nwhich is why every app on that host gets the same answer. It is\n",[78,236,238],{"href":237},"\u002Fblog\u002Fmissing-security-headers","worth having"," and it is not what a D is made\nof.",[10,241,242,243,246],{},"Leave that row out and ",[17,244,245],{},"15,453 of the 18,554 apps had nothing else at all",".\nThe remaining 3,092 are where the rest of this post lives.",[25,248,250],{"id":249},"what-lovable-gets-right-and-it-is-most-of-the-list","What Lovable gets right, and it is most of the list",[10,252,253],{},"Three of the numbers above are the best we have recorded on any builder, and\nthey are all decided by the platform rather than by you.",[10,255,256,259,260,82],{},[17,257,258],{},"Source maps."," 225 of 18,553 Lovable apps publish the original files behind\nthe app, comments and all. That is about 1 in 80. On Base44 the same check fires\non 59% of apps, and on Replit 6%. Lovable's production build does the right\nthing by default, so\n",[78,261,263],{"href":262},"\u002Fblog\u002Fsource-maps-exposed-in-production","this one is mostly not your problem",[10,265,266,269,270,274],{},[17,267,268],{},"Cross-origin headers."," Zero apps out of 18,518 told any website in the world\nthat it may call their API, and zero allowed that with the visitor's login\ncookies attached. That is the finding\n",[78,271,273],{"href":272},"\u002Fblog\u002Fcors-wildcard-security-risk","most likely to let another site act as your user",",\nand on Lovable it did not appear once.",[10,276,277,280,281,283,284,286],{},[17,278,279],{},"Stray private files."," Zero apps out of 18,442 served a ",[186,282,188],{}," or a\n",[186,285,192],{}," from a plain URL. A Lovable app has no server of its own to\nmisconfigure, so there is no file at the back to leave out.",[10,288,289],{},"None of that is faint praise. It is the part of the job you did not have to\nthink about, and on most other builders somebody does.",[291,292,294],"callout",{"type":293},"note",[10,295,296,297,82],{},"Free, no account, about 20 seconds: the scan on our homepage runs all nine of\nthese checks against your live app and prints \"Couldn't check\" for anything it\ncould not answer rather than a tick. ",[78,298,300],{"href":299},"\u002Fsecurity-scanner","Scan your app",[25,302,304],{"id":303},"the-one-number-that-matters-2017-of-3553","The one number that matters: 2,017 of 3,553",[10,306,307],{},"Of the Lovable apps whose Supabase database we could actually ask, 57% handed\nrows to a request carrying no login at all.",[10,309,310,311,82],{},"The denominators are worth walking, because this is the number everybody quotes\nand almost nobody scopes. Of 18,554 Lovable apps, 6,532 named a Supabase project\nin the code they ship. Of those, 3,553 answered our request well enough for us\nto judge, and the other 2,979 did not, so they are unknown rather than clean.\nOf the 3,553, ",[17,312,313],{},"2,017 returned rows to a stranger",[61,315],{"alt":316,"caption":317,"src":318},"A funnel drawn as four stacked bars narrowing left to right: 18,554 Lovable apps, 6,532 that named a Supabase project, 3,553 whose database gave a usable answer, and 2,017 that returned rows with no login. The last bar is drawn in red and the third is annotated with a question mark for the 2,979 that could not be judged.","Four denominators, not one. The bar that gets quoted as a headline is the last one, and it is measured against the third.","\u002Fblog\u002Fis-lovable-safe\u002Fwhere-it-lands-1600x620.png",[10,320,321,322,325,326,329,330,329,333,329,336,339],{},"In ",[17,323,324],{},"373"," of those apps the table that answered was named after people:\n",[186,327,328],{},"users",", ",[186,331,332],{},"profiles",[186,334,335],{},"orders",[186,337,338],{},"messages",". That is 373 apps, not 373 tables. In\nthe other 1,644 it was something we could not name from outside, which may be a\nproduct catalogue that was always meant to be public or may be anything else.",[10,341,342,343,346],{},"Measured against every Lovable app we scanned rather than the subset we could\njudge, 2,017 out of 18,554 is about ",[17,344,345],{},"11 in every 100",". Hold onto that figure\nfor two sections' time.",[25,348,350],{"id":349},"why-it-lands-on-the-database-and-not-on-lovable","Why it lands on the database and not on Lovable",[10,352,353],{},"Because of a design decision that is correct, deliberate, and almost never\nexplained to the person it affects.",[10,355,356,357,360],{},"A Lovable app has no server of its own. The page in the visitor's browser talks\nto Supabase directly, which is why the whole thing can be built in an afternoon\nand why so few of these apps have an open API route: there is no API of yours to\nleave open. For that to work, the address of your database and a key to it have\nto be printed inside the app, where anyone can read them. That key is the\n",[17,358,359],{},"publishable"," key, and it being public is correct. It is supposed to be there.",[10,362,363,364,366],{},"Which means the only thing between a stranger and your ",[186,365,328],{}," table is a\nper-table Supabase setting called Row Level Security. With it on and a policy\nwritten, the public key reads only the rows the policy allows. With it off, the\npublic key reads the table.",[10,368,369,370,373],{},"Now the part that decides most Lovable projects. Supabase turns Row Level\nSecurity on by default for tables you create by clicking around in the Table\nEditor. Tables created by ",[17,371,372],{},"running SQL"," do not get it, and running SQL is how\na builder creates tables for you. So the usual shape of a Lovable project is a\nfew tables you made by hand, which are protected, sitting beside the ones that\nwere generated for you, which may not be. Both look identical. Neither will\ncomplain. The app works perfectly either way, which is the whole problem:\nnothing you can see from the front tells you which kind you have.",[10,375,376,377,381,382,82],{},"The longer version of this, with the SQL,\n",[78,378,380],{"href":379},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","is here",", and the plain-language\nwalkthrough for this platform is\n",[78,383,385],{"href":384},"\u002Fis-your-lovable-app-safe","is your Lovable app safe",[25,387,389],{"id":388},"the-policy-that-clears-the-error-and-leaves-the-table-open","The policy that clears the error and leaves the table open",[10,391,392],{},"Turning Row Level Security on is step one of two, and the second step is where\nan AI assistant will helpfully do the wrong thing.",[10,394,395,396,399],{},"With the setting on and no policy written, your own app stops working. You get\nan error, you paste it into the chat, and something arrives that makes the error\ngo away. Very often what arrives is a policy that permits everybody, written as\n",[186,397,398],{},"using (true)",". It is a valid policy. It satisfies the requirement that a policy\nexist. It allows every row to every request.",[10,401,402,403,82],{},"The dashboard now reports the table as protected, the error is gone, your app\nworks, and the table is exactly as readable as it was before. We have a whole\narticle on this one because it is the single most convincing failure in the\nstack:\n",[78,404,406],{"href":405},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","RLS is on and your table is still public",[10,408,409],{},"If you have ever pasted a row-level-security error into a chat window and\naccepted the first fix that made it build, go and read that policy today.",[25,411,413],{"id":412},"cve-2025-48757-and-why-it-is-no-longer-your-question","CVE-2025-48757, and why it is no longer your question",[10,415,416],{},"It is real, it was serious, and it has been closed on Lovable's side for over a\nyear. It is also not the thing you should be checking for.",[10,418,419],{},"In May 2025 the security researcher Matt Palmer published CVE-2025-48757,\ncovering Lovable apps whose Supabase tables had Row Level Security missing or\nwritten too permissively. He scanned 1,645 Lovable apps and found 170 with\nexposed databases. Lovable's response was to add a security check that runs\nbefore you publish and warns you about unprotected tables.",[10,421,422,423],{},"Here is the honest reading, and it is why the CVE is the wrong frame. That\ndisclosure found roughly 10 exposed apps in every 100. Sixteen months later, on\na cohort eleven times the size, we found about 11 in every 100. The denominators\nare not identical and neither sample is the whole internet, so treat the two as\nthe same order of magnitude rather than as a precise comparison. The direction\nis clear enough: ",[17,424,425],{},"the rate did not fall.",[10,427,428],{},"That is not a fix that failed. It is a sign that this was never really a\nvulnerability in a product. It is a setting on your own tables, in your own\nSupabase project, which nobody else can turn on for you. A patch cannot reach\nit, which is exactly why a check you run yourself can.",[25,430,432],{"id":431},"what-the-822-keys-were-actually-made-of","What the 822 keys were actually made of",[10,434,435],{},"Almost all of them were fine, and a scanner that told you otherwise would be\ntraining you to ignore it.",[10,437,438],{},"822 of the 18,554 Lovable apps had something key-shaped in the code a visitor\ndownloads. Read as a list of shapes that is 4% of apps \"leaking secrets\". Read\nas what each key can actually do, it looks like this:",[84,440,441,454],{},[87,442,443],{},[90,444,445,448,451],{},[93,446,447],{},"What we found in the bundle",[93,449,450],{"align":98},"Apps",[93,452,453],{},"What it means",[104,455,456,467,478,489,499,509,522],{},[90,457,458,461,464],{},[109,459,460],{},"A Google API key",[109,462,463],{"align":98},"727",[109,465,466],{},"Usually correct, once restricted to your domain",[90,468,469,472,475],{},[109,470,471],{},"An unattributable secret",[109,473,474],{"align":98},"82",[109,476,477],{},"We could not tell you which provider it belongs to",[90,479,480,483,486],{},[109,481,482],{},"An OpenAI key",[109,484,485],{"align":98},"18",[109,487,488],{},"Bills your account, directly",[90,490,491,494,497],{},[109,492,493],{},"An AWS access key",[109,495,496],{"align":98},"7",[109,498,488],{},[90,500,501,504,507],{},[109,502,503],{},"An Anthropic key",[109,505,506],{"align":98},"3",[109,508,488],{},[90,510,511,517,519],{},[109,512,513,514],{},"A Supabase ",[186,515,516],{},"service_role",[109,518,506],{"align":98},[109,520,521],{},"Reads and writes every row in every table, ignoring every rule",[90,523,524,527,530],{},[109,525,526],{},"A live Stripe secret",[109,528,529],{"align":98},"2",[109,531,532],{},"Your payments account",[10,534,535,536,540],{},"The 727 Google keys are the reason we classify rather than match. A Google Maps\nkey in a browser is where it is supposed to be, and the fix is\n",[78,537,539],{"href":538},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","restricting it to your own domain","\nrather than panicking.",[10,542,543,544,546,547,549,550,82],{},"The bottom four rows are the ones that matter, and they are rare: 30 apps out of\n18,554. They are also the findings that cost money on their own, and they\nusually surface as a bill arriving before anyone noticed. Two details worth\nrecording. All three ",[186,545,516],{}," keys in the entire 30,998-app sweep were in\nLovable apps, and so were two of the three live Stripe secret keys. A\n",[186,548,516],{}," key in a browser makes every Row Level Security policy in your\nproject irrelevant in one line, which is why it is the one finding we grade\ncritical on sight and the one\n",[78,551,553],{"href":552},"\u002Fblog\u002Frotate-supabase-service-role-key","worth rotating the same day",[10,555,556,557,82],{},"Telling the two kinds apart takes about a minute, and\n",[78,558,560],{"href":559},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","we wrote the guide",[25,562,564],{"id":563},"the-768-storage-buckets-nobody-meant-to-open","The 768 storage buckets nobody meant to open",[10,566,567],{},"A Supabase bucket marked public does not only serve the files your app links to.\nIt will also list every file in it to anyone who asks.",[10,569,570,571,575],{},"768 of the 16,565 Lovable apps we could check had at least one bucket that\nlisted its contents. The reason this happens is the same as the reason tables\nend up readable: making a bucket public is how you get an image to appear, it\nworks immediately, and nothing afterwards tells you that the listing came with\nit. Uploaded invoices, ID photos and user avatars all end up in the same place.\n",[78,572,574],{"href":573},"\u002Fblog\u002Fsupabase-storage-bucket-public","What a public bucket actually exposes","\ncovers the fix, which is signed URLs rather than a private bucket you then\ncannot read from.",[25,577,579],{"id":578},"the-five-minute-check-on-your-own-lovable-app","The five-minute check on your own Lovable app",[10,581,582],{},"Each one is a page you open. Use a private window so your own login does not\nanswer for a stranger.",[36,584,585,591,597,603,609],{},[39,586,587,590],{},[17,588,589],{},"Supabase → Authentication → Policies."," Read down the list. Any table\nshowing Row Level Security disabled is readable by anyone with your project\naddress, which is printed in your app.",[39,592,593,596],{},[17,594,595],{},"Read the policies on the tables that do have it on."," If one of them\npermits everybody, the table is open and the dashboard still calls it\nprotected.",[39,598,599,602],{},[17,600,601],{},"Supabase → Storage."," Any bucket marked public lists its files to anyone.\nCheck what is in it before deciding that is fine.",[39,604,605,608],{},[17,606,607],{},"Supabase → Settings → API."," Confirm the key your app ships is the\npublishable one. If a secret key has ever been pasted into the project,\nrotate it there before deleting it from the code, because the old value still\nworks until you do.",[39,610,611,614,615,82],{},[17,612,613],{},"Or let the scan do it."," It runs those four from outside and five more,\ntakes about 20 seconds, needs no account, and shows you a grade and what\nproduced it: ",[78,616,617],{"href":299},"scan your app",[10,619,620,621,625,626,630],{},"If you would rather work through the whole surface as a list, the\n",[78,622,624],{"href":623},"\u002Fchecklist","10-minute security checklist"," covers what is worth confirming on\nany newly launched app, and\n",[78,627,629],{"href":628},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","can anyone read your Supabase database","\nis the test to run if you only do one thing.",[25,632,634],{"id":633},"your-app-changes-every-time-you-publish","Your app changes every time you publish",[10,636,637],{},"A scan you ran last month describes last month's app, and on Lovable that is a\nshorter month than most.",[10,639,640],{},"Publishing is one click, so a change is live the moment you accept it. There is\nno deploy step between you and the internet to catch a table that was added this\nmorning with Row Level Security off, or a key pasted into the chat to get past a\nfailing build at midnight. Every one of the 2,017 exposed databases we found\nbelonged to somebody whose app was working fine.",[10,642,643,647,648,651],{},[78,644,646],{"href":645},"\u002Fpricing","Reeve Monitor"," is the version of this post that runs itself. It\nre-runs all nine checks every hour on up to three apps, watches whether the app\nis up every 60 seconds, tells you when a result ",[17,649,650],{},"changes"," rather than waiting\nfor you to look, and sends a monthly report. It is $12 a month at list, with\nseven days free before it charges you; the pricing page is sometimes below the\nfigure here and never above it.",[10,653,654,657,658,662],{},[17,655,656],{},"If your Lovable app uses Supabase, and 6,532 of the 18,554 we scanned do, the\nother half of the problem is the copy."," An exposed table is a thing a stranger\ncan read. An agent with database access, or a migration that ran the wrong way,\nis a thing that can delete it, and Supabase's own daily backup on the free tier\nis not something you can restore from yourself.\n",[78,659,661],{"href":660},"\u002Fsupabase-backups","Reeve Care"," takes an encrypted copy of your Supabase\ndatabase every night, keeps it somewhere your project cannot reach, verifies\nthat each copy actually restores, and gives you a one-click restore when you\nneed it. It includes everything Monitor does. Care is $49 a month at list for\none app, with the same seven days free.",[10,664,665,666,670],{},"The shape of that second failure, told by someone it happened to, is\n",[78,667,669],{"href":668},"\u002Fblog\u002Fai-agent-deleted-my-database","the day an AI agent deleted a production database",".\nNothing in this article's nine checks would have helped there. A copy would\nhave.",[25,672,674],{"id":673},"what-to-do-this-week","What to do this week",[676,677,678],"key-takeaways",{},[679,680,681,684,687,690,696],"ul",{},[39,682,683],{},"Open Supabase → Authentication → Policies and read the list. Any table with Row Level Security disabled is readable by anyone who has your app's address.",[39,685,686],{},"Read the policies on the tables that do have it on. One that permits everybody leaves the table open while the dashboard reports it as protected.",[39,688,689],{},"Check Storage for public buckets. A public bucket lists every file in it, not only the ones your app links to.",[39,691,692,693,695],{},"Confirm the key in your app is the publishable one. A ",[186,694,516],{}," key in the browser makes every policy you have written irrelevant, and it is the same-day job.",[39,697,698],{},"Keep a copy of your database somewhere your project and your agent cannot reach, and check that the copy restores.",[10,700,701,702,706],{},"Lovable did its half well. The 2,017 is the half that is yours, and it is a\nsetting rather than a rewrite. If you want the cross-builder comparison instead,\n",[78,703,705],{"href":704},"\u002Fblog\u002Fsafest-ai-app-builder","which AI app builder is safest"," has the table for\nall five.",{"title":708,"searchDepth":709,"depth":709,"links":710},"",3,[711,713,714,715,716,717,718,719,720,721,722,723],{"id":27,"depth":712,"text":28},2,{"id":68,"depth":712,"text":69},{"id":249,"depth":712,"text":250},{"id":303,"depth":712,"text":304},{"id":349,"depth":712,"text":350},{"id":388,"depth":712,"text":389},{"id":412,"depth":712,"text":413},{"id":431,"depth":712,"text":432},{"id":563,"depth":712,"text":564},{"id":578,"depth":712,"text":579},{"id":633,"depth":712,"text":634},{"id":673,"depth":712,"text":674},"Security basics","\u002Fblog\u002Fis-lovable-safe\u002Fcover-1200x630.png","The Lovable logo on a white tile, an arrow to a published app, an arrow on to three visitors, and a database hanging below the app.","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.",false,"md",[731,734,737,740,743,746],{"q":732,"a":733},"Is Lovable safe to use for a real product?","The platform side was the cleanest of the five builders we scanned. Every certificate we could read was valid, no domain was near lapsing, no app allowed any website in the world to call its API, and 225 of 18,553 published their source code. What decides whether your product is safe to run there is the database behind it: 2,017 of the 3,553 Lovable apps whose Supabase we could ask handed rows to a request with no login. That is a setting on your tables, it is yours to change, and you can check it in about five minutes.",{"q":735,"a":736},"Can people see my Lovable source code?","They can always read the browser half, because a browser cannot draw a page it was not sent. What they normally cannot read is your original files with their comments and variable names, which is what a published source map gives away. 225 of the 18,553 Lovable apps we checked were publishing one, about 1 in 80, which is the lowest rate of any builder we measured. Your database queries are a different matter: a Lovable app talks to Supabase straight from the browser, so the table names and columns it reads are visible to anyone who opens the network tab.",{"q":738,"a":739},"Is my Supabase data safe in a Lovable app?","It depends on one per-table setting and nothing else. A Lovable app reaches Supabase directly from the visitor browser using a publishable key that is meant to be public, so the only thing standing between a stranger and a table is Row Level Security. With it off, that public key reads the whole table. We measured this on 3,553 Lovable apps and 2,017 of them answered an anonymous request with rows. In 373 of those the exposed table was named after people: users, profiles, orders, messages.",{"q":741,"a":742},"What was CVE-2025-48757 and does it still affect me?","It is the 2025 disclosure by security researcher Matt Palmer covering Lovable apps whose Supabase tables had Row Level Security missing or written too permissively. He scanned 1,645 Lovable apps and found 170 with exposed databases. Lovable responded by adding a security check that runs before you publish. It is not a patch you are waiting for and never was, because the exposure is a setting on your own tables rather than a defect in Lovable code, which is why our 2026 numbers look so much like his 2025 ones. Whether it affects you is answerable today by opening one page in Supabase.",{"q":744,"a":745},"Does Lovable security scan catch an exposed table?","Lovable runs a check before you publish that reads your project from the inside: the schema, the policies, the dependencies. That sees things an outside scan structurally cannot, such as a table your front end never names. What it cannot prove is that a policy actually holds, because a policy can exist, read as valid and still return every row to everybody. The two views answer different questions, so run the inside one before publishing and an outside one afterwards, and treat a disagreement between them as the outside answer winning.",{"q":747,"a":748},"Is Lovable safer than Bolt or Replit?","On the things the platform decides, Lovable came out ahead of the four others we measured: fewer published source maps than any of them, no open cross-origin headers at all, and no certificate or domain problems. On the things the owner decides it looks the same as everywhere else, because those findings follow from how an app was built rather than from where it was built. We put the full comparison in a separate article rather than repeating the table here.","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",[751,752,753,754,755,756,757,758,759],"is lovable safe","lovable security","is lovable secure","are lovable apps safe","lovable supabase security","lovable rls","is lovable safe for production","lovable security issues","lovable data breach",{},true,"\u002Fblog\u002Fis-lovable-safe","2026-09-21",{"title":5,"description":727},"blog\u002Fis-lovable-safe",[767,768,769],"Is Lovable safe? The platform was the cleanest of the five builders we measured. 225 of 18,553 apps published their source code, not one told any website it could call its API, and 15,963 of 18,554 graded A.","Everything serious we found was inside the app its owner built. Of the 3,553 Lovable apps whose Supabase database we could actually ask, 2,017 handed rows to a request with no login.","That is about 11 in every 100 Lovable apps we scanned. A researcher measuring the same thing in May 2025 found 10 in 100, so sixteen months later the rate has not moved.","ZST9AXZEDZg05JiaWbLPp2ZqZyT81e0MY25X-lfcsxQ",[772,779,785,786,792,798,804,810,816,822,828,834,840,845,850,856,861,867,873,879,884,890,896,902,908,914,920,926,932,937,943,949,954,959,964,969,973,979,985,990,995,1001],{"path":773,"title":774,"description":775,"published":776,"category":777,"image":778,"draft":728},"\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":780,"title":781,"description":782,"published":783,"category":724,"image":784,"draft":728},"\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":762,"title":5,"description":727,"published":763,"category":724,"image":749,"draft":728},{"path":787,"title":788,"description":789,"published":790,"category":724,"image":791,"draft":728},"\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":793,"title":794,"description":795,"published":796,"category":724,"image":797,"draft":728},"\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":799,"title":800,"description":801,"published":802,"category":724,"image":803,"draft":728},"\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":805,"title":806,"description":807,"published":808,"category":724,"image":809,"draft":728},"\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":811,"title":812,"description":813,"published":814,"category":724,"image":815,"draft":728},"\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":817,"title":818,"description":819,"published":820,"category":724,"image":821,"draft":728},"\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":823,"title":824,"description":825,"published":826,"category":777,"image":827,"draft":728},"\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":829,"title":830,"description":831,"published":832,"category":777,"image":833,"draft":728},"\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":835,"title":836,"description":837,"published":838,"category":777,"image":839,"draft":728},"\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":704,"title":841,"description":842,"published":843,"category":724,"image":844,"draft":728},"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":379,"title":846,"description":847,"published":848,"category":724,"image":849,"draft":728},"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":851,"title":852,"description":853,"published":854,"category":724,"image":855,"draft":728},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": what the warning misses","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.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":552,"title":857,"description":858,"published":859,"category":724,"image":860,"draft":728},"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":862,"title":863,"description":864,"published":865,"category":724,"image":866,"draft":728},"\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":868,"title":869,"description":870,"published":871,"category":724,"image":872,"draft":728},"\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":874,"title":875,"description":876,"published":877,"category":724,"image":878,"draft":728},"\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":237,"title":880,"description":881,"published":882,"category":724,"image":883,"draft":728},"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":885,"title":886,"description":887,"published":888,"category":724,"image":889,"draft":728},"\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":891,"title":892,"description":893,"published":894,"category":724,"image":895,"draft":728},"\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":897,"title":898,"description":899,"published":900,"category":777,"image":901,"draft":728},"\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":903,"title":904,"description":905,"published":906,"category":724,"image":907,"draft":728},"\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":909,"title":910,"description":911,"published":912,"category":777,"image":913,"draft":728},"\u002Fblog\u002Fback-up-supabase-free-tier","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":915,"title":916,"description":917,"published":918,"category":724,"image":919,"draft":728},"\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":921,"title":922,"description":923,"published":924,"category":724,"image":925,"draft":728},"\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":927,"title":928,"description":929,"published":930,"category":724,"image":931,"draft":728},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","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":272,"title":933,"description":934,"published":935,"category":724,"image":936,"draft":728},"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":938,"title":939,"description":940,"published":941,"category":777,"image":942,"draft":728},"\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":944,"title":945,"description":946,"published":947,"category":777,"image":948,"draft":728},"\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":573,"title":950,"description":951,"published":952,"category":724,"image":953,"draft":728},"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":538,"title":955,"description":956,"published":957,"category":724,"image":958,"draft":728},"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":668,"title":960,"description":961,"published":962,"category":777,"image":963,"draft":728},"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":628,"title":965,"description":966,"published":967,"category":724,"image":968,"draft":728},"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":262,"title":970,"description":971,"published":967,"category":724,"image":972,"draft":728},"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":974,"title":975,"description":976,"published":977,"category":724,"image":978,"draft":728},"\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":980,"title":981,"description":982,"published":983,"category":777,"image":984,"draft":728},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","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":405,"title":986,"description":987,"published":988,"category":724,"image":989,"draft":728},"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":991,"title":992,"description":993,"published":988,"category":777,"image":994,"draft":728},"\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":996,"title":997,"description":998,"published":999,"category":777,"image":1000,"draft":728},"\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":559,"title":1002,"description":1003,"published":999,"category":724,"image":1004,"draft":728},"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]