[{"data":1,"prerenderedAt":1086},["ShallowReactive",2],{"blog-en-is-bolt-safe":3,"blog-index-en":736},{"id":4,"title":5,"body":6,"category":694,"cover":695,"coverAlt":696,"description":697,"draft":698,"extension":699,"faq":700,"image":715,"keywords":716,"meta":725,"navigation":726,"ogTitle":5,"path":727,"published":728,"seo":729,"stem":730,"tldr":731,"updated":728,"__hash__":735},"blog_en\u002Fblog\u002Fis-bolt-safe.md","Is Bolt safe? What 1,123 live Bolt apps showed",{"type":7,"value":8,"toc":678},"minimark",[9,18,26,29,34,37,40,62,65,69,82,218,221,227,243,247,250,260,271,283,286,297,301,304,307,367,374,382,389,394,398,401,404,426,434,438,441,444,449,459,463,466,469,485,492,496,499,506,513,516,520,523,560,564,570,579,598,601,612,629,632,640,644,667],[10,11,12,13,17],"p",{},"You built something on Bolt, pressed Publish, and now it lives at an address\nending in ",[14,15,16],"code",{},"bolt.host",". Before you send that link to real customers you typed\n\"is bolt safe\" into a search box, and what came back was a list of five\nvulnerabilities said to be in almost every Bolt app, with a scanner for sale at\nthe bottom.",[10,19,20,21,25],{},"Here is what those lists get wrong: ",[22,23,24],"strong",{},"they rank every risk the same, and on live\nBolt apps most of them barely appear."," Source maps, open cross-origin headers\nand unprotected API routes sit on those lists as equals of leaked keys and open\ntables. In our data the first three turned up on 13, 1 and 4 apps out of more\nthan a thousand. The other two are where the findings were.",[10,27,28],{},"Between 12 and 14 August 2026 we ran the same nine external checks anyone can\nrun free on our homepage over 30,998 live apps, and 1,123 of them were published\non Bolt's own hosting. This is what came back for those, and where our view\nstops.",[30,31,33],"h2",{"id":32},"is-bolt-safe","Is Bolt safe?",[10,35,36],{},"On everything Bolt itself decides, yes. Its hosting came back as clean as\nLovable's, and everything that lowered a grade sat inside an app its owner had\nbuilt.",[10,38,39],{},"Think of a Bolt app as a shop. Bolt puts up the building: the address, the\ncertificate, the hosting. You fill the shop window, which is every page, image\nand script your app hands to a visitor, and anyone walking past can read\nwhatever is in it. Behind the shop is the stockroom, your database, with its own\ndoor and its own lock. \"Is Bolt safe\" is really three questions, one about each.",[41,42,43,50,56],"ol",{},[44,45,46,49],"li",{},[22,47,48],{},"The building."," Does Bolt publish your app properly: a valid certificate, a\ndomain that will not lapse, nothing stray left at a public address. This is\nBolt's job.",[44,51,52,55],{},[22,53,54],{},"The window."," What a visitor's browser downloads. A key left in it can be\nread by anyone who looks, however it was put there.",[44,57,58,61],{},[22,59,60],{},"The stockroom."," Whether your database answers a stranger who walks round\nthe back and asks. That depends on a lock you set, table by table.",[10,63,64],{},"Our checks read all three from outside. None of them reads the code Bolt's agent\nwrote the way you would read it in the editor, and this post does not guess at\nit.",[30,66,68],{"id":67},"what-we-found-in-1123-bolt-apps","What we found in 1,123 Bolt apps",[10,70,71,72,75,76,81],{},"Nine checks, run from outside, with no login and no access to anyone's account.\nWhere a database answered, we asked how many rows it would hand over and stopped\nthere; we never read one. No app is named here or anywhere else we publish.\nEvery share below is of the apps that check ",[22,73,74],{},"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",[77,78,80],"a",{"href":79},"\u002Fresearch\u002Fvibe-coded-app-security-2026","in the report",".",[83,84,85,102],"table",{},[86,87,88],"thead",{},[89,90,91,95,99],"tr",{},[92,93,94],"th",{},"What we checked",[92,96,98],{"align":97},"right","Bolt apps",[92,100,101],{},"Who decides it",[103,104,105,117,128,138,149,159,169,179,197,208],"tbody",{},[89,106,107,111,114],{},[108,109,110],"td",{},"Browser security headers missing",[108,112,113],{"align":97},"1,121 of 1,123",[108,115,116],{},"Bolt's hosting",[89,118,119,122,125],{},[108,120,121],{},"Something key-shaped in the code a visitor downloads",[108,123,124],{"align":97},"75 of 1,123 (7%)",[108,126,127],{},"Your app",[89,129,130,133,136],{},[108,131,132],{},"A database table readable with no login",[108,134,135],{"align":97},"27 of 35",[108,137,127],{},[89,139,140,143,146],{},[108,141,142],{},"Original source code published (source maps)",[108,144,145],{"align":97},"13 of 1,123 (1%)",[108,147,148],{},"A build setting",[89,150,151,154,157],{},[108,152,153],{},"A storage bucket that lists its files",[108,155,156],{"align":97},"6 of 901",[108,158,127],{},[89,160,161,164,167],{},[108,162,163],{},"An API route that answered a stranger with data",[108,165,166],{"align":97},"4 of 1,120",[108,168,127],{},[89,170,171,174,177],{},[108,172,173],{},"Any website allowed to call your API",[108,175,176],{"align":97},"1 of 1,120",[108,178,127],{},[89,180,181,192,195],{},[108,182,183,184,187,188,191],{},"A private file such as ",[14,185,186],{},".env"," or ",[14,189,190],{},".git\u002Fconfig"," at a public URL",[108,193,194],{"align":97},"0 of 1,109",[108,196,127],{},[89,198,199,202,205],{},[108,200,201],{},"Certificate expired or untrusted",[108,203,204],{"align":97},"0 of 1,119",[108,206,207],{},"Bolt",[89,209,210,213,216],{},[108,211,212],{},"Domain about to lapse",[108,214,215],{"align":97},"0 of 1,123",[108,217,207],{},[10,219,220],{},"The grades: 1,051 A, 33 B, 24 C, 15 D and no F at all.",[222,223],"diagram",{"alt":224,"caption":225,"src":226},"Seven horizontal bars on one scale, each headed by a small glyph and ending in a numeral: 1,121 for headers, 75 for keys, 27 for readable tables, 13 for source maps, 6 for storage buckets, 4 for open routes and 1 for the open cross-origin header. The top bar is long and faint grey, the rest are short teal bars, and the last three are hairlines with a ring around them.","Numbers of apps on one scale. The grey bar is decided by Bolt's hosting. Every teal bar followed from something inside the app, and the readable-table row is measured against a much smaller base, which a later picture takes apart.","\u002Fblog\u002Fis-bolt-safe\u002Fwhat-we-found-1600x720.png",[10,228,229,230,233,234,238,239,242],{},"That first row is decided by whoever serves your pages, which on\n",[14,231,232],{},"yourapp.bolt.host"," is Bolt, so 1,121 apps got the same answer. Headers are\n",[77,235,237],{"href":236},"\u002Fblog\u002Fmissing-security-headers","worth having"," and they are not what a D is\nmade of. Leave that row out and ",[22,240,241],{},"1,008 of the 1,123 Bolt apps had nothing else\nat all",". The other 115 are what the rest of this post is about.",[30,244,246],{"id":245},"what-bolt-gets-right","What Bolt gets right",[10,248,249],{},"The checks Bolt decides came back almost empty, and on the one build setting we\nmeasure it matched Lovable.",[10,251,252,255,256,81],{},[22,253,254],{},"Source maps."," 13 of 1,123 Bolt apps publish the original files behind the\napp, comments and all. That is a little over one in a hundred, about the same\nrate as Lovable's 225 of 18,553, and\n",[77,257,259],{"href":258},"\u002Fblog\u002Fsource-maps-exposed-in-production","a map gives away more than people expect",[10,261,262,265,266,270],{},[22,263,264],{},"Cross-origin headers."," One app out of 1,120 told every website in the world\nthat it may call its API. That is the finding\n",[77,267,269],{"href":268},"\u002Fblog\u002Fcors-wildcard-security-risk","most likely to let another site act as your user",",\nand on Bolt it appeared once.",[10,272,273,276,277,279,280,282],{},[22,274,275],{},"The building itself."," The certificate was valid on all 1,119 apps where we\ncould read one, no domain out of 1,123 was close to lapsing, and no app served a\n",[14,278,186],{}," file or a ",[14,281,190],{}," from a plain address.",[10,284,285],{},"None of that needed anything from you, and on some other builders it does.",[287,288,290],"callout",{"type":289},"note",[10,291,292,293,81],{},"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. ",[77,294,296],{"href":295},"\u002Fsecurity-scanner","Scan your app",[30,298,300],{"id":299},"what-the-75-keys-were-made-of","What the 75 keys were made of",[10,302,303],{},"Most of them were fine, and the few that were not are the most expensive thing\nin this post.",[10,305,306],{},"75 of the 1,123 Bolt apps had something key-shaped in the code a visitor\ndownloads. Counted as shapes, that is 7% of Bolt apps \"leaking secrets\". Counted\nby what each key can do, it splits like this, with each app counted once under\nthe most serious thing in it:",[83,308,309,322],{},[86,310,311],{},[89,312,313,316,319],{},[92,314,315],{},"What we found in the bundle",[92,317,318],{"align":97},"Apps",[92,320,321],{},"What it means",[103,323,324,335,346,357],{},[89,325,326,329,332],{},[108,327,328],{},"A Google API key, and nothing else",[108,330,331],{"align":97},"38",[108,333,334],{},"Usually correct, once restricted to your domain",[89,336,337,340,343],{},[108,338,339],{},"A secret we could not attribute",[108,341,342],{"align":97},"26",[108,344,345],{},"We could not tell which provider it belongs to",[89,347,348,351,354],{},[108,349,350],{},"An OpenAI key",[108,352,353],{"align":97},"10",[108,355,356],{},"Bills your account, directly",[89,358,359,362,365],{},[108,360,361],{},"An Anthropic key",[108,363,364],{"align":97},"1",[108,366,356],{},[10,368,369,370,81],{},"The 38 Google keys are the reason we classify every key instead of matching a\npattern. A Google Maps key in a browser is where it is supposed to be, and the\nfix is ",[77,371,373],{"href":372},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","restricting it to your own domain",[10,375,376,377,381],{},"The ten OpenAI keys are the opposite case. An OpenAI key is a bearer token:\nwhoever holds it can spend it, from anywhere, and OpenAI offers no setting that\nties a key to your site. All ten of those apps graded D, because one critical\nfinding caps the grade whatever else the app got right.\n",[77,378,380],{"href":379},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","What to do about one, in order","\nstarts with rotating it today.",[10,383,384,385,388],{},"Here is the number that makes this the Bolt finding. Bolt apps were under 4 in\nevery 100 apps we scanned, and they carried ",[22,386,387],{},"10 of the 33 OpenAI keys"," we\nfound anywhere. Put per app, that is about one Bolt app in 110, against 18 of\nthe 18,554 Lovable apps, about one in a thousand. Ten apps is a small sample,\nand a handful either way would move that ratio a long way. It would still leave\nBolt ahead of every other builder we measured.",[222,390],{"alt":391,"caption":392,"src":393},"Two bars of equal length, one above the other, each headed by a glyph. The upper bar stands for 30,998 scanned apps and has a thin teal slice at its left end marked 1,123 with the Bolt logo beside it. The lower bar stands for 33 OpenAI keys and has a red slice nearly a third of its length marked 10.","Bolt was a thin slice of the apps we scanned and close to a third of the OpenAI keys we found. The counts are small, which is why both are printed rather than turned into a rate.","\u002Fblog\u002Fis-bolt-safe\u002Fshare-of-openai-keys-1600x620.png",[30,395,397],{"id":396},"why-do-bolt-apps-leak-api-keys","Why do Bolt apps leak API keys?",[10,399,400],{},"We cannot see from outside how any one of those ten keys got there, and Bolt's\nown instructions say none of them should have.",[10,402,403],{},"Bolt's documentation describes the intended path. Ask the agent to integrate\nOpenAI and, in the documentation's words, it will \"complete the coding and then\ndisplay a message asking you to add your secret\". That secret goes in the\nSecrets panel, where only a server function can read it. A server function runs\non Bolt's side, so the visitor's browser never receives the key. Built that way,\nthe key stays in the stockroom.",[10,405,406,407,410,411,414,415,418,419,421,422,425],{},"The route around it that we can name is the environment variable. Bolt's own\nintroduction to databases says that environment variables keep these values\nprivate, and two of the three names it lists, ",[14,408,409],{},"VITE_SUPABASE_URL"," and\n",[14,412,413],{},"VITE_SUPABASE_ANON_KEY",", start with ",[14,416,417],{},"VITE_",". That prefix belongs to Vite, the\nbuild tool, and Vite's documentation says the opposite about it: a ",[14,420,417],{},"\nvariable is written into the code the browser downloads, and it should never\nhold an API key. For those two names that is harmless, because a project address\nand a publishable key are meant to be public. Copy the same pattern for\n",[14,423,424],{},"VITE_OPENAI_API_KEY"," and the key is sitting in the window.",[10,427,428,429,433],{},"A key pasted into the chat while you were fixing something else can also end up\nwritten straight into a page. Either way the result is the same file.\n",[77,430,432],{"href":431},"\u002Fblog\u002Fvite-and-next-public-env-vars","How the prefix works"," covers which values\nbelong behind it and which never do.",[30,435,437],{"id":436},"_27-of-35-the-bolt-databases-we-could-ask","27 of 35: the Bolt databases we could ask",[10,439,440],{},"Of the Bolt databases that gave us a usable answer, 27 of 35 handed rows to a\nrequest carrying no login at all. That is a count, and the base is too small to\nprint as a percentage.",[10,442,443],{},"The denominators matter more here than anywhere else in this post. 266 of the\n1,123 Bolt apps named a Supabase project in the code they ship. Only 35 of those\nanswered our request well enough for us to judge. The other 231 could not be\njudged, which makes them unknown, and we have counted them as neither clean nor\nexposed.",[222,445],{"alt":446,"caption":447,"src":448},"Four stacked bars narrowing from left to right on one scale: 1,123 Bolt apps, 266 that named a Supabase project, 35 whose database gave a usable answer, and 27 that returned rows with no login. The third bar continues as a dashed outline out to the width of the second, marked with a question mark and the numeral 231. The last bar is red.","Four denominators. The 27 is measured against the 35, and the 231 we could not judge are drawn as unknown rather than left out.","\u002Fblog\u002Fis-bolt-safe\u002Fwhere-it-lands-1600x620.png",[10,450,451,452,187,455,458],{},"In 4 of the 27 the table that answered was named the way tables about people are\nnamed, such as ",[14,453,454],{},"users",[14,456,457],{},"profiles",". Those four and the eleven apps with an\nOpenAI or Anthropic key make up all 15 of the D grades. In the other 23 it was a\ntable we could not name from outside, which may be a product list that was always\nmeant to be public or may be anything else.",[30,460,462],{"id":461},"why-it-lands-on-the-database","Why it lands on the database",[10,464,465],{},"Because the stockroom's address is printed in the window, and it has to be.",[10,467,468],{},"When a Bolt app reads its data from the page, the page needs the address of the\ndatabase and a publishable key, so both travel to every visitor. That key being\npublic is correct; it is how your own app gets in. What decides what the key gets\nback is a per-table 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, it\nreads the table.",[10,470,471,472,475,476,479,480,484],{},"Supabase turns row-level security on by default for tables you create by\nclicking around in its Table Editor. Tables created by ",[22,473,474],{},"running SQL"," do not\nget it, and running SQL is how a builder creates tables for you. Turning it on\nis also only step one, because the policy an assistant writes to clear a\npermissions error is often ",[14,477,478],{},"using (true)",", which permits everybody while\nthe dashboard reports the table as protected.\n",[77,481,483],{"href":482},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","RLS is on and your table is still public","\nis the whole of that story.",[10,486,487,488,81],{},"Bolt's own database check looks for exactly this: its documentation describes\nit as finding \"a missing row-level security (RLS) policy or a permission that's\ntoo open\". The plain-language walkthrough for this platform is\n",[77,489,491],{"href":490},"\u002Fis-your-bolt-app-safe","is your Bolt app safe",[30,493,495],{"id":494},"what-bolts-own-security-audit-checks","What Bolt's own security audit checks",[10,497,498],{},"It reads your project from the inside, and it runs when you press the button.",[10,500,501,502,505],{},"Bolt announced the audit on 30 July 2026. On a paid plan it sits in the Publish\nmenu as ",[22,503,504],{},"Run security audit",": it reviews your code and your database, fixes\nmost problems itself, flags the rest, and does not spend your tokens. On every\nplan, including Free, the settings of a Bolt database have a Security section\nthat runs the row-level security check described above.",[10,507,508,509,512],{},"Our scan ran two weeks after that button appeared, so the numbers above cannot\nsay how much it has changed since. What we can say is how the two views fit\ntogether. The audit sees your project from the inside, including tables your\npages never mention, which a scan from outside never can. A scan from outside\nsees what a stranger gets from the published app. When an audit finishes, the\nbutton reads ",[22,510,511],{},"Security audit up to date",", and the next change you publish is\none it has not seen.",[10,514,515],{},"Run the audit before you publish and look from outside afterwards. If the two\never disagree about whether a table is readable, go with the outside answer,\nbecause that is the one a stranger gets.",[30,517,519],{"id":518},"how-to-check-your-own-bolt-app","How to check your own Bolt app",[10,521,522],{},"Five things to look at. Use a private window, so your own login does not answer\nfor a stranger.",[41,524,525,531,537,545,551],{},[44,526,527,530],{},[22,528,529],{},"Find out which database you have."," New Bolt projects use a Bolt database\nby default. If you picked Supabase when you created the project, or connected\none later, your tables live in a Supabase project you can sign in to.",[44,532,533,536],{},[22,534,535],{},"Read the lock on every table."," With a Bolt database, open the Security\nsection of your database settings and run the check. With Supabase, open\nAuthentication → Policies and read down the list: a table with row-level\nsecurity disabled is readable by anyone who has your project address, and\nthat address is in your app. A policy that permits everybody counts as\ndisabled.",[44,538,539,544],{},[22,540,541,542,81],{},"Search your project for ",[14,543,417],{}," Every value behind that prefix is in the\nwindow. A project address and a publishable key belong there. A key that\nbills you belongs in the Secrets panel, read by a server function. If one has\never sat behind the prefix, rotate it with the provider first, because the\nold value keeps working until you do.",[44,546,547,550],{},[22,548,549],{},"Look at your storage."," A bucket marked public will list every file in it\nto anyone who asks, including the ones your app never shows.",[44,552,553,556,557,81],{},[22,554,555],{},"Or let the scan do it."," It runs these from outside along with five more\nchecks, takes about 20 seconds, needs no account, and shows you a grade and\nwhat produced it: ",[77,558,559],{"href":295},"scan your app free",[30,561,563],{"id":562},"keeping-it-that-way-after-you-publish","Keeping it that way after you publish",[10,565,566,569],{},[22,567,568],{},"A check you ran last month describes last month's app."," On Bolt, publishing\nis one button, so a table added this morning or a key pasted in at midnight is\nlive the moment you press it.",[10,571,572],{},[22,573,574,578],{},[77,575,577],{"href":576},"\u002Fpricing","Reeve Monitor"," runs the nine checks again for you:",[580,581,582,585,588,595],"ul",{},[44,583,584],{},"all nine checks every hour, on up to three apps",[44,586,587],{},"whether the app is up, every 60 seconds",[44,589,590,591,594],{},"a message when a result ",[22,592,593],{},"changes",", so a new finding does not wait for you to look",[44,596,597],{},"a monthly report of what it saw",[10,599,600],{},"Monitor is $12 a month at list, with seven days free before it charges you. The\npricing page is sometimes below the figure here and never above it.",[10,602,603,611],{},[22,604,605,606,610],{},"If your Bolt app keeps its data in your own Supabase project,\n",[77,607,609],{"href":608},"\u002Fsupabase-backups","Reeve Care"," keeps a copy of it."," That includes a project\nyou connected from the start and a Bolt database you have claimed into Supabase.",[580,613,614,617,620,623,626],{},[44,615,616],{},"an encrypted copy of your Supabase database every night, kept where your project cannot reach it",[44,618,619],{},"each copy verified before it counts, by counting the rows in every table",[44,621,622],{},"a one-click restore when you need one",[44,624,625],{},"your uploaded files as well, once you connect a Storage credential",[44,627,628],{},"everything Monitor does",[10,630,631],{},"Care is $49 a month at list for one app, with the same seven days free.",[10,633,634,635,639],{},"An open table is a thing a stranger can read. A migration that ran the wrong\nway, or an agent with database access, is a thing that can empty it, and none of\nthe nine checks in this post would bring the rows back.\n",[77,636,638],{"href":637},"\u002Fblog\u002Fai-agent-deleted-my-database","The day an AI agent deleted a production database","\nis what that looks like from the inside.",[30,641,643],{"id":642},"what-to-do-this-week","What to do this week",[645,646,647],"key-takeaways",{},[580,648,649,655,658,661,664],{},[44,650,651,652,654],{},"Search your Bolt project for ",[14,653,417],{}," and read every value behind it. A key that bills you belongs in the Secrets panel, read by a server function.",[44,656,657],{},"If an OpenAI key or any other paid key was ever in that list, rotate it with the provider before you remove it from the code.",[44,659,660],{},"Run the database security check, or open Authentication → Policies in Supabase, and read the lock on every table. A policy that permits everybody leaves the table open.",[44,662,663],{},"Run Bolt's own audit before you publish, then check the published app from outside.",[44,665,666],{},"Keep a copy of your database somewhere your project and your agent cannot reach, and check that the copy restores.",[10,668,669,670,672,673,677],{},"Start with the ",[14,671,417],{}," search, because it is the one finding on Bolt that costs\nmoney by itself. If you are still choosing between builders,\n",[77,674,676],{"href":675},"\u002Fblog\u002Fsafest-ai-app-builder","which AI app builder is safest"," puts all five side\nby side.",{"title":679,"searchDepth":680,"depth":680,"links":681},"",3,[682,684,685,686,687,688,689,690,691,692,693],{"id":32,"depth":683,"text":33},2,{"id":67,"depth":683,"text":68},{"id":245,"depth":683,"text":246},{"id":299,"depth":683,"text":300},{"id":396,"depth":683,"text":397},{"id":436,"depth":683,"text":437},{"id":461,"depth":683,"text":462},{"id":494,"depth":683,"text":495},{"id":518,"depth":683,"text":519},{"id":562,"depth":683,"text":563},{"id":642,"depth":683,"text":643},"Security basics","\u002Fblog\u002Fis-bolt-safe\u002Fcover-1200x630.png","An app drawn as a shop window with the Bolt logo for a sign, one red key lying in it, a locked database behind it and a visitor outside.","Is Bolt safe? We ran nine checks on 1,123 live Bolt apps. The hosting came back clean. The findings were API keys and open tables inside the apps.",false,"md",[701,704,707,709,712],{"q":702,"a":703},"Is Bolt safe to use?","For the parts Bolt controls, our numbers say yes. Across 1,123 live apps on bolt.host we found no bad certificate, no domain close to lapsing, 13 apps publishing source maps and one that let any website call its API. What decides your own app is inside it: whether a key that bills you ended up in the code visitors download, and whether your database tables answer a stranger. Both are settings you can check yourself.",{"q":705,"a":706},"Are Bolt apps secure by default?","The parts Bolt publishes for you came back clean in our scan. The rest depends on what happened in the chat. Bolt is meant to keep a paid API key in its Secrets panel behind a server function, and it has a database check that looks for missing row-level security. Neither runs by itself: the project audit is a button in the Publish menu on paid plans, and the database check is a section you open. In August 2026, 75 of 1,123 Bolt apps had something key-shaped in their front end, and 27 of the 35 databases we could ask answered a stranger.",{"q":397,"a":708},"We cannot see from outside how any single key got there. The route we can name is the environment variable. A variable whose name starts with VITE_ is written into the JavaScript every visitor downloads, and Vite, the build tool behind that prefix, says such variables should never hold an API key. For a project address or a publishable key that is harmless. For an OpenAI key it is a bill. Ten of the 1,123 Bolt apps we scanned shipped one.",{"q":710,"a":711},"Is my Supabase data safe in a Bolt app?","It depends on one setting per table. When a Bolt app talks to Supabase from the page, it uses a publishable key that is meant to be public, so row-level security is the only thing deciding what a stranger gets back. We could ask 35 Bolt databases for rows without logging in, and 27 handed them over. That is a count, and the base is too small to turn into a percentage. You can read your own policies in a few minutes.",{"q":713,"a":714},"Is Bolt safer than Lovable?","On the platform side they came out level: 13 of 1,123 Bolt apps and 225 of 18,553 Lovable apps published source maps, a little over one in a hundred each, and neither had a certificate or domain problem. The difference was keys. Ten of the 1,123 Bolt apps carried an OpenAI key, against 18 of 18,554 on Lovable. Ten is a small number, so read that as a direction. The full five-builder comparison is in a separate article.","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",[717,718,719,720,721,722,723,724],"is bolt safe","bolt.new security","is bolt.new safe","bolt app security","are bolt apps secure","bolt supabase security","bolt security issues","bolt deployment security",{},true,"\u002Fblog\u002Fis-bolt-safe","2026-10-02",{"title":5,"description":697},"blog\u002Fis-bolt-safe",[732,733,734],"Is Bolt safe? On everything Bolt itself decides, yes. Across 1,123 live Bolt apps we found 13 publishing their source maps, one that let any website call its API, and not one bad certificate.","75 of those apps shipped something key-shaped in the code a visitor downloads. Most were Google keys, which are usually fine. Ten were OpenAI keys, and anyone who finds one can spend it.","Of the 35 Bolt databases we could actually ask, 27 handed rows to a request with no login. Both problems are settings inside your own project.","kQMmuM3sa-5Gao6lJeAUniE7ModDQhSVd7coaNXqg6E",[737,743,749,755,761,767,773,779,785,791,792,798,804,810,817,823,829,834,840,846,852,858,864,870,876,881,887,893,899,905,911,917,922,928,934,940,946,952,958,963,968,974,980,986,992,998,1004,1010,1015,1021,1027,1033,1038,1043,1049,1053,1059,1065,1070,1075,1081],{"path":738,"title":739,"description":740,"published":741,"category":694,"image":742,"draft":698},"\u002Fblog\u002Fstorage-upload-violates-row-level-security","\"Row-level security policy for table objects\" on upload","\"New row violates row-level security policy for table objects\" means your upload has no insert rule. Making the bucket public does not add one.","2026-10-11","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",{"path":744,"title":745,"description":746,"published":747,"category":694,"image":748,"draft":698},"\u002Fblog\u002Fbase44-security-scan","Base44 security scan: the one thing only it can see","The Base44 security scan checks seven kinds of problem from inside your app. Here is the half it reads that nothing outside can, and the half it never looks at.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":750,"title":751,"description":752,"published":753,"category":694,"image":754,"draft":698},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Your API key leaked. Here is the order to do things in","An API key leaked and you want to know what to do first. Not every key in your frontend is one, and the order matters more than the speed.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":756,"title":757,"description":758,"published":759,"category":694,"image":760,"draft":698},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","\"Infinite recursion detected in policy\" without disabling RLS","\"Infinite recursion detected in policy for relation\" means your Supabase policy asked the table it protects. Here is how to break the circle.","2026-10-08","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",{"path":762,"title":763,"description":764,"published":765,"category":694,"image":766,"draft":698},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" in Supabase, and the wrong fix","\"No API key found in request\" means your Supabase request arrived without a key. Most answers you find point at your database rules instead.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":768,"title":769,"description":770,"published":771,"category":694,"image":772,"draft":698},"\u002Fblog\u002Fis-base44-safe","Is Base44 safe? What 5,442 live Base44 apps showed","Is Base44 safe? We ran nine checks on 5,442 live Base44 apps. Almost all scored B for reasons the owner never chose, and one question nobody can answer.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":774,"title":775,"description":776,"published":777,"category":694,"image":778,"draft":698},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","Hide an API key: move it to a Supabase Edge Function","Hiding an API key means moving it off the browser, and a Supabase Edge Function is the smallest place to put it. Two steps around the move matter more.","2026-10-05","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":780,"title":781,"description":782,"published":783,"category":694,"image":784,"draft":698},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Is your .env file exposed? The twelve paths to check","Is your .env file exposed on your own web server? Twelve addresses tell you in a minute, and a hit means everything in the file is already public.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":786,"title":787,"description":788,"published":789,"category":694,"image":790,"draft":698},"\u002Fblog\u002Fis-v0-safe","v0 security: all 1,790 v0 apps we scanned got an A","v0 security, measured on 1,790 live v0 apps: every one graded A. Only 17 named a database, and that is most of what the A is measuring.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":727,"title":5,"description":697,"published":728,"category":694,"image":715,"draft":698},{"path":793,"title":794,"description":795,"published":796,"category":694,"image":797,"draft":698},"\u002Fblog\u002Fis-supabase-down-or-your-app","Is Supabase down, or is it your app? How to tell","Is Supabase down, or is it your app? A paused project, a full database and a bug of your own all look like an outage. Four checks tell them apart.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":799,"title":800,"description":801,"published":802,"category":694,"image":803,"draft":698},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","Does Supabase encrypt my data? Yes. Here is what it stops","Does Supabase encrypt data? Yes: AES-256 at rest, TLS in transit, SOC 2 and ISO 27001 audited. What each one covers, and the leak none of them stops.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":805,"title":806,"description":807,"published":808,"category":694,"image":809,"draft":698},"\u002Fblog\u002Fsupabase-free-plan-limits","Supabase free plan limits, and what happens at each one","The Supabase free plan limits you to 500 MB of database and 5 GB of egress, with no backups. What happens as you cross each line, and what $25 changes.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":811,"title":812,"description":813,"published":814,"category":815,"image":816,"draft":698},"\u002Fblog\u002Ftest-your-supabase-backup","Test your Supabase backup before the day you need it","How to test your Supabase backup: restore it into a spare project, compare the row counts, sign in, and check for the line a cut-off file is missing.","2026-09-28","Backups","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":818,"title":819,"description":820,"published":821,"category":815,"image":822,"draft":698},"\u002Fblog\u002Fsupabase-backup-github-action","Free Supabase backup with a GitHub Action, and the catch","A Supabase backup GitHub Action costs nothing and suits a lot of apps. The workflow, the connection string that works on GitHub, and the egress each run uses.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":824,"title":825,"description":826,"published":827,"category":815,"image":828,"draft":698},"\u002Fblog\u002Fdownload-your-supabase-backup","Why you can't download your Supabase backup","You can't download your Supabase backup on a current project, because the daily copy is a physical snapshot. How to tell, and how to hold a copy of your own.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":830,"title":831,"description":832,"published":827,"category":694,"image":833,"draft":698},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": the missing grant","From October 30, a new Supabase table answers \"permission denied for table\" until you grant access. The grant the email shows is half the fix.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":835,"title":836,"description":837,"published":838,"category":694,"image":839,"draft":698},"\u002Fblog\u002Fopen-api-endpoint-exposed","Is an open API endpoint a security problem? Look at the JSON","Your scan flagged an open API endpoint. Whether it matters depends on what came back, and most of the ones we found were the platform's own.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":841,"title":842,"description":843,"published":844,"category":694,"image":845,"draft":698},"\u002Fblog\u002Flovable-security-scan","Lovable security scan: the one thing it cannot prove","Lovable security scan: what the Quick and Deep scans check, when each one runs, and the one thing no scan from inside your project can prove.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":847,"title":848,"description":849,"published":850,"category":815,"image":851,"draft":698},"\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","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":853,"title":854,"description":855,"published":856,"category":694,"image":857,"draft":698},"\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":859,"title":860,"description":861,"published":862,"category":694,"image":863,"draft":698},"\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":865,"title":866,"description":867,"published":868,"category":694,"image":869,"draft":698},"\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":871,"title":872,"description":873,"published":874,"category":694,"image":875,"draft":698},"\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":431,"title":877,"description":878,"published":879,"category":694,"image":880,"draft":698},"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":882,"title":883,"description":884,"published":885,"category":694,"image":886,"draft":698},"\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":888,"title":889,"description":890,"published":891,"category":694,"image":892,"draft":698},"\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":894,"title":895,"description":896,"published":897,"category":694,"image":898,"draft":698},"\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":900,"title":901,"description":902,"published":903,"category":815,"image":904,"draft":698},"\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":906,"title":907,"description":908,"published":909,"category":815,"image":910,"draft":698},"\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":912,"title":913,"description":914,"published":915,"category":815,"image":916,"draft":698},"\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":675,"title":918,"description":919,"published":920,"category":694,"image":921,"draft":698},"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":923,"title":924,"description":925,"published":926,"category":694,"image":927,"draft":698},"\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":929,"title":930,"description":931,"published":932,"category":694,"image":933,"draft":698},"\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":935,"title":936,"description":937,"published":938,"category":694,"image":939,"draft":698},"\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":941,"title":942,"description":943,"published":944,"category":694,"image":945,"draft":698},"\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":947,"title":948,"description":949,"published":950,"category":694,"image":951,"draft":698},"\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":953,"title":954,"description":955,"published":956,"category":694,"image":957,"draft":698},"\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":236,"title":959,"description":960,"published":961,"category":694,"image":962,"draft":698},"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":379,"title":964,"description":965,"published":966,"category":694,"image":967,"draft":698},"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":969,"title":970,"description":971,"published":972,"category":694,"image":973,"draft":698},"\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":975,"title":976,"description":977,"published":978,"category":815,"image":979,"draft":698},"\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":981,"title":982,"description":983,"published":984,"category":694,"image":985,"draft":698},"\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":987,"title":988,"description":989,"published":990,"category":815,"image":991,"draft":698},"\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":993,"title":994,"description":995,"published":996,"category":694,"image":997,"draft":698},"\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":999,"title":1000,"description":1001,"published":1002,"category":694,"image":1003,"draft":698},"\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":1005,"title":1006,"description":1007,"published":1008,"category":694,"image":1009,"draft":698},"\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":268,"title":1011,"description":1012,"published":1013,"category":694,"image":1014,"draft":698},"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":1016,"title":1017,"description":1018,"published":1019,"category":815,"image":1020,"draft":698},"\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":1022,"title":1023,"description":1024,"published":1025,"category":815,"image":1026,"draft":698},"\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":1028,"title":1029,"description":1030,"published":1031,"category":694,"image":1032,"draft":698},"\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":372,"title":1034,"description":1035,"published":1036,"category":694,"image":1037,"draft":698},"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":637,"title":1039,"description":1040,"published":1041,"category":815,"image":1042,"draft":698},"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":1044,"title":1045,"description":1046,"published":1047,"category":694,"image":1048,"draft":698},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","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":258,"title":1050,"description":1051,"published":1047,"category":694,"image":1052,"draft":698},"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":1054,"title":1055,"description":1056,"published":1057,"category":694,"image":1058,"draft":698},"\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":1060,"title":1061,"description":1062,"published":1063,"category":815,"image":1064,"draft":698},"\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":482,"title":1066,"description":1067,"published":1068,"category":694,"image":1069,"draft":698},"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":1071,"title":1072,"description":1073,"published":1068,"category":815,"image":1074,"draft":698},"\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":1076,"title":1077,"description":1078,"published":1079,"category":815,"image":1080,"draft":698},"\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":1082,"title":1083,"description":1084,"published":1079,"category":694,"image":1085,"draft":698},"\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",1791705957970]