[{"data":1,"prerenderedAt":959},["ShallowReactive",2],{"blog-es-storage-upload-violates-row-level-security":3,"blog-index-es":602},{"id":4,"title":5,"body":6,"category":558,"cover":559,"coverAlt":560,"description":561,"draft":562,"extension":563,"faq":564,"image":580,"keywords":581,"meta":589,"navigation":590,"ogTitle":591,"path":592,"published":593,"seo":594,"stem":595,"tldr":596,"updated":593,"__hash__":601},"blog_es\u002Fblog\u002Fstorage-upload-violates-row-level-security.md","\"Row-level security policy for table objects\" al subir",{"type":7,"value":8,"toc":545},"minimark",[9,13,24,31,39,44,51,57,70,74,77,87,99,105,109,112,118,121,129,133,136,142,153,156,172,179,259,262,267,271,274,277,283,289,292,298,312,319,326,330,333,339,348,355,362,365,371,384,389,395,399,402,405,408,418,422,425,434,454,463,480,483,487,532],[10,11,12],"p",{},"Tu app sube un archivo. Funcionaba en la vista previa de tu builder, o\nfuncionaba la semana pasada, y ahora cada intento vuelve con una frase sobre\nrow-level security:",[14,15,20],"pre",{"className":16,"code":18,"language":19},[17],"language-text","new row violates row-level security policy for table \"objects\"\n","text",[21,22,18],"code",{"__ignoreMap":23},"",[10,25,26,27,30],{},"Casi toda esa frase te sonará si ya pasaste por esto en una tabla tuya. Lo\ndistinto es la última palabra, porque ",[21,28,29],{},"objects"," no es una tabla que tú hayas\ncreado.",[10,32,33,34,38],{},"Esta es la parte que guía tras guía cuenta mal: ",[35,36,37],"strong",{},"la primera solución que vas a\nencontrar es hacer público el bucket, y no hace nada por las subidas."," La\npropia documentación de Supabase lo dice en una línea. Ese interruptor deja la\nsubida rechazada y abre los archivos que ya estaban dentro.",[40,41,43],"h2",{"id":42},"qué-significa-new-row-violates-row-level-security-policy-for-table-objects","Qué significa \"new row violates row-level security policy for table objects\"",[10,45,46,47,50],{},"Tu subida llegó a Supabase Storage, Storage preguntó a las reglas puestas sobre\nuna tabla llamada ",[21,48,49],{},"storage.objects"," si ese archivo podía entrar, no encontró\nninguna que dijera que sí, y la rechazó.",[10,52,53,54,56],{},"La fila del mensaje existe de verdad. Storage guarda una fila en\n",[21,55,49],{}," por cada archivo que tiene, con el nombre del archivo, el\nbucket en el que está y quién lo puso ahí. Escribir un archivo es escribir esa\nfila, así que las reglas de esa tabla deciden si la subida llega a ocurrir. No\nse perdió nada: no se guardó ningún archivo, y el resto del bucket está\nexactamente como hace un minuto.",[10,58,59,60,63,64,69],{},"La redacción viene de Postgres, la base de datos que hay debajo de Supabase, y\npor eso se lee como maquinaria. Lleva el código ",[21,61,62],{},"42501",", el mismo que\n",[65,66,68],"a",{"href":67},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","un guardado rechazado en una de tus propias tablas",".",[40,71,73],{"id":72},"por-qué-el-mensaje-nombra-objects-y-no-tu-bucket","Por qué el mensaje nombra \"objects\" y no tu bucket",[10,75,76],{},"Porque Storage guarda las reglas de todos los buckets de tu proyecto en esa\núnica tabla.",[10,78,79,80,82,83,86],{},"Un bucket ordena archivos. No tiene reglas propias, y no hay ningún editor de\npolicies colgando de él. ",[21,81,49],{}," es donde viven las reglas, para todos\ntus buckets a la vez, y ",[21,84,85],{},"bucket_id"," es una columna suya. Así que una regla que\ndice \"solo en el bucket avatars\" se escribe como una condición sobre esa\ncolumna.",[10,88,89,90,93,94,96,97,69],{},"Por eso tampoco ayudó la regla de tabla que escribiste la semana pasada. Una\nregla sobre ",[21,91,92],{},"profiles"," es una regla sobre filas de ",[21,95,92],{},", y un archivo es\nuna fila de ",[21,98,49],{},[100,101],"diagram",{"alt":102,"caption":103,"src":104},"Tres buckets uno al lado de otro, cada uno con una flecha que baja hacia un panel ancho rotulado storage.objects que lleva tres fichas de policy y un nombre de columna. A la izquierda, al otro lado de una línea discontinua, una tarjeta más apagada rotulada profiles tiene sus propias filas y su propia ficha insert, sin ninguna línea que la una a nada.","Todos los buckets de tu proyecto se gobiernan desde la misma tabla. Las reglas que escribiste en tus propias tablas están al otro lado de esa línea y nunca se encuentran con un archivo.","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fone-table-every-bucket-1600x720.png",[40,106,108],{"id":107},"tengo-que-hacer-público-el-bucket-para-poder-subir","¿Tengo que hacer público el bucket para poder subir?",[10,110,111],{},"No. Detrás de un bucket hay dos preguntas distintas, y el interruptor solo\nresponde a una. Quién puede sacar un archivo lo decide público. Quién puede\nmeter uno es el tema de tu error, y la documentación de Supabase es explícita en\nque el ajuste no llega hasta ahí. De la página que describe las dos clases de\nbucket, leída el 11 de octubre de 2026:",[113,114,115],"blockquote",{},[10,116,117],{},"El control de acceso se sigue aplicando a otros tipos de operación, incluidos\nsubir, borrar, mover y copiar.",[10,119,120],{},"Lo que público sí hace está dicho con la misma claridad en esa página:\ncualquiera que tenga la dirección de un archivo puede abrirlo sin iniciar\nsesión. El ajuste no es nada más que eso.",[10,122,123,124,128],{},"Así que cambiarlo te deja en el único estado que nadie quiere. La subida sigue\nrechazada, porque subir nunca fue lo que el ajuste controlaba, y los archivos\nque ya estaban en el bucket los puede abrir ahora cualquiera que tenga sus\ndirecciones.\n",[65,125,127],{"href":126},"\u002Fblog\u002Fsupabase-storage-bucket-public","Lo que de verdad te cuesta un bucket público","\nes una pregunta distinta de este error, y vale la pena leerla antes de tocar el\ninterruptor.",[40,130,132],{"id":131},"qué-comprueba-de-verdad-un-bucket-cuando-subes","Qué comprueba de verdad un bucket cuando subes",[10,134,135],{},"Una regla, y se llama insert.",[10,137,138,139,141],{},"La página de control de acceso de Supabase deja claro el valor por defecto: sin\npolicies, Storage no permite ninguna subida a un bucket, y tú permites\noperaciones de una en una escribiéndolas sobre ",[21,140,49],{},". Después nombra\nla que necesitas:",[113,143,144],{},[10,145,146,147,150,151,69],{},"Por ejemplo, la única policy de RLS necesaria para subir objetos es conceder\nel permiso ",[21,148,149],{},"INSERT"," sobre la tabla ",[21,152,49],{},[10,154,155],{},"Hay una segunda mitad, y es el motivo más común por el que una regla insert no\nquita el error:",[113,157,158],{},[10,159,160,161,164,165,168,169,69],{},"Para permitir sobrescribir archivos mediante la funcionalidad ",[21,162,163],{},"upsert","\ntendrás que conceder además los permisos ",[21,166,167],{},"SELECT"," y ",[21,170,171],{},"UPDATE",[10,173,174,175,178],{},"Si tu subida pasa ",[21,176,177],{},"upsert: true",", que pide a Storage reemplazar un archivo del\nmismo nombre cuando ya hay uno, entonces una regla insert sola no basta.\nReemplazar un archivo son tres preguntas en vez de una: puedes añadir esta fila,\npuedes ver la que está, y puedes cambiarla.",[180,181,182,197],"table",{},[183,184,185],"thead",{},[186,187,188,192],"tr",{},[189,190,191],"th",{},"Lo que tu app le pide a Storage",[189,193,194,195],{},"Lo que necesita sobre ",[21,196,49],{},[198,199,200,212,231,240,249],"tbody",{},[186,201,202,206],{},[203,204,205],"td",{},"subir un archivo nuevo",[203,207,208,209],{},"una regla ",[21,210,211],{},"insert",[186,213,214,220],{},[203,215,216,217,219],{},"reemplazar un archivo del mismo nombre (",[21,218,163],{},")",[203,221,222,224,225,168,228],{},[21,223,211],{},", más ",[21,226,227],{},"select",[21,229,230],{},"update",[186,232,233,236],{},[203,234,235],{},"abrir un archivo de un bucket privado",[203,237,208,238],{},[21,239,227],{},[186,241,242,245],{},[203,243,244],{},"listar lo que hay en un bucket",[203,246,208,247],{},[21,248,227],{},[186,250,251,254],{},[203,252,253],{},"borrar un archivo",[203,255,208,256],{},[21,257,258],{},"delete",[10,260,261],{},"No tienes que escribir las cinco. Escribe las que tu app hace de verdad, que\npara la mayoría de las subidas es la primera fila y a veces la segunda.",[100,263],{"alt":264,"caption":265,"src":266},"Un almacén de archivos con tapa y dos aberturas en su pared derecha. La abertura de arriba tiene una barra echada, y un documento que llega de fuera lo rechaza una cruz. La de abajo tiene la barra levantada, y un archivo sale por ella hacia una figura que espera junto a una marca de visto. Un interruptor debajo se une con una sola línea a la abertura de abajo y a nada más.","Un almacén, dos aberturas. El interruptor está cableado a la de abajo. Una subida llega a la de arriba, donde una regla que nadie ha escrito todavía decide si entra.","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Ftwo-counters-1600x720.png",[40,268,270],{"id":269},"la-regla-que-deja-subir-a-tu-app-y-solo-a-tu-app","La regla que deja subir a tu app, y solo a tu app",[10,272,273],{},"Nombra el bucket, y di para quién vale la regla.",[10,275,276],{},"El punto de partida de la documentación limita una subida a un bucket y a\nvisitantes con sesión iniciada:",[14,278,281],{"className":279,"code":280,"language":19},[17],"create policy \"Allow authenticated uploads\"\non storage.objects\nfor insert\nto authenticated\nwith check (bucket_id = 'my_bucket_id');\n",[21,282,280],{"__ignoreMap":23},[10,284,285,288],{},[21,286,287],{},"to authenticated"," es la parte que conviene no saltarse. Significa que la regla\nse aplica a visitantes con sesión iniciada; quítala y la regla se aplica a todo\nel mundo, desconocidos incluidos.",[10,290,291],{},"Para cualquier cosa que pertenezca a una persona concreta, la versión que\npublica Supabase pone los archivos de cada persona en una carpeta con su nombre:",[14,293,296],{"className":294,"code":295,"language":19},[17],"create policy \"Allow authenticated uploads\"\non storage.objects\nfor insert\nto authenticated\nwith check (\n  bucket_id = 'my_bucket_id' and\n  (storage.foldername(name))[1] = (select auth.jwt()->>'sub')\n);\n",[21,297,295],{"__ignoreMap":23},[10,299,300,303,304,307,308,311],{},[21,301,302],{},"storage.foldername(name)"," parte la ruta de un archivo guardado en sus carpetas,\nasí que ",[21,305,306],{},"[1]"," es la primera. ",[21,309,310],{},"auth.jwt()->>'sub'"," es el id de quien tiene la\nsesión iniciada y hace la petición. Leídas juntas, las dos líneas dicen que\npuedes poner un archivo en la carpeta con tu nombre, en ese bucket, y en ningún\notro sitio.",[10,313,314,315,318],{},"Los dos son ejemplos de Supabase y no nuestros, leídos el 11 de octubre de 2026,\ncon ",[21,316,317],{},"my_bucket_id"," donde ellos lo dejaron para que veas qué parte es el nombre\nde tu propio bucket.",[10,320,321,322,69],{},"Si prefieres ver el resultado desde fuera, nuestro escaneo gratuito le pregunta\na tu proyecto en vivo cuáles de tus buckets le entregarán su contenido a un\ndesconocido. Tarda unos 20 segundos y no necesita cuenta:\n",[65,323,325],{"href":324},"\u002Fsecurity-scanner","escanea tu app",[40,327,329],{"id":328},"lo-que-una-regla-de-lectura-entrega-sin-que-se-lo-pidan","Lo que una regla de lectura entrega sin que se lo pidan",[10,331,332],{},"Listar un bucket y descargar de él son el mismo privilegio, así que una regla\nescrita para que tus descargas funcionen hace también que el contenido del\nbucket se pueda listar.",[10,334,335,336,338],{},"La página de funciones de ayuda de Supabase lo dice directamente: un solo\nprivilegio de SQL como ",[21,337,167],{}," lo usan varias acciones de Storage. La página de\ncontrol de acceso avisa después del caso concreto, bajo un ejemplo que abre a\ntodo el mundo un bucket de avatares:",[113,340,341],{},[10,342,343,344,347],{},"El filtro ",[21,345,346],{},"allow_any_operation()"," es crítico aquí, porque sin él los usuarios\npodrían listar el contenido del bucket.",[10,349,350,351,354],{},"Ese es el hueco que medimos desde fuera. Hemos escaneado 8.435 apps en vivo que\nnombran un proyecto de Supabase. La comprobación de buckets obtuvo respuesta en\n4.703 de ellas, y ",[35,352,353],{},"792 de esas respondieron a nuestra petición de listado con\nlos nombres de lo que tenían dentro",", sin nadie con la sesión iniciada. Eso es\nalrededor de una de cada seis de las apps a las que pudimos preguntar.",[10,356,357,358,361],{},"Muchas veces basta con un nombre, porque un bucket que lista le ahorra a un\ndesconocido el trabajo de adivinar nombres de archivo.\n",[21,359,360],{},"invoice-2026-03-hannah.pdf"," dice de quién es el archivo antes de que nadie lo\nabra.",[10,363,364],{},"El arreglo que Supabase documenta es decir para qué acción de Storage vale la\nregla:",[14,366,369],{"className":367,"code":368,"language":19},[17],"create policy \"Allow users to list their own objects\"\non storage.objects\nfor select\nto authenticated\nusing (\n  storage.allow_only_operation('object.list')\n  and owner_id = (select auth.uid()::text)\n);\n",[21,370,368],{"__ignoreMap":23},[10,372,373,376,377,380,381,383],{},[21,374,375],{},"storage.allow_only_operation"," y su hermana ",[21,378,379],{},"storage.allow_any_operation"," son la\nforma en que una regla ",[21,382,227],{}," se estrecha a una de las acciones que comparten\nel privilegio. Sin una de las dos, una regla que escribiste para que tu app\npudiera enseñar una imagen es también una regla que leerá en voz alta todo lo\nque hay en el bucket.",[100,385],{"alt":386,"caption":387,"src":388},"Una caja rotulada select de la que salen dos ramas. La rama de arriba llega a un documento suelto, que pasa a una figura junto a una marca de visto. La rama de abajo atraviesa una placa estrecha dibujada con trazo discontinuo y llega a una pila de seis filas encendidas, marcada con una cruz.","Una regla, dos acciones distintas de Storage. La placa del trayecto de abajo es el filtro de acción, y el trazo discontinuo es cómo se ve cuando nadie escribió ninguno.","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fone-rule-two-actions-1600x700.png",[10,390,391,394],{},[65,392,393],{"href":126},"Si un bucket que se puede listar es un problema para tu app","\ndepende de lo que haya dentro, y esa es una pregunta que el resultado del\nescaneo no puede responder por ti.",[40,396,398],{"id":397},"cuándo-público-es-la-respuesta-correcta","Cuándo público es la respuesta correcta",[10,400,401],{},"Cuando los archivos están pensados para que los vea cualquiera que los pida, que\nes una categoría real y de la que Supabase da sus propios ejemplos.",[10,403,404],{},"Los casos de uso que Supabase cita para un bucket público son fotos de perfil,\nmedios públicos y contenido de entradas de blog. Son archivos que tu app enseña\na un visitante sin sesión iniciada, y servirlos desde un bucket público es\nademás más rápido, porque las dos clases de bucket se cachean de forma distinta.",[10,406,407],{},"Para la otra clase, la documentación nombra dos maneras de sacar un archivo de\nun bucket privado: una descarga que lleva el token de la persona con sesión\niniciada, o un enlace firmado que funciona un tiempo limitado. Las dos dejan la\ndecisión en tus reglas en vez de en quien encontró la dirección.",[409,410,412],"callout",{"type":411},"warn",[10,413,414,417],{},[35,415,416],{},"Los buckets son privados por defecto."," Un bucket que creaste y en el que no\nvolviste a pensar ya está en el más estricto de los dos estados, lo que\nsignifica que el error que estás leyendo es el comportamiento previsto. Escribe\nla regla y la subida pasa; el interruptor no tiene nada que decir en esa\npregunta, ni para un lado ni para el otro.",[40,419,421],{"id":420},"cómo-mantener-bien-el-bucket-después-de-hoy","Cómo mantener bien el bucket después de hoy",[10,423,424],{},"Una vez correctas las reglas, se mueven dos cosas: alguien cambia el interruptor\nmientras persigue un fallo sin relación, y un archivo desaparece.",[10,426,427],{},[35,428,429,433],{},[65,430,432],{"href":431},"\u002Fpricing","Reeve Monitor"," vuelve a pasar las nueve comprobaciones externas por ti:",[435,436,437,441,444,451],"ul",{},[438,439,440],"li",{},"las nueve comprobaciones cada hora, en hasta tres apps, incluida la del listado de buckets",[438,442,443],{},"si la app responde, cada 60 segundos",[438,445,446,447,450],{},"un mensaje cuando un resultado ",[35,448,449],{},"cambia",", para que un bucket que se abrió anoche no espere a que mires",[438,452,453],{},"un informe mensual de lo que vio",[10,455,456],{},[35,457,458,462],{},[65,459,461],{"href":460},"\u002Fsupabase-backups","Reeve Care"," guarda una copia de lo que hay dentro:",[435,464,465,468,471,474,477],{},[438,466,467],{},"una copia cifrada de tu base de datos de Supabase cada noche, guardada donde tu proyecto no llega",[438,469,470],{},"cada copia verificada antes de contar, contando las filas de cada tabla",[438,472,473],{},"también tus archivos subidos, en cuanto conectes un acceso de Storage",[438,475,476],{},"una restauración en un clic cuando la necesites",[438,478,479],{},"todo lo que hace Monitor",[10,481,482],{},"Los dos están en la página de precios, que a veces está por debajo de la cifra\nde lista de aquí y nunca por encima.",[40,484,486],{"id":485},"qué-hacer-hoy","Qué hacer hoy",[488,489,490],"key-takeaways",{},[435,491,492,495,511,521,524],{},[438,493,494],{},"Lee el mensaje como un rechazo. El archivo no se guardó, el bucket está igual, y no hay nada que recuperar.",[438,496,497,498,500,501,503,504,506,507,510],{},"Añade una regla ",[21,499,211],{}," sobre ",[21,502,49],{}," que nombre tu bucket en ",[21,505,85],{}," y lleve la cláusula ",[21,508,509],{},"TO"," que querías.",[438,512,174,513,515,516,168,518,520],{},[21,514,177],{},", añade también ",[21,517,227],{},[21,519,230],{},", o la regla insert sola no quitará el error.",[438,522,523],{},"Deja el interruptor de público donde está mientras haces esto. Sobre las subidas no tiene nada que decir, y sobre quién puede abrir lo que ya está guardado sí que lo tiene.",[438,525,526,527,500,529,531],{},"Lee cada regla ",[21,528,227],{},[21,530,49],{}," y pregúntate qué permite además de la descarga para la que la escribiste. El listado comparte ese privilegio.",[10,533,534,535,539,540,544],{},"Empieza por el bucket del que vino el error, y mira después los otros buckets\ndel mismo proyecto, porque una regla escrita amplia una vez suele haberse pegado\ndos. La ",[65,536,538],{"href":537},"\u002Fchecklist","checklist de seguridad en 10 minutos"," cubre qué más suele\nquedarse abierto en una app recién lanzada, y la\n",[65,541,543],{"href":542},"\u002Fis-your-supabase-app-safe","guía de seguridad de Supabase"," repasa el resto de\nlo que puede alcanzar un desconocido.",{"title":23,"searchDepth":546,"depth":546,"links":547},3,[548,550,551,552,553,554,555,556,557],{"id":42,"depth":549,"text":43},2,{"id":72,"depth":549,"text":73},{"id":107,"depth":549,"text":108},{"id":131,"depth":549,"text":132},{"id":269,"depth":549,"text":270},{"id":328,"depth":549,"text":329},{"id":397,"depth":549,"text":398},{"id":420,"depth":549,"text":421},{"id":485,"depth":549,"text":486},"Fundamentos de seguridad","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcover-1200x630.png","Una trampilla de entrega con una barra echada y un documento fuera, y detrás una estantería de archivos con una tapa sobre el borde.","\"New row violates row-level security policy for table objects\" significa que tu subida no tiene regla insert. Hacer público el bucket no añade ninguna.",false,"md",[565,568,571,574,577],{"q":566,"a":567},"¿Por qué mi subida a Supabase falla con un error de row-level security?","Porque Supabase Storage preguntó a las reglas puestas sobre una tabla llamada storage.objects si tu archivo podía entrar, y no encontró ninguna que dijera que sí. Storage escribe una fila en esa tabla por cada archivo que guarda, y Row Level Security se aplica a esa fila igual que a una fila de cualquier otra tabla. No se guardó ningún archivo y nada de lo que ya estaba en el bucket cambió. El mensaje lleva el código de Postgres 42501, el mismo que cuando se rechaza un guardado en una tabla tuya.",{"q":569,"a":570},"¿Tengo que hacer público mi bucket para poder subir?","No, y hacerlo público no ayuda. Supabase documenta que el control de acceso se sigue aplicando a subir, borrar, mover y copiar, esté el bucket como esté. Público cambia una sola cosa: si alguien que tiene la dirección de un archivo puede abrirlo sin iniciar sesión. Así que el interruptor deja tu subida rechazada y hace que los archivos que ya estaban dentro los pueda abrir cualquiera que tenga su dirección.",{"q":572,"a":573},"¿Qué policies necesita un bucket?","Una subida necesita una regla insert sobre storage.objects. Si tu código reemplaza archivos del mismo nombre, que es lo que hace upsert, Supabase dice que también necesitas select y update. Abrir un archivo en un bucket privado necesita una regla select, y listar lo que hay en el bucket también, porque esas dos acciones de Storage corren sobre el mismo privilegio de SQL. Borrar necesita una regla delete. No hay obligación de escribir las cuatro, solo las que tu app hace de verdad.",{"q":575,"a":576},"¿Es peligroso un bucket público?","Depende por completo de lo que haya dentro. Público es el ajuste correcto para fotos de perfil, logos y cualquier otra cosa que tu app enseñe a un visitante que no ha iniciado sesión, que es justo lo que Supabase lista como sus propios casos de uso. Es el ajuste equivocado para facturas, exportaciones o cualquier cosa que pertenezca a una persona concreta, y para eso quieres un bucket privado con un enlace firmado. La pregunta nunca fue si público es malo.",{"q":578,"a":579},"¿Cómo compruebo si mi bucket se puede listar?","Pregúntaselo desde fuera, sin ninguna cuenta iniciada, exactamente como haría un desconocido. El listado lo concede una regla select y no el interruptor de público, así que ni el interruptor del panel ni un vistazo a tu lista de policies responden a eso. Nuestro escaneo gratuito lo hace sobre tu proyecto en vivo y te dice cuáles de tus buckets respondieron con los nombres de lo que tenían dentro.","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",[582,583,584,585,586,587,588],"new row violates row-level security policy for table objects","error rls subida supabase storage","supabase storage policy subir","supabase bucket upload 403","storage objects rls supabase","supabase subida permiso denegado","ejemplo policy supabase storage",{},true,"\"Row-level security policy for table objects\"","\u002Fblog\u002Fstorage-upload-violates-row-level-security","2026-10-11",{"title":5,"description":561},"blog\u002Fstorage-upload-violates-row-level-security",[597,598,599,600],"\"New row violates row-level security policy for table objects\" significa que tu subida llegó a Supabase Storage y ninguna regla sobre storage.objects la dejó entrar. El archivo no se guardó, y el resto del bucket sigue intacto.","Storage guarda sus reglas en una sola tabla para todos los buckets de tu proyecto, y por eso el mensaje nombra una tabla que tú nunca creaste.","Hacer público el bucket no lo resuelve. Supabase comprueba las subidas igualmente, y público solo decide quién puede abrir un archivo cuya dirección ya tiene.","Una subida necesita una regla insert sobre storage.objects. Si tu código guarda con upsert, también necesita select y update.","G-N2DGC2p_XJOWd6vW-6JuXjJRoL0sC6C1gYrdPbVs0",[603,604,610,616,622,628,634,640,646,652,658,664,670,676,683,689,695,700,706,712,718,724,730,736,742,748,754,760,766,772,778,784,790,796,802,808,814,820,826,832,838,844,850,856,862,868,874,879,885,891,897,902,908,914,920,925,931,937,943,948,954],{"path":592,"title":5,"description":561,"published":593,"category":558,"image":580,"draft":562},{"path":605,"title":606,"description":607,"published":608,"category":558,"image":609,"draft":562},"\u002Fblog\u002Fbase44-security-scan","Escaneo de seguridad de Base44: lo que solo él ve","El escaneo de seguridad de Base44 revisa siete tipos de problema desde dentro. Esta es la mitad que lee y nadie más puede leer, y la mitad que nunca mira.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":611,"title":612,"description":613,"published":614,"category":558,"image":615,"draft":562},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Tu clave API se filtró. El orden en el que hay que actuar","Una clave API se filtró y no sabes por dónde empezar. No todas las claves de tu frontend lo son, y el orden importa más que la velocidad.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":617,"title":618,"description":619,"published":620,"category":558,"image":621,"draft":562},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","\"Infinite recursion detected in policy\" sin desactivar RLS","\"Infinite recursion detected in policy for relation\" significa que tu policy preguntó a la tabla que protege. Así se rompe el círculo.","2026-10-08","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",{"path":623,"title":624,"description":625,"published":626,"category":558,"image":627,"draft":562},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" en Supabase, y el arreglo equivocado","\"No API key found in request\" significa que tu petición llegó a Supabase sin clave. Casi todas las respuestas apuntan a las reglas de tu base de datos.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":629,"title":630,"description":631,"published":632,"category":558,"image":633,"draft":562},"\u002Fblog\u002Fis-base44-safe","¿Es seguro Base44? Lo que vimos en 5.442 apps Base44","¿Es seguro Base44? Pasamos nueve comprobaciones a 5.442 apps Base44 en producción. Casi todas sacaron B por motivos que su dueño nunca eligió.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":635,"title":636,"description":637,"published":638,"category":558,"image":639,"draft":562},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","Ocultar una clave API: muévela a una Edge Function de Supabase","Ocultar una clave API significa sacarla del navegador, y una Edge Function de Supabase es el sitio más pequeño donde ponerla. Dos pasos importan más.","2026-10-05","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":641,"title":642,"description":643,"published":644,"category":558,"image":645,"draft":562},"\u002Fblog\u002Fenv-file-exposed-on-your-server","¿Tu archivo .env está expuesto? Las doce rutas a revisar","¿Tu archivo .env está expuesto en tu propio servidor web? Doce direcciones te lo dicen, y un acierto significa que todo lo que contiene ya es público.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":647,"title":648,"description":649,"published":650,"category":558,"image":651,"draft":562},"\u002Fblog\u002Fis-v0-safe","Seguridad de v0: las 1.790 aplicaciones escaneadas sacaron una A","Seguridad de v0, medida en 1.790 aplicaciones v0 en vivo: todas sacaron A. Solo 17 nombraban una base de datos, y eso es casi todo lo que mide la A.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":653,"title":654,"description":655,"published":656,"category":558,"image":657,"draft":562},"\u002Fblog\u002Fis-bolt-safe","¿Es seguro Bolt? Lo que vimos en 1.123 aplicaciones Bolt","¿Es seguro Bolt? Pasamos 1.123 aplicaciones Bolt en vivo por nueve comprobaciones. El hosting salió limpio. Los hallazgos eran claves y tablas abiertas dentro.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":659,"title":660,"description":661,"published":662,"category":558,"image":663,"draft":562},"\u002Fblog\u002Fis-supabase-down-or-your-app","¿Supabase está caído o es tu app? Cómo distinguirlo","¿Supabase está caído o es tu app? Un proyecto pausado, una base de datos llena y un fallo tuyo parecen lo mismo. Cuatro comprobaciones los separan.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":665,"title":666,"description":667,"published":668,"category":558,"image":669,"draft":562},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","¿Supabase cifra mis datos? Sí. Esto es lo que detiene","¿Supabase cifra los datos? Sí: AES-256 en reposo, TLS en tránsito, SOC 2 e ISO 27001. Qué cubre cada uno, y la fuga que ninguno de ellos detiene.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":671,"title":672,"description":673,"published":674,"category":558,"image":675,"draft":562},"\u002Fblog\u002Fsupabase-free-plan-limits","¿Cuánto cuesta Supabase? Los límites del plan gratuito","Los límites del plan gratuito de Supabase: 500 MB de base de datos, 5 GB de egress y ningún backup. Qué pasa en cada uno y qué cambia Pro por $25.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":677,"title":678,"description":679,"published":680,"category":681,"image":682,"draft":562},"\u002Fblog\u002Ftest-your-supabase-backup","Prueba tu backup de Supabase antes del día que lo necesites","Cómo probar tu backup de Supabase: restaurarlo en un proyecto de prueba, contar filas, iniciar sesión y buscar la línea que le falta a un archivo cortado.","2026-09-28","Backups","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":684,"title":685,"description":686,"published":687,"category":681,"image":688,"draft":562},"\u002Fblog\u002Fsupabase-backup-github-action","Backup gratis de Supabase con una GitHub Action, y la trampa","Un backup de Supabase con GitHub Action es gratis y sirve a muchas apps. El workflow, el connection string correcto y el egress de cada ejecución.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":690,"title":691,"description":692,"published":693,"category":681,"image":694,"draft":562},"\u002Fblog\u002Fdownload-your-supabase-backup","Por qué no puedes descargar tu backup de Supabase","No puedes descargar tu backup de Supabase en un proyecto actual: la copia diaria es una instantánea física. Cómo comprobarlo y tener tu propia copia.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":696,"title":697,"description":698,"published":693,"category":558,"image":699,"draft":562},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": el grant que falta","Desde el 30 de octubre, una tabla nueva de Supabase responde \"permission denied for table\" hasta que le das acceso. El grant del email es la mitad del arreglo.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":701,"title":702,"description":703,"published":704,"category":558,"image":705,"draft":562},"\u002Fblog\u002Fopen-api-endpoint-exposed","¿Un endpoint de API abierto es un problema? Mira el JSON","Tu escaneo señaló un endpoint de API abierto. Que importe depende de lo que devolvió, y la mayoría de los que encontramos eran de la plataforma.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":707,"title":708,"description":709,"published":710,"category":558,"image":711,"draft":562},"\u002Fblog\u002Flovable-security-scan","Escaneo de seguridad de Lovable: lo que no puede probar","Escaneo de seguridad de Lovable: qué revisan el Quick scan y el Deep scan, cuándo corre cada uno, y lo único que ningún escaneo desde dentro puede probar.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":713,"title":714,"description":715,"published":716,"category":681,"image":717,"draft":562},"\u002Fblog\u002Fsupabase-backup-auth-users","Por qué tu dump de Supabase no tiene usuarios dentro","Ejecuta supabase db dump por sí solo y obtienes la forma de tu base de datos y ninguna de sus filas, sin el esquema auth donde viven tus usuarios.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":719,"title":720,"description":721,"published":722,"category":558,"image":723,"draft":562},"\u002Fblog\u002Fdomain-and-certificate-expiry","Dominio caducado, web caída: qué pasa a partir de ahora","Tu dominio caducó y tu web está caída. Aquí tienes el reloj que acaba de arrancar, por qué el certificado es el menor problema, y cómo comprobar ambos.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":725,"title":726,"description":727,"published":728,"category":558,"image":729,"draft":562},"\u002Fblog\u002Fis-lovable-safe","¿Es seguro Lovable? Lo que vimos en 18.554 aplicaciones Lovable","¿Es seguro Lovable? Pasamos 18.554 aplicaciones Lovable por nueve comprobaciones. La plataforma fue la más limpia de cinco. Los hallazgos estaban dentro.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":731,"title":732,"description":733,"published":734,"category":558,"image":735,"draft":562},"\u002Fblog\u002Fvibe-coded-app-security-checklist","La lista de seguridad del vibe coding, en nueve comprobaciones","Una lista de seguridad del vibe coding con nueve puntos, cada uno verificable en tu app desde fuera por cualquiera, y cada uno con una prueba de una línea.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":737,"title":738,"description":739,"published":740,"category":558,"image":741,"draft":562},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Una clave secreta de Stripe en tu frontend puede mover dinero","Una clave secreta de Stripe expuesta en tu frontend puede reembolsar, cobrar y leer cada ficha de cliente que tienes. Tu clave pk_live_ sí debe estar ahí.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":743,"title":744,"description":745,"published":746,"category":558,"image":747,"draft":562},"\u002Fblog\u002Fvite-and-next-public-env-vars","Variables de entorno de Vite expuestas: el prefijo dice publica esto","Variables de entorno de Vite expuestas en tu app: hicieron lo que pedía el prefijo. VITE_ y NEXT_PUBLIC_ significan publica esto, y la IA nunca supo el coste.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":749,"title":750,"description":751,"published":752,"category":558,"image":753,"draft":562},"\u002Fblog\u002Fbase44-source-maps","Seguridad en Base44: qué marca un escaneo y qué te toca arreglar a ti","Seguridad en Base44 en 5.438 apps escaneadas: tres hallazgos en casi todas son de la plataforma, el source map es la insignia de Base44 y lo tuyo es poco.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":755,"title":756,"description":757,"published":758,"category":558,"image":759,"draft":562},"\u002Fblog\u002Fis-cursor-ai-safe","¿Es seguro Cursor AI? El editor, el código y la app que publicaste","¿Es seguro Cursor AI? Tres preguntas en una búsqueda: qué guarda Cursor, en qué falla el código que escribe y si la app que publicaste está abierta.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":761,"title":762,"description":763,"published":764,"category":558,"image":765,"draft":562},"\u002Fblog\u002Fis-replit-safe","¿Es seguro Replit? Lo que vimos en 3.042 aplicaciones Replit en vivo","¿Es seguro Replit? Pasamos 3.042 aplicaciones Replit en vivo por nueve comprobaciones externas. Los hallazgos estaban en la aplicación publicada, no en el host.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":767,"title":768,"description":769,"published":770,"category":681,"image":771,"draft":562},"\u002Fblog\u002Fsupabase-storage-backup","Supabase storage backup: tu copia de la base no tiene archivos","Un Supabase storage backup es una tarea aparte. Las copias de la base guardan la lista de tus archivos y ninguno de ellos, así que cada upload queda roto.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":773,"title":774,"description":775,"published":776,"category":681,"image":777,"draft":562},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Point-in-time recovery de Supabase: precio y límites","El point-in-time recovery de Supabase rebobina tu base de datos a cualquier segundo de la última semana. Cuesta $100 al mes sobre Pro y solo cubre la base.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":779,"title":780,"description":781,"published":782,"category":681,"image":783,"draft":562},"\u002Fblog\u002Fsupabase-project-paused-recover","¿Proyecto de Supabase pausado? Tus datos siguen ahí","Supabase pausó tu proyecto tras una semana sin actividad. No se ha borrado nada, Restaurar está junto al nombre y tienes un año antes de que eso cambie.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":785,"title":786,"description":787,"published":788,"category":558,"image":789,"draft":562},"\u002Fblog\u002Fsafest-ai-app-builder","¿Qué builder de apps con IA es más seguro? 30.998 apps escaneadas","¿Qué builder de apps con IA es más seguro? Escaneamos 30.998 apps activas de Lovable, Base44, Replit, v0 y Bolt. El builder no es lo que decide tu nota.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":791,"title":792,"description":793,"published":794,"category":558,"image":795,"draft":562},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Activa Row Level Security en cada tabla de Supabase y compruébalo","Activar Row Level Security en Supabase sin política cierra la tabla del todo. Una política sin el interruptor no hace nada. Aquí tienes el SQL y la prueba.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":797,"title":798,"description":799,"published":800,"category":558,"image":801,"draft":562},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": lo que el aviso no ve","Supabase marca \"RLS disabled in public\" como error. No dice nada de la política de lectura que deja tu tabla igual de abierta a cualquiera.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":803,"title":804,"description":805,"published":806,"category":558,"image":807,"draft":562},"\u002Fblog\u002Frotate-supabase-service-role-key","Cómo rotar una clave service_role de Supabase filtrada","Supabase dice que primero cierres la fuga. Otras guías dicen que rotes ya. Cuál es lo correcto depende de dónde se filtró tu clave service_role.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":809,"title":810,"description":811,"published":812,"category":558,"image":813,"draft":562},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Escáneres de seguridad vibe coding comparados, el nuestro incluido","El mejor escáner de seguridad para vibe coding depende de tres preguntas que ninguna lista de funciones responde. Diez herramientas, con precios.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":815,"title":816,"description":817,"published":818,"category":558,"image":819,"draft":562},"\u002Fblog\u002Fsupabase-security-checker","Supabase security checker: haz tú mismo las cinco comprobaciones","Un Supabase security checker lee tu app publicada en lugar de la configuración de tu proyecto. Estas son las cinco comprobaciones y cómo hacer cada una.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":821,"title":822,"description":823,"published":824,"category":558,"image":825,"draft":562},"\u002Fblog\u002Fvibe-coding-security-scanner","Escáner de seguridad para vibe coding: qué se le escapa","Un escáner de seguridad para vibe coding lee tu app en vivo desde fuera. Qué cubre eso, las cuatro cosas que no puede ver y cómo leer el resultado.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":827,"title":828,"description":829,"published":830,"category":558,"image":831,"draft":562},"\u002Fblog\u002Fmissing-security-headers","Faltan cabeceras de seguridad: cuándo importa de verdad","Que falten cabeceras de seguridad es el hallazgo que más imprime nuestro escáner. Contra qué protegen y cuándo son la línea menos urgente de tu informe.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":833,"title":834,"description":835,"published":836,"category":558,"image":837,"draft":562},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","Tu clave de API de OpenAI está expuesta en tu frontend. Rótala.","Una clave de API de OpenAI expuesta en tu frontend no se puede atar a un dominio. Rótala hoy, mueve la llamada a tu servidor y limita el gasto.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":839,"title":840,"description":841,"published":842,"category":558,"image":843,"draft":562},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","Clave de API expuesta en el frontend: qué llevan 30.998 apps","Una clave de API expuesta en tu frontend suele ser una clave de Google Maps. Escaneamos 30.998 apps vibe-coded y contamos qué secretos se filtran de verdad.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":845,"title":846,"description":847,"published":848,"category":681,"image":849,"draft":562},"\u002Fblog\u002Fsupabase-backup-tools-compared","Herramientas de backup de Supabase comparadas, la nuestra incluida","Cuatro tipos de herramienta de backup de Supabase, qué copia cada una y cuándo una GitHub Action gratuita le gana a pagar a cualquiera, nosotros incluidos.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":851,"title":852,"description":853,"published":854,"category":558,"image":855,"draft":562},"\u002Fblog\u002Freplit-secrets-explained","Cómo usar secrets en Replit, y qué se publica de todos modos","Cómo usar secrets en Replit: añadir uno, leerlo y arreglar las dos causas del undefined. Y las claves que la herramienta Secrets no puede mantener privadas.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":857,"title":858,"description":859,"published":860,"category":681,"image":861,"draft":562},"\u002Fblog\u002Fback-up-supabase-free-tier","Backups del plan gratuito de Supabase: cómo hacer uno sin terminal","No hay backups en el plan gratuito de Supabase: la copia tienes que hacerla tú. Cómo sacarla desde el panel y qué deja fuera la vía CSV.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":863,"title":864,"description":865,"published":866,"category":558,"image":867,"draft":562},"\u002Fblog\u002Fis-supabase-secure","¿Supabase es seguro? Sí. Tu proyecto es otra pregunta","¿Supabase es seguro? La plataforma está auditada, cifrada y sometida a pentests. Su propia documentación dice dónde termina eso y empiezan tus ajustes.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":869,"title":870,"description":871,"published":872,"category":558,"image":873,"draft":562},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Dónde están tus claves API de Supabase: anon, service_role y URL","La URL del proyecto, la clave anon y la clave service_role están en una sola página del panel. Aquí tienes dónde está, y cuál de los cuatro va en tu app.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":67,"title":875,"description":876,"published":877,"category":558,"image":878,"draft":562},"New row violates row-level security policy en Supabase. ¿Y ahora?","\"New row violates row-level security policy\" significa que Supabase rechazó una escritura. El arreglo rápido vuelve a abrir la tabla para cualquiera.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":880,"title":881,"description":882,"published":883,"category":558,"image":884,"draft":562},"\u002Fblog\u002Fcors-wildcard-security-risk","¿Es un comodín CORS un riesgo de seguridad? Casi nunca.","¿Es un comodín CORS un riesgo de seguridad? Casi siempre es el ajuste por defecto de tu builder y no entrega nada que tu servidor no diera ya a cualquiera.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":886,"title":887,"description":888,"published":889,"category":681,"image":890,"draft":562},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Supabase branching no es un backup. Solo va hacia adelante.","Por qué el branching de Supabase no es un backup: una rama arranca sin tus datos y un merge solo mueve el esquema. Para qué sirve y qué usar en su lugar.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":892,"title":893,"description":894,"published":895,"category":681,"image":896,"draft":562},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Cómo restaurar un backup de Supabase, y qué se rompe después","Cómo restaurar un backup de Supabase desde el panel o desde un archivo de volcado, qué reemplaza la restauración y por qué tu app puede seguir rota al terminar.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":126,"title":898,"description":899,"published":900,"category":558,"image":901,"draft":562},"Tu bucket de Supabase Storage es público. ¿Es un problema?","Un bucket público de Supabase Storage significa que quien tenga la URL de un archivo puede abrirlo. No significa que alguien pueda listar lo que hay dentro.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":903,"title":904,"description":905,"published":906,"category":558,"image":907,"draft":562},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","¿Es un problema una clave de API de Google en tu frontend?","Una clave de API de Google en tu frontend es la clave que más encuentra nuestro escáner, y casi siempre no pasa nada. Un ajuste gratuito decide cuál es cuál.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":909,"title":910,"description":911,"published":912,"category":681,"image":913,"draft":562},"\u002Fblog\u002Fai-agent-deleted-my-database","Un agente de IA borró mis datos de Supabase. ¿Qué puedo recuperar?","Un agente de IA borró datos de tu base. Lo que puedes recuperar ya estaba decidido antes de que se ejecutara, y los próximos minutos deciden el resto.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":915,"title":916,"description":917,"published":918,"category":558,"image":919,"draft":562},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","¿Puede cualquiera leer tu base de datos Supabase? 3.680 apps","¿Puede cualquiera leer tu base de datos Supabase sin iniciar sesión? Escaneamos 30.998 apps activas hechas con builders de IA y medimos cuántas dicen que sí.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":921,"title":922,"description":923,"published":918,"category":558,"image":924,"draft":562},"\u002Fblog\u002Fsource-maps-exposed-in-production","Source maps expuestos: tu app está publicando su código original","Un source map expuesto deja que cualquiera lea el código original de tu app, comentarios incluidos. La comprobación de 30 segundos y lo que de verdad importa.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":926,"title":927,"description":928,"published":929,"category":558,"image":930,"draft":562},"\u002Fblog\u002Fsupabase-new-api-keys","Las nuevas claves de API de Supabase: ¿cuál va en tu app?","Supabase sustituyó anon y service_role por claves publicables y secretas. ¿Cuál pertenece a tu app y cuál no debe estar nunca?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":932,"title":933,"description":934,"published":935,"category":681,"image":936,"draft":562},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","¿Supabase respalda mi base de datos? Depende de tu plan.","¿Supabase respalda tu base de datos? A diario en los planes de pago, y nada en el gratuito. Cómo saber cuál tienes y qué es lo que esa copia no cubre.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":938,"title":939,"description":940,"published":941,"category":558,"image":942,"draft":562},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","Supabase Row Level Security está activado. Tu tabla sigue pública.","Activar Supabase Row Level Security no protege una tabla. Lo hacen tus políticas, y la que arregló tu app rota puede dejar entrar a cualquiera.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":944,"title":945,"description":946,"published":941,"category":681,"image":947,"draft":562},"\u002Fblog\u002Fversion-history-is-not-a-backup","El historial de versiones no es un backup. No recupera una tabla.","Lovable y Bolt guardan un historial de versiones de tu código. Tu base de datos es un servicio aparte, y volver atrás no te devuelve tus datos.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":949,"title":950,"description":951,"published":952,"category":681,"image":953,"draft":562},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Tres formas de respaldar una base Supabase, y qué falta en cada una","El panel, pg_dump y un servicio gestionado. Qué guarda de verdad cada uno, qué deja fuera sin avisar y cuál sobrevive a perder la cuenta.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":955,"title":956,"description":957,"published":952,"category":558,"image":958,"draft":562},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Qué claves de API son seguras en el navegador y cuáles no","Tu clave anon de Supabase está pensada para ser pública. Tu clave service_role no, y se salta todas las reglas que pongas. Cómo distinguirlas.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1791705961188]