[{"data":1,"prerenderedAt":802},["ShallowReactive",2],{"blog-pt-enable-rls-on-every-supabase-table":3,"blog-index-pt":563},{"id":4,"title":5,"body":6,"category":519,"cover":520,"coverAlt":521,"description":522,"draft":523,"extension":524,"faq":525,"image":541,"keywords":542,"meta":551,"navigation":552,"ogTitle":553,"path":554,"published":555,"seo":556,"stem":557,"tldr":558,"updated":555,"__hash__":562},"blog_pt\u002Fblog\u002Fenable-rls-on-every-supabase-table.md","Ative Row Level Security em toda tabela do Supabase e comprove",{"type":7,"value":8,"toc":507},"minimark",[9,13,21,26,29,32,39,45,48,52,55,58,69,80,86,89,95,98,114,118,121,127,133,159,165,171,174,180,186,193,275,287,291,294,297,302,305,308,314,318,321,324,327,333,344,347,351,354,360,367,372,393,406,413,417,420,423,435,438,441,453,457,494],[10,11,12],"p",{},"Disseram para você ligar o Row Level Security, ou o seu construtor de IA\nmencionou isso de passagem enquanto consertava outra coisa. O seu projeto no\nSupabase tem entre quatro e quarenta tabelas, e você não sabe quais estão\ncobertas.",[10,14,15,16,20],{},"A instrução que você encontra em todo lugar é uma linha de SQL por tabela, e até\naí ela está certa. Onde quase todo guia para é no passo seguinte. ",[17,18,19],"strong",{},"Uma política\nque existe não é uma política que funciona",", e nada no seu dashboard vai\nmostrar a diferença. Então ativar o Row Level Security no Supabase são três\ntrabalhos e não um: ligar em todas as tabelas, escrever as duas ou três\npolíticas que remontam o seu app, e depois perguntar ao seu próprio banco o que\num desconhecido perguntaria a ele.",[22,23,25],"h2",{"id":24},"o-que-ativar-o-row-level-security-faz-de-verdade","O que ativar o Row Level Security faz de verdade?",[10,27,28],{},"Faz o Postgres consultar as suas regras antes de entregar uma linha. Com a opção\ndesligada não há regras para consultar, então a resposta para qualquer\nrequisição é tudo.",[10,30,31],{},"Imagine um bibliotecário que busca o que você pedir. Row Level Security é a\ninstrução de ler um bilhete sobre você antes de encher o carrinho. O bilhete é a\nsua política, e ele pode dizer que essa pessoa pode levar os livros que ela\nmesma escreveu, ou pode dizer que qualquer um pode levar qualquer coisa. Com a\ninstrução em vigor e nenhum bilhete escrito ainda, o bibliotecário volta com o\ncarrinho vazio e não explica por quê.",[10,33,34,35,38],{},"É nessa última parte que as pessoas tropeçam, e ela decide como um teste vai ser\nmais adiante. ",[17,36,37],{},"Row Level Security filtra linhas. Ele não recusa requisições.","\nUma tabela que você não tem permissão de ler responde com uma lista vazia e um\ncódigo de sucesso, não com um erro nem com uma tela de login. Ao seu app nunca é\ndito que ele foi recusado. Ele não recebe nada e desenha uma tela em branco.",[40,41],"diagram",{"alt":42,"caption":43,"src":44},"A mesma requisição desenhada três vezes. Com o interruptor de segurança desligado, voltam quatro linhas acesas. Com o interruptor ligado e nenhuma política, volta um espaço tracejado vazio. Com o interruptor ligado e uma política de propriedade, volta uma linha acesa. Os três retornos estão marcados com 200.","Uma requisição, três configurações e o mesmo código de sucesso todas as vezes. O Row Level Security muda o que volta, nunca se a requisição deu certo.","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fsame-request-three-answers-1600x780.png",[10,46,47],{},"Então ligar a opção num projeto que ainda não tem políticas não tranca os\ndesconhecidos longe dos seus dados. Tranca todo mundo, o seu próprio app\nincluído, até você dizer quem pode ver o quê.",[22,49,51],{"id":50},"como-ativo-o-rls-em-todas-as-tabelas-do-supabase-de-uma-vez","Como ativo o RLS em todas as tabelas do Supabase de uma vez?",[10,53,54],{},"Um laço, rodado uma vez no SQL Editor. Ele percorre cada tabela do seu esquema\npublic e liga a opção onde ela estiver desligada.",[10,56,57],{},"Comece vendo onde você está. Isto lista as suas tabelas e diz se cada uma tem a\nopção agora:",[59,60,65],"pre",{"className":61,"code":63,"language":64},[62],"language-text","select tablename, rowsecurity\nfrom pg_tables\nwhere schemaname = 'public'\norder by tablename;\n","text",[66,67,63],"code",{"__ignoreMap":68},"",[10,70,71,72,75,76,79],{},"Toda linha em que ",[66,73,74],{},"rowsecurity"," aparece como ",[66,77,78],{},"false"," é uma tabela entregando o\nseu conteúdo para qualquer um que tenha a chave publicável que vai junto com o\nseu app. Se essa lista for curta, faça uma de cada vez e veja o que quebra:",[59,81,84],{"className":82,"code":83,"language":64},[62],"alter table public.orders enable row level security;\n",[66,85,83],{"__ignoreMap":68},[10,87,88],{},"Se não for curta, isto dá conta de todas:",[59,90,93],{"className":91,"code":92,"language":64},[62],"do $$\ndeclare t record;\nbegin\n  for t in\n    select tablename from pg_tables where schemaname = 'public'\n  loop\n    execute format(\n      'alter table public.%I enable row level security', t.tablename\n    );\n  end loop;\nend $$;\n",[66,94,92],{"__ignoreMap":68},[10,96,97],{},"Rode isso e o seu app fica em branco. O Supabase diz isso com todas as letras na\nprópria documentação: os dados ficam inacessíveis pela API com uma chave\npublicável até que políticas sejam definidas. É a opção fazendo o trabalho dela,\ne é por isso que a próxima seção é a que vale deixar aberta antes de apertar\nexecutar.",[99,100,102],"callout",{"type":101},"warn",[10,103,104,107,108,113],{},[17,105,106],{},"As tabelas que o seu construtor fez são as que estavam abertas."," Uma tabela\ncriada clicando no Table Editor do Supabase já vem com Row Level Security\nligado. Uma tabela criada rodando SQL não vem, e rodar SQL é como Lovable, Bolt,\nCursor e v0 criam tabelas por você. As tabelas que você nunca viu nascer são\njustamente aquelas para as quais esse laço existe, e\n",[109,110,112],"a",{"href":111},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","o que o aviso \"RLS disabled in public\" pega e o que ele não pega","\nexplica por que o seu dashboard pode ter ficado calado sobre elas.",[22,115,117],{"id":116},"as-três-políticas-de-que-você-realmente-precisa","As três políticas de que você realmente precisa",[10,119,120],{},"Quase toda tabela num app como o seu tem um de três formatos: linhas que\npertencem a uma pessoa, linhas que qualquer um pode ler e linhas que o seu app\ngrava em nome de um visitante. Aqui está cada uma, pronta para colar e renomear.",[10,122,123,126],{},[17,124,125],{},"Linhas que pertencem a uma pessoa."," Pedidos, mensagens, itens salvos,\nqualquer coisa com dono.",[59,128,131],{"className":129,"code":130,"language":64},[62],"create policy \"read own orders\"\non public.orders for select\nto authenticated\nusing ( (select auth.uid()) = user_id );\n",[66,132,130],{"__ignoreMap":68},[10,134,135,138,139,142,143,146,147,150,151,154,155,158],{},[66,136,137],{},"auth.uid()"," é o id de quem está logado naquela requisição. ",[66,140,141],{},"user_id"," é a coluna\nda sua tabela que registra o dono, então confira o nome antes de rodar: os\nconstrutores também escrevem ",[66,144,145],{},"owner_id",", ",[66,148,149],{},"profile_id"," e ",[66,152,153],{},"created_by",". A linha\n",[66,156,157],{},"to authenticated"," significa que a política nem chega a ser considerada para um\nvisitante deslogado, e é isso que mantém a tabela fechada ao público.",[10,160,161,164],{},[17,162,163],{},"Linhas que qualquer um pode ler."," Um catálogo de produtos, artigos\npublicados, um mapa de locais.",[59,166,169],{"className":167,"code":168,"language":64},[62],"create policy \"anyone may read products\"\non public.products for select\nto anon, authenticated\nusing ( true );\n",[66,170,168],{"__ignoreMap":68},[10,172,173],{},"Escreva essa de propósito ou não escreva, porque é também a política à qual um\nconstrutor de IA recorre no momento em que você pede para ele consertar uma tela\nvazia. A pergunta a resolver antes: essa tabela poderia ser uma página do seu\nsite, exatamente como está, sem tirar nada? Um não quer dizer que ela quer a\npolítica de propriedade acima.",[10,175,176,179],{},[17,177,178],{},"Linhas que o seu app grava."," Ler e escrever são permissões separadas no\nPostgres, então uma tabela em que o seu app salva precisa de uma segunda\npolítica, e esta confere a linha na entrada e não na saída.",[59,181,184],{"className":182,"code":183,"language":64},[62],"create policy \"insert own orders\"\non public.orders for insert\nto authenticated\nwith check ( (select auth.uid()) = user_id );\n",[66,185,183],{"__ignoreMap":68},[10,187,188,189,192],{},"Qual cláusula vai onde é a parte que pega as pessoas, e a linha ",[66,190,191],{},"update"," carrega\num requisito que não tem nada de óbvio:",[194,195,196,212],"table",{},[197,198,199],"thead",{},[200,201,202,206,209],"tr",{},[203,204,205],"th",{},"Operação",[203,207,208],{},"Cláusula",[203,210,211],{},"Também precisa de",[213,214,215,230,244,262],"tbody",{},[200,216,217,223,228],{},[218,219,220],"td",{},[66,221,222],{},"select",[218,224,225],{},[66,226,227],{},"using",[218,229],{},[200,231,232,237,242],{},[218,233,234],{},[66,235,236],{},"insert",[218,238,239],{},[66,240,241],{},"with check",[218,243],{},[200,245,246,250,256],{},[218,247,248],{},[66,249,191],{},[218,251,252,150,254],{},[66,253,227],{},[66,255,241],{},[218,257,258,259,261],{},"uma política ",[66,260,222],{}," na mesma tabela",[200,263,264,269,273],{},[218,265,266],{},[66,267,268],{},"delete",[218,270,271],{},[66,272,227],{},[218,274],{},[10,276,277,278,281,282,286],{},"A documentação do Supabase é explícita sobre a última: sem uma política de\nselect correspondente, um update não funciona como você espera. E se a mensagem\n",[66,279,280],{},"new row violates row-level security policy"," foi o que colocou você a procurar,\na distância entre essas duas cláusulas é\n",[109,283,285],{"href":284},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","todo esse erro",".",[22,288,290],{"id":289},"por-que-todo-exemplo-escreve-select-authuid-em-vez-de-authuid","Por que todo exemplo escreve (select auth.uid()) em vez de auth.uid()",[10,292,293],{},"Porque os parênteses fazem o Postgres calcular o valor uma vez para a consulta\ninteira em vez de uma vez para cada linha que ele olha.",[10,295,296],{},"A versão embrulhada vira o que o Postgres chama de initPlan: rodada uma única\nvez e depois reaproveitada pelo resto do comando. Sem os parênteses a função é\nchamada de novo na linha um, na linha dois, na linha três, e assim por diante\nnuma tabela que pode ter cem mil delas. O próprio Performance Advisor do\nSupabase reporta a versão sem parênteses sob uma regra chamada Auth RLS\nInitialization Plan, e ela é uma das entradas que as pessoas mais encontram lá\ndentro.",[40,298],{"alt":299,"caption":300,"src":301},"Dois painéis sobre as mesmas oito linhas de tabela. No painel da esquerda uma marca de função fica ao lado de cada linha com a sua própria ligação, oito no total. No painel da direita uma única marca de função no alto se abre em leque para as oito linhas de uma vez.","Os parênteses são toda a diferença. À esquerda a função roda uma vez por linha; à direita roda uma vez e a resposta é reaproveitada.","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fonce-per-query-1600x620.png",[10,303,304],{},"Uma ressalva, e ela é do próprio Supabase: isso funciona porque a resposta não\nmuda de linha para linha. Uma função cujo resultado realmente depende da linha à\nfrente dela não pode ser tirada do laço, então essa deixe sem parênteses.",[10,306,307],{},"Já que você está por aqui, adicione um índice na coluna que as suas políticas\nfiltram. A política vira uma condição em toda leitura daquela tabela, então numa\ntabela com muitas linhas uma coluna sem índice aparece nos seus tempos de\nresposta:",[59,309,312],{"className":310,"code":311,"language":64},[62],"create index orders_user_id_idx on public.orders (user_id);\n",[66,313,311],{"__ignoreMap":68},[22,315,317],{"id":316},"testar-uma-política-sem-fabricar-uma-conta-falsa","Testar uma política sem fabricar uma conta falsa",[10,319,320],{},"O SQL Editor do Supabase consegue rodar uma consulta como se um visitante\nespecífico a tivesse enviado, e isso cobre o caso anônimo por inteiro.",[10,322,323],{},"O editor traz um controle para o papel com que uma consulta deve rodar. Coloque\nno papel anônimo e depois rode um select comum contra a tabela que você acabou\nde mudar. O que volta é o que um desconhecido deslogado recebe. Para um visitante\nlogado, pegue o id de um usuário que você já tem em vez de criar um novo;\nqualquer linha da sua própria tabela serve para testar.",[10,325,326],{},"Se você prefere digitar a clicar, a mesma coisa em SQL:",[59,328,331],{"className":329,"code":330,"language":64},[62],"begin;\nset local role anon;\nselect * from public.orders;\nrollback;\n",[66,332,330],{"__ignoreMap":68},[10,334,335,336,339,340,343],{},"O ",[66,337,338],{},"begin"," e o ",[66,341,342],{},"rollback"," estão aí para a troca de papel durar aquele bloco e nada\nalém, o que importa se você estiver passando por várias tabelas de uma sentada.",[10,345,346],{},"O que isso diz é o que as suas políticas fazem dentro do banco. O que isso não\nconsegue dizer é o que o seu projeto entrega para a internet, porque a requisição\nque os seus visitantes realmente fazem não começa no SQL Editor. Ela começa num\nnavegador, carrega uma chave publicável e chega pelo endereço público do seu\nprojeto.",[22,348,350],{"id":349},"como-testo-o-rls-do-supabase-de-fora-do-meu-app","Como testo o RLS do Supabase de fora do meu app?",[10,352,353],{},"Mande a requisição que um desconhecido mandaria. Você precisa de dois valores e\nos dois já estão no código que o seu site entrega a cada visitante: a URL do seu\nprojeto e a sua chave publicável.",[59,355,358],{"className":356,"code":357,"language":64},[62],"curl \"https:\u002F\u002FYOUR-PROJECT.supabase.co\u002Frest\u002Fv1\u002Forders?select=*&limit=1\" \\\n  -H \"apikey: YOUR_PUBLISHABLE_KEY\" \\\n  -H \"Authorization: Bearer YOUR_PUBLISHABLE_KEY\"\n",[66,359,357],{"__ignoreMap":68},[10,361,362,363,366],{},"Troque um nome de tabela por vez e leia o que volta. Uma lista vazia, ",[66,364,365],{},"[]",", quer\ndizer que a política segurou para um visitante deslogado. Uma linha quer dizer\nque qualquer um com uma chave que vai junto com o seu app consegue ler aquela\ntabela. Um erro que menciona a própria chave quer dizer que você copiou o valor\nerrado, e vale descartar isso antes de concluir qualquer coisa.",[40,368],{"alt":369,"caption":370,"src":371},"Um limite tracejado em volta de uma tabela de banco de dados. Dentro dele, uma lupa fica ao lado da tabela com uma seta curta. Fora dele, uma pessoa manda uma seta que leva uma chave por uma brecha no limite, com o caminho barra rest barra v1 escrito ao lado da brecha, e alcança a mesma tabela.","O teste no editor nunca sai do prédio. A requisição de fora chega pelo mesmo endereço público que os seus visitantes usam, levando a mesma chave que o seu app entrega.","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Ftwo-tests-one-table-1600x640.png",[10,373,374,375,378,379,382,383,387,388,392],{},"Num projeto Supabase mais novo essa chave começa com ",[66,376,377],{},"sb_publishable_",", e num\nmais antigo é a chave ",[66,380,381],{},"anon",". As duas são seguras de usar assim e seguras de\nficar no seu app, é para isso que servem;\n",[109,384,386],{"href":385},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","quais chaves de API pertencem a um frontend","\ncobre o par que não pertence, e\n",[109,389,391],{"href":390},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","onde encontrá-las no dashboard"," são os\nquatro valores daquela página de configurações.",[10,394,395,396,400,401,405],{},"Esse é o teste que corresponde à realidade, e rodá-lo em escala é como sabemos o\nquanto essa falha é comum. Entre 12 e 14 de agosto de 2026 rodamos nove\nverificações externas em 30.998 apps no ar publicados pelo Lovable, Base44,\nReplit, v0 e Bolt. Dos 3.680 apps com Supabase em que a verificação conseguiu\nterminar, 2.096 responderam a uma requisição anônima com linhas de pelo menos uma\ntabela. Isso dá 57%, e é uma fatia dos apps que nos deram uma resposta clara, não\nde tudo o que escaneamos. O\n",[109,397,399],{"href":398},"\u002Fresearch\u002Fvibe-coded-app-security-2026","conjunto de dados completo está publicado",",\ne ",[109,402,404],{"href":403},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","de que esses 57% são uma fatia","\npercorre a contagem.",[10,407,408,409,286],{},"Fazer isso na mão está bom com quatro tabelas e cansa com quarenta. O nosso scan\ngratuito manda essa requisição por você, descobre quais tabelas existem sem que\nvocê as nomeie e diz quais responderam, ao lado de outras oito verificações que\nele faz de fora. Ele lê o seu site no ar do mesmo jeito que qualquer visitante\npode, leva cerca de 20 segundos e não precisa de conta:\n",[109,410,412],{"href":411},"\u002Fsecurity-scanner","escaneie o seu app",[22,414,416],{"id":415},"antes-de-reescrever-políticas-numa-tabela-no-ar","Antes de reescrever políticas numa tabela no ar",[10,418,419],{},"Tire primeiro uma cópia do seu banco. Você está prestes a mudar permissões em\ntodas as tabelas que tem, com as mesmas ferramentas que produziram o problema.",[10,421,422],{},"Vale separar dois riscos diferentes, porque só um deles tem a ver com o trabalho\nde hoje. Se uma tabela era legível e gravável por qualquer um, apertar agora não\nmuda nada do que já aconteceu, e essa versão costuma aparecer como uma mensagem\nde suporte sobre dados que mudaram sozinhos. O outro risco é a própria migração.\nUma política apagada e recriada um pouco torta é uma terça-feira comum, e o\ncaminho de volta é uma cópia de como as coisas estavam uma hora atrás.",[10,424,425,426,430,431,286],{},"Num plano pago do Supabase a cópia de ontem à noite está esperando no console. No\nplano gratuito não há nada em que se apoiar, porque\n",[109,427,429],{"href":428},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","o Supabase não faz nenhum backup automático no plano gratuito",".\nSe esse é o seu caso,\n",[109,432,434],{"href":433},"\u002Fblog\u002Fback-up-supabase-free-tier","tire um antes de começar",[10,436,437],{},"O Reeve Care é a versão disso de que você não precisa lembrar. O seu banco\nSupabase é copiado num calendário, guardado fora da sua conta Supabase,\ncriptografado, e lido de volta para confirmar que restaura antes que a data no\nseu painel se mexa. Os arquivos enviados pelos seus usuários viajam junto assim\nque você conecta uma chave de Storage, e essa chave é pedida à parte porque o\nSupabase não emite chave só de leitura para arquivos: a que copia os seus uploads\ntambém consegue gravar, e a que copia o seu banco não. Conectá-la é opcional e o\nseu banco é salvo de qualquer jeito. Os backups são só do Supabase, então se os\nseus dados moram em outro lugar a gente diz isso em vez de vender uma assinatura\nque vigia uma caixa vazia.",[10,439,440],{},"Restaurar é a parte que importa num dia como esse. O Care copia o estado atual do\nseu banco antes de reproduzir a versão que você escolheu, então apertar o botão\ntem um desfazer próprio.",[10,442,443,444,448,449,286],{},"A outra metade é a verificação que você acabou de fazer na mão. Uma política que\nafrouxa numa migração posterior não é coisa que alguém encontre olhando, então o\nCare roda de novo a mesma requisição anônima num calendário e avisa quando uma\ntabela começa a responder tendo ficado calada na semana passada. Monitoramento de\nuptime e um relatório mensal estão na mesma assinatura. Nada disso escreve as\nsuas políticas por você, e nenhum backup fecha uma tabela aberta. O que muda é o\nquanto uma migração malfeita custa a você.\n",[109,445,447],{"href":446},"\u002Fsupabase-backups","O que o Reeve salva no Supabase, com que frequência, e o que uma restauração faz","\npercorre o ciclo inteiro, e os planos estão na\n",[109,450,452],{"href":451},"\u002Fpricing","página de preços",[22,454,456],{"id":455},"a-ordem-em-que-trabalhar","A ordem em que trabalhar",[458,459,460],"key-takeaways",{},[461,462,463,471,474,481,491],"ul",{},[464,465,466,467,470],"li",{},"Liste as suas tabelas com ",[66,468,469],{},"select tablename, rowsecurity from pg_tables where schemaname = 'public'"," e veja quantas estão abertas antes de mudar qualquer coisa.",[464,472,473],{},"Tire um backup e depois ative o Row Level Security em toda tabela do esquema public. Espere o seu app ficar em branco; é a opção funcionando.",[464,475,476,477,480],{},"Dê a cada tabela uma das três políticas. A de propriedade é o caso padrão; ",[66,478,479],{},"USING (true)"," é uma decisão que você toma tabela por tabela, não um jeito de recuperar as telas.",[464,482,483,484,487,488,490],{},"Escreva ",[66,485,486],{},"(select auth.uid())"," em vez de ",[66,489,137],{},", e indexe a coluna que as suas políticas filtram.",[464,492,493],{},"Teste cada tabela de fora e sem login. Uma lista vazia é aprovação. Uma linha é uma tabela que qualquer um consegue ler, diga o que disser o seu dashboard.",[10,495,496,497,501,502,506],{},"Comece pela tabela que mais constrangeria você como página pública e siga para\nbaixo a partir daí. A\n",[109,498,500],{"href":499},"\u002Fchecklist","checklist de segurança de 10 minutos"," cobre isso junto com o resto\ndo que vale confirmar num app recém-lançado, e o\n",[109,503,505],{"href":504},"\u002Fis-your-supabase-app-safe","guia de segurança do Supabase"," passa pelo que mais\ncostuma ficar aberto.",{"title":68,"searchDepth":508,"depth":508,"links":509},3,[510,512,513,514,515,516,517,518],{"id":24,"depth":511,"text":25},2,{"id":50,"depth":511,"text":51},{"id":116,"depth":511,"text":117},{"id":289,"depth":511,"text":290},{"id":316,"depth":511,"text":317},{"id":349,"depth":511,"text":350},{"id":415,"depth":511,"text":416},{"id":455,"depth":511,"text":456},"Noções de segurança","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcover-1200x630.png","Uma lista de tabelas de banco de dados em um painel, cada uma com um interruptor de segurança ao lado, e a maioria ainda desligada.","Ativar Row Level Security no Supabase sem política fecha a tabela por completo. Uma política sem a chave ligada não faz nada. Aqui está o SQL, e o teste.",false,"md",[526,529,532,535,538],{"q":527,"a":528},"O que acontece se eu ativar o RLS e não escrever nenhuma política?","A tabela para de responder, inclusive para o seu próprio app. Com a opção ligada, o Postgres consulta as suas políticas antes de entregar uma linha, e sem políticas não existe nada que possa dizer sim, então as requisições voltam vazias. O Supabase documenta isso direto: os dados ficam inacessíveis pela API com uma chave publicável até que políticas sejam definidas. Nada é apagado e nada quebra. Escreva uma política para as linhas que o seu app deve mostrar e as telas voltam.",{"q":530,"a":531},"O Row Level Security deixa as minhas consultas mais lentas?","Pode deixar, e os dois ajustes são pequenos. Escreva `(select auth.uid())` na condição da política, com os parênteses, para o Postgres calcular o valor uma vez para a consulta inteira e depois reaproveitá-lo em cada linha. O Supabase aponta a versão sem parênteses no próprio Performance Advisor, sob uma regra chamada Auth RLS Initialization Plan. Depois adicione um índice na coluna que a política filtra, normalmente `user_id`. Numa tabela com alguns milhares de linhas é pouco provável que você note diferença. Numa tabela grande, as duas coisas importam.",{"q":533,"a":534},"Preciso de RLS se a minha tabela não tem dados pessoais?","Você ainda quer a opção ligada, e a política pode ser a permissiva. Uma tabela com Row Level Security desligado é legível por qualquer um que tenha a chave publicável que vai junto com o seu app, o que é aceitável para um catálogo de produtos e bem menos aceitável para qualquer coisa que você não publicaria como página. Ligar e escrever uma política de leitura com `USING (true)` dá esse mesmo acesso público de propósito, e faz a tabela ser lida como decidida em vez de esquecida na próxima vez que alguém passar pela lista.",{"q":536,"a":537},"Por que minha inscrição no realtime parou de funcionar depois que ativei o RLS?","Porque o Realtime consulta as mesmas políticas antes de mandar uma mudança para quem está inscrito. Uma tabela com Row Level Security ligado e sem política de select para aquele visitante não entrega linhas a uma consulta nem mudanças a uma inscrição, exatamente pelo mesmo motivo. Adicione a política de select de que aquela inscrição precisa e o fluxo volta. Se você usa Realtime broadcast ou presence em vez de mudanças no banco, esses são autorizados à parte, por políticas escritas na tabela `realtime.messages`.",{"q":539,"a":540},"Como testo uma política sem criar um usuário falso?","De dois jeitos, e nenhum deles precisa de conta nova. O SQL Editor do Supabase consegue rodar uma consulta como se um papel específico a tivesse enviado, e isso cobre o caso anônimo por inteiro: o que volta é o que um desconhecido recebe. Para o caso logado você precisa de um id de usuário para servir de dublê, e qualquer linha que já esteja na sua tabela serve. O segundo jeito é uma requisição de fora levando a sua chave publicável, que testa o caminho todo e não só a política.","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",[543,544,545,546,547,548,549,550],"ativar row level security supabase","supabase ativar rls","row level security policies supabase","exemplo de política rls supabase","supabase rls select auth.uid","testar rls supabase","supabase rls best practices","auth.uid() policy",{},true,"Ative Row Level Security em toda tabela do Supabase","\u002Fblog\u002Fenable-rls-on-every-supabase-table","2026-09-10",{"title":5,"description":522},"blog\u002Fenable-rls-on-every-supabase-table",[559,560,561],"Ativar Row Level Security no Supabase sem política fecha uma tabela por completo, e escrever uma política sem ativar a opção não faz absolutamente nada. Toda tabela precisa das duas coisas.","Três formatos de política cobrem quase tudo que um construtor de IA cria: linhas que pertencem a uma pessoa, linhas que qualquer um pode ler e linhas que o seu app grava em nome de um visitante.","Depois confira de fora do seu app e sem login, porque essa é a requisição que um desconhecido faz, e é a única que diz o que as suas políticas fazem em vez do que elas dizem.","QXXeA-IwcFx4jt6kKBsLj5WGq0O-vQ0ETM1GBlJQmWE",[564,571,577,583,589,595,601,607,613,619,625,631,637,643,644,649,655,661,667,673,679,685,691,697,703,708,714,719,724,730,736,742,748,754,760,765,770,776,781,787,792,798],{"path":565,"title":566,"description":567,"published":568,"category":569,"image":570,"draft":523},"\u002Fblog\u002Fsupabase-backup-auth-users","Por que seu dump do Supabase não tem usuários dentro","Rode supabase db dump sozinho e você recebe a forma do seu banco e nenhuma das linhas dele, sem o schema auth onde seus usuários moram.","2026-09-23","Backups","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":572,"title":573,"description":574,"published":575,"category":519,"image":576,"draft":523},"\u002Fblog\u002Fdomain-and-certificate-expiry","Domínio expirado, site fora do ar: o que acontece agora","Seu domínio expirou e seu site está fora do ar. O relógio que começa a correr, por que o certificado é o problema menor, e como conferir os dois.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":578,"title":579,"description":580,"published":581,"category":519,"image":582,"draft":523},"\u002Fblog\u002Fis-lovable-safe","O Lovable é seguro? O que vimos em 18.554 aplicativos Lovable","O Lovable é seguro? Passamos 18.554 aplicativos Lovable no ar por nove verificações. A plataforma foi a mais limpa de cinco. Os achados estavam nos aplicativos.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":584,"title":585,"description":586,"published":587,"category":519,"image":588,"draft":523},"\u002Fblog\u002Fvibe-coded-app-security-checklist","O checklist de segurança do vibe coding, em nove verificações","Um checklist de segurança do vibe coding com nove itens, cada um verificável no seu app de fora por qualquer pessoa, e cada um com um teste de uma linha.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":590,"title":591,"description":592,"published":593,"category":519,"image":594,"draft":523},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Uma chave secreta da Stripe no frontend pode mover dinheiro","Uma chave secreta da Stripe exposta no seu frontend pode reembolsar, cobrar e ler cada ficha de cliente que você tem. Sua chave pk_live_ é que deve estar aí.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":596,"title":597,"description":598,"published":599,"category":519,"image":600,"draft":523},"\u002Fblog\u002Fvite-and-next-public-env-vars","Variáveis de ambiente do Vite expostas: o prefixo diz publique isto","Variáveis de ambiente do Vite expostas no seu app: fizeram o que o prefixo pediu. VITE_ e NEXT_PUBLIC_ significam publique isto, e a IA nunca soube o custo.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":602,"title":603,"description":604,"published":605,"category":519,"image":606,"draft":523},"\u002Fblog\u002Fbase44-source-maps","Segurança no Base44: o que um scan aponta e o que é seu para corrigir","Segurança no Base44 em 5.438 apps escaneados: três achados em quase todos são da plataforma, o source map é o selo do Base44, e a sua parte é uma lista curta.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":608,"title":609,"description":610,"published":611,"category":519,"image":612,"draft":523},"\u002Fblog\u002Fis-cursor-ai-safe","O Cursor AI é seguro? O editor, o código e o app que você publicou","O Cursor AI é seguro? Três perguntas em uma busca: o que o Cursor guarda, o que o código que ele escreve erra, e se o app que você publicou está aberto.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":614,"title":615,"description":616,"published":617,"category":519,"image":618,"draft":523},"\u002Fblog\u002Fis-replit-safe","O Replit é seguro? O que vimos em 3.042 aplicativos Replit no ar","O Replit é seguro? Passamos 3.042 aplicativos Replit no ar por nove verificações externas. Os achados estavam no aplicativo publicado, não no host.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":620,"title":621,"description":622,"published":623,"category":569,"image":624,"draft":523},"\u002Fblog\u002Fsupabase-storage-backup","Supabase storage backup: sua cópia do banco não tem nenhum arquivo","Um Supabase storage backup é uma tarefa à parte. Os backups do banco guardam a lista dos seus arquivos e nenhum deles, então cada upload fica quebrado.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":626,"title":627,"description":628,"published":629,"category":569,"image":630,"draft":523},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Point-in-time recovery do Supabase: preço e limites","O point-in-time recovery do Supabase rebobina seu banco para qualquer segundo da última semana. Custa $100 por mês além do Pro e cobre só o banco.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":632,"title":633,"description":634,"published":635,"category":569,"image":636,"draft":523},"\u002Fblog\u002Fsupabase-project-paused-recover","Projeto Supabase pausado? Seus dados continuam lá","O Supabase pausou seu projeto depois de uma semana sem atividade. Nada foi apagado, Restaurar fica ao lado do nome e você tem um ano antes disso mudar.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":638,"title":639,"description":640,"published":641,"category":519,"image":642,"draft":523},"\u002Fblog\u002Fsafest-ai-app-builder","Qual builder de apps com IA é mais seguro? 30.998 apps testados","Qual builder de apps com IA é mais seguro? Escaneamos 30.998 apps no ar do Lovable, Base44, Replit, v0 e Bolt. O builder não é o que decide sua nota.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":554,"title":5,"description":522,"published":555,"category":519,"image":541,"draft":523},{"path":111,"title":645,"description":646,"published":647,"category":519,"image":648,"draft":523},"Supabase \"RLS disabled in public\": o que o aviso não vê","O Supabase marca \"RLS disabled in public\" como erro. Ele não diz nada sobre a política de leitura que deixa a sua tabela igualmente aberta.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":650,"title":651,"description":652,"published":653,"category":519,"image":654,"draft":523},"\u002Fblog\u002Frotate-supabase-service-role-key","Como rotacionar uma chave service_role do Supabase vazada","O Supabase manda fechar o vazamento primeiro. Outros guias mandam rotacionar agora. O que vale depende de para onde a sua chave service_role vazou.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":656,"title":657,"description":658,"published":659,"category":519,"image":660,"draft":523},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Scanners de segurança para vibe coding comparados, o nosso incluído","O melhor scanner de segurança para vibe coding depende de três perguntas que nenhuma lista de recursos responde. Dez ferramentas comparadas, com preços.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":662,"title":663,"description":664,"published":665,"category":519,"image":666,"draft":523},"\u002Fblog\u002Fsupabase-security-checker","Supabase security checker: faça você mesmo as cinco verificações","Um Supabase security checker lê o seu app publicado em vez das configurações do projeto. Aqui estão as cinco verificações e como fazer cada uma sozinho.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":668,"title":669,"description":670,"published":671,"category":519,"image":672,"draft":523},"\u002Fblog\u002Fvibe-coding-security-scanner","Scanner de segurança para vibe coding: o que ele não vê","Um scanner de segurança para vibe coding lê seu app no ar, de fora. O que isso cobre, as quatro coisas que ele não consegue ver e como ler o resultado.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":674,"title":675,"description":676,"published":677,"category":519,"image":678,"draft":523},"\u002Fblog\u002Fmissing-security-headers","Cabeçalhos de segurança faltando: quando isso importa","Cabeçalhos de segurança faltando é o achado que nosso scanner mais imprime. Contra o que eles protegem e quando são a linha menos urgente do relatório.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":680,"title":681,"description":682,"published":683,"category":519,"image":684,"draft":523},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","Sua chave de API da OpenAI está exposta no frontend. Troque-a.","Uma chave de API da OpenAI exposta no frontend não pode ser presa a um domínio. Troque-a hoje, mova a chamada para o seu servidor e limite o gasto.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":686,"title":687,"description":688,"published":689,"category":519,"image":690,"draft":523},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","Chave de API exposta no frontend: o que 30.998 apps entregam","Uma chave de API exposta no seu frontend costuma ser uma chave do Google Maps. Escaneamos 30.998 apps vibe-coded e contamos quais segredos vazam de verdade.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":692,"title":693,"description":694,"published":695,"category":569,"image":696,"draft":523},"\u002Fblog\u002Fsupabase-backup-tools-compared","Ferramentas de backup do Supabase comparadas, a nossa incluída","Quatro tipos de ferramenta de backup do Supabase, o que cada uma copia de verdade e quando uma GitHub Action gratuita ganha de pagar, nós inclusive.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":698,"title":699,"description":700,"published":701,"category":519,"image":702,"draft":523},"\u002Fblog\u002Freplit-secrets-explained","Como usar secrets no Replit, e o que ainda assim é publicado","Como usar secrets no Replit: adicionar um, ler de volta e resolver as duas causas do undefined. E as chaves que a ferramenta Secrets não consegue proteger.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":433,"title":704,"description":705,"published":706,"category":569,"image":707,"draft":523},"Backups do plano gratuito do Supabase: como fazer sem terminal","No plano gratuito do Supabase não existe backup nenhum: a cópia é você que faz. Como fazer uma pelo painel e o que a rota do CSV deixa para trás.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":709,"title":710,"description":711,"published":712,"category":519,"image":713,"draft":523},"\u002Fblog\u002Fis-supabase-secure","O Supabase é seguro? É. Seu projeto é outra pergunta","O Supabase é seguro? A plataforma é auditada, criptografada e passa por pentests. A documentação deles diz onde isso termina e começam suas configurações.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":390,"title":715,"description":716,"published":717,"category":519,"image":718,"draft":523},"Onde ficam as chaves de API do Supabase: anon, service_role e URL","A URL do projeto, a chave anon e a chave service_role ficam todas numa página do painel. Aqui está onde ela fica, e qual dos quatro valores vai no seu app.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":284,"title":720,"description":721,"published":722,"category":519,"image":723,"draft":523},"New row violates row-level security policy no Supabase. E agora?","\"New row violates row-level security policy\" significa que o Supabase recusou uma escrita. O conserto rápido reabre a tabela para qualquer um.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":725,"title":726,"description":727,"published":728,"category":519,"image":729,"draft":523},"\u002Fblog\u002Fcors-wildcard-security-risk","Um curinga CORS é um risco de segurança? Quase nunca.","Um curinga CORS é um risco de segurança? Em geral é o padrão do seu builder e não entrega nada que o seu servidor já não desse a qualquer um que pedisse.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":731,"title":732,"description":733,"published":734,"category":569,"image":735,"draft":523},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Branching do Supabase não é backup. Ele só anda para a frente.","Por que o branching do Supabase não é backup: um branch começa sem os seus dados e um merge só leva o esquema. Para que ele serve e o que usar no lugar.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":737,"title":738,"description":739,"published":740,"category":569,"image":741,"draft":523},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Como restaurar um backup do Supabase, e o que quebra depois","Como restaurar um backup do Supabase pelo painel ou por um arquivo de dump, o que a restauração substitui e por que o seu app pode continuar quebrado no fim.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":743,"title":744,"description":745,"published":746,"category":519,"image":747,"draft":523},"\u002Fblog\u002Fsupabase-storage-bucket-public","Seu bucket do Supabase Storage é público. Isso é um problema?","Um bucket público do Supabase Storage significa que quem tem a URL de um arquivo pode abri-lo. Não significa que alguém possa listar o que está lá dentro.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":749,"title":750,"description":751,"published":752,"category":519,"image":753,"draft":523},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Uma chave de API do Google no frontend é um problema?","Uma chave de API do Google exposta no seu frontend é a chave que nosso scanner mais encontra, e quase sempre está tudo bem. Um ajuste gratuito decide isso.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":755,"title":756,"description":757,"published":758,"category":569,"image":759,"draft":523},"\u002Fblog\u002Fai-agent-deleted-my-database","Um agente de IA apagou meus dados do Supabase. O que eu recupero?","Um agente de IA apagou dados do seu banco. O que você recupera já estava decidido antes de ele rodar, e os próximos minutos decidem o resto.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":403,"title":761,"description":762,"published":763,"category":519,"image":764,"draft":523},"Qualquer um consegue ler seu banco Supabase? Testamos 3.680 apps","Qualquer um consegue ler seu banco de dados Supabase sem fazer login? Escaneamos 30.998 apps no ar criadas com builders de IA e medimos quantas dizem que sim.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":766,"title":767,"description":768,"published":763,"category":519,"image":769,"draft":523},"\u002Fblog\u002Fsource-maps-exposed-in-production","Source maps expostos: seu app está publicando o código original","Um source map exposto deixa qualquer um ler o código original do seu app, comentários incluídos. A verificação de 30 segundos e o que importa de verdade.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":771,"title":772,"description":773,"published":774,"category":519,"image":775,"draft":523},"\u002Fblog\u002Fsupabase-new-api-keys","As novas chaves de API do Supabase: qual vai no seu app?","O Supabase trocou anon e service_role por chaves publicáveis e secretas. Qual delas pertence ao seu app e qual nunca deve estar lá?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":428,"title":777,"description":778,"published":779,"category":569,"image":780,"draft":523},"O Supabase faz backup do meu banco de dados? Depende do plano.","O Supabase faz backup do seu banco de dados? Todo dia nos planos pagos, e nada no gratuito. Como descobrir o que você tem e o que essa cópia não cobre.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":782,"title":783,"description":784,"published":785,"category":519,"image":786,"draft":523},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","O Supabase Row Level Security está ligado. A tabela continua pública.","Ligar o Supabase Row Level Security não protege uma tabela. Quem protege são as políticas, e a que consertou o seu app pode deixar qualquer um entrar.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":788,"title":789,"description":790,"published":785,"category":569,"image":791,"draft":523},"\u002Fblog\u002Fversion-history-is-not-a-backup","O histórico de versões não é backup. Ele não desfaz um delete.","Lovable e Bolt guardam um histórico de versões do seu código. Seu banco de dados é um serviço à parte, e voltar atrás não traz os seus dados de volta.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":793,"title":794,"description":795,"published":796,"category":569,"image":797,"draft":523},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Três formas de fazer backup de um banco Supabase, e o que falta","O painel, o pg_dump e um serviço gerenciado. O que cada um salva de verdade, o que deixa de fora sem avisar e qual sobrevive a perder a conta.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":385,"title":799,"description":800,"published":796,"category":519,"image":801,"draft":523},"Quais chaves de API são seguras no navegador e quais não são","Sua chave anon do Supabase foi feita para ser pública. Sua chave service_role não, e ela ignora todas as regras que você criar. Como diferenciar as duas.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1790150954293]