[{"data":1,"prerenderedAt":732},["ShallowReactive",2],{"blog-es-supabase-rls-disabled-in-public":3,"blog-index-es":491},{"id":4,"title":5,"body":6,"category":447,"cover":448,"coverAlt":449,"description":450,"draft":451,"extension":452,"faq":453,"image":469,"keywords":470,"meta":479,"navigation":480,"ogTitle":481,"path":482,"published":483,"seo":484,"stem":485,"tldr":486,"updated":483,"__hash__":490},"blog_es\u002Fblog\u002Fsupabase-rls-disabled-in-public.md","Supabase \"RLS disabled in public\": lo que el aviso no ve",{"type":7,"value":8,"toc":435},"minimark",[9,18,29,36,41,44,55,58,61,65,68,71,77,80,83,87,98,101,107,110,117,212,215,221,235,239,242,249,252,255,261,271,275,278,281,286,299,306,310,313,316,329,335,348,352,355,362,365,370,373,385,389,422],[10,11,12,13,17],"p",{},"Abriste el Security Advisor en tu dashboard de Supabase, o alguien te pegó su\nsalida delante, y ahí está en rojo: ",[14,15,16],"strong",{},"RLS disabled in public",". Debajo, una línea\npor tabla, con las palabras de Supabase:",[19,20,25],"pre",{"className":21,"code":23,"language":24},[22],"language-text","Table public.profiles is public, but RLS has not been enabled.\n","text",[26,27,23],"code",{"__ignoreMap":28},"",[10,30,31,32,35],{},"Aquí está la parte que guía tras guía cuenta mal: ",[14,33,34],{},"vaciar esa lista no\nsignifica que nadie pueda leer tus datos."," El advisor tiene una regla aparte\npara una política que deja entrar a todo el mundo, y esa regla se salta justo la\nforma que escribe un constructor de IA cuando desatasca tu app. Así que la lista\nque acabas de arreglar y la lista de tablas que un desconocido puede leer son\ndos listas distintas, y una de ellas no aparece en ningún sitio de tu dashboard.",[37,38,40],"h2",{"id":39},"qué-significa-rls-disabled-in-public","¿Qué significa \"RLS disabled in public\"?",[10,42,43],{},"Una tabla de tu esquema public tiene Row Level Security apagado, y la\nconsecuencia es que cualquiera con la dirección de tu proyecto puede leer todas\nsus filas.",[10,45,46,47,50,51,54],{},"Las dos mitades de esa frase necesitan explicación. El ",[14,48,49],{},"esquema public"," es\ndonde va una tabla cuando nadie dice otra cosa, y es la parte de tu base de\ndatos que Supabase publica en la web: cada proyecto responde peticiones en una\ndirección propia, y la clave que hace falta para hablar con ella está en el\ncódigo que tu web envía a cada visitante. ",[14,52,53],{},"Row Level Security"," es el\ninterruptor que decide si tus reglas se consultan antes de entregar filas. Con\nél apagado no hay nada que consultar, así que la respuesta siempre es que sí.",[10,56,57],{},"Esa combinación es la razón de que esto se reporte como error y no como aviso.\nEl advisor clasifica sus hallazgos, y este es el escalón más alto.",[10,59,60],{},"Piensa en el advisor como un inspector con un portapapeles. Lee tu documentación\ncon cuidado y lo hace bien. Nunca prueba el picaporte. Nada de lo que hay en ese\npanel es el resultado de una petición que alguien haya hecho a tu base de datos.",[37,62,64],{"id":63},"activar-rls-va-a-romper-mi-app","¿Activar RLS va a romper mi app?",[10,66,67],{},"Sí, de inmediato, y eso es el interruptor funcionando.",[10,69,70],{},"El arreglo que te da Supabase es una línea, y la ejecutas en el SQL Editor:",[19,72,75],{"className":73,"code":74,"language":24},[22],"alter table public.profiles enable row level security;\n",[26,76,74],{"__ignoreMap":28},[10,78,79],{},"La propia documentación de Supabase es clara sobre lo que pasa después: los\ndatos dejan de ser accesibles por la API con una clave publicable mientras no\nhaya políticas definidas. Así que tus listas vuelven vacías, tus pantallas se\nquedan en blanco, y el error del advisor queda sustituido por una entrada más\ndiscreta que dice que la tabla tiene RLS activado pero ninguna política.",[10,81,82],{},"Esa es la puerta cerrada sin nadie todavía en la lista. Lo siguiente que hace\ncasi todo el mundo es añadir una política que deja leer a cualquiera, porque eso\nes lo que hace que las pantallas vuelvan.",[37,84,86],{"id":85},"el-fallo-que-el-aviso-no-está-buscando","El fallo que el aviso no está buscando",[10,88,89,90,93,94,97],{},"Una tabla con Row Level Security ",[14,91,92],{},"encendido"," y una política de lectura cuya\ncondición es ",[26,95,96],{},"USING (true)"," entrega exactamente las mismas filas al mismo\ndesconocido. El advisor no la marca.",[10,99,100],{},"No es un descuido. Supabase sí tiene una regla para las políticas siempre\nverdaderas, y deja fuera las de lectura a propósito. Su propia descripción de la\nregla lo dice:",[19,102,105],{"className":103,"code":104,"language":24},[22],"SELECT policies with `USING (true)` are intentionally excluded as this\npattern is often used deliberately for public read access.\n",[26,106,104],{"__ignoreMap":28},[10,108,109],{},"En el caso general la regla tiene razón. Un catálogo de productos, una lista de\nartículos publicados, un mapa de locales: eso está pensado para que lo lea\ncualquiera, y marcarlo entrenaría a todos los desarrolladores de la plataforma\npara ignorar el panel. Lo que ningún linter puede saber es si la tabla que está\nmirando guarda locales o clientes.",[10,111,112,113,116],{},"Y una política que deja leer a todos es la forma más rápida de volver a poner en\npie una app rota, que es por lo que un constructor de IA tira de ella. Pídele a\nCursor o a Lovable que arregle las pantallas vacías y\n",[26,114,115],{},"FOR SELECT USING (true)"," es una respuesta habitual. Tu app carga, el error\ndesaparece, el panel se calla, y la tabla se lee igual que antes de empezar.",[118,119,120,136],"table",{},[121,122,123],"thead",{},[124,125,126,130,133],"tr",{},[127,128,129],"th",{},"Lo que el advisor puede ver",[127,131,132],{},"Cómo lo reporta",[127,134,135],{},"Lo que recibe un desconocido con tu clave publicable",[137,138,139,155,169,183,198],"tbody",{},[124,140,141,145,148],{},[142,143,144],"td",{},"RLS apagado",[142,146,147],{},"Error",[142,149,150],{},[151,152,154],"key-verdict",{"type":153},"danger","Todas las filas",[124,156,157,160,163],{},[142,158,159],{},"RLS encendido, sin ninguna política",[142,161,162],{},"Info",[142,164,165],{},[151,166,168],{"type":167},"safe","Nada",[124,170,171,176,179],{},[142,172,173,174],{},"RLS encendido, ",[26,175,115],{},[142,177,178],{},"Nada en absoluto",[142,180,181],{},[151,182,154],{"type":153},[124,184,185,190,193],{},[142,186,173,187],{},[26,188,189],{},"FOR ALL USING (true)",[142,191,192],{},"Aviso",[142,194,195],{},[151,196,197],{"type":153},"Todas las filas, y puede cambiarlas",[124,199,200,205,207],{},[142,201,173,202],{},[26,203,204],{},"USING (auth.uid() = user_id)",[142,206,178],{},[142,208,209],{},[151,210,211],{"type":167},"Solo las suyas",[10,213,214],{},"Las dos filas donde no se reporta nada en absoluto son el par que merece un\nmomento. Una es una tabla que nadie fuera de tu app puede tocar. La otra es una\ntabla que puede leer cualquiera. Tu dashboard calla igual con las dos.",[216,217],"diagram",{"alt":218,"caption":219,"src":220},"Dos carriles que terminan en las mismas cuatro filas, todas encendidas. El carril de arriba tiene el interruptor de Row Level Security apagado y lleva una señal de aviso. El de abajo lo tiene encendido, con una política que dice USING (true), y un círculo punteado vacío donde iría la señal.","Las mismas cuatro filas entregadas al mismo desconocido. La diferencia entre los carriles es de cuál dice algo tu dashboard.","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Ftwo-tables-one-outcome-1600x640.png",[10,222,223,224,229,230,234],{},"Cómo se escribió esa política, y por qué sustituirla tabla por tabla, es el tema\nde\n",[225,226,228],"a",{"href":227},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","Row Level Security está activado y tu tabla sigue pública",".\nSi esa misma política también tiene que dejar que tu app guarde datos, el error\nque te encuentras después es\n",[225,231,233],{"href":232},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","new row violates row-level security policy",".",[37,236,238],{"id":237},"por-qué-la-tabla-que-hiciste-con-una-migración-nunca-te-avisó","Por qué la tabla que hiciste con una migración nunca te avisó",[10,240,241],{},"Porque el Table Editor enciende Row Level Security por ti y SQL no.",[10,243,244,245,248],{},"Supabase documenta la diferencia sin rodeos: las tablas creadas con el Table\nEditor del dashboard tienen RLS activado por defecto, y las creadas con SQL\ndirecto hay que activarlas de forma explícita. Una tabla que creaste a base de\nclics arranca protegida. Una tabla que llegó por un archivo de migración, un\n",[26,246,247],{},"supabase db push",", un fragmento en el SQL Editor o una sentencia que tu\nconstructor de IA ejecutó por ti arranca abierta.",[10,250,251],{},"Esa segunda vía es como crea tablas un constructor de IA. Escribe el SQL y lo\nejecuta por ti, así que nunca viste la casilla y nunca la viste sin marcar.",[10,253,254],{},"La costumbre que lo cierra es poner la línea en la migración, al lado de lo que\nprotege:",[19,256,259],{"className":257,"code":258,"language":24},[22],"create table public.profiles (\n  id uuid primary key references auth.users,\n  full_name text\n);\n\nalter table public.profiles enable row level security;\n",[26,260,258],{"__ignoreMap":28},[262,263,265],"callout",{"type":264},"warn",[10,266,267,270],{},[14,268,269],{},"El advisor es una foto fija, no una vigilancia."," Reporta cómo estaba tu base\nde datos la última vez que se ejecutó, y seguirá enseñándote tan tranquilo un\npanel limpio de antes de la migración de esta mañana. Vuelve a ejecutarlo\ndespués de cualquier cambio que cree una tabla o toque una política, que en un\nproyecto hecho con IA son casi todos los cambios.",[37,272,274],{"id":273},"cómo-comprobar-las-tablas-que-el-advisor-dio-por-buenas","Cómo comprobar las tablas que el advisor dio por buenas",[10,276,277],{},"Hazle a tu base de datos la pregunta que hace un desconocido: manda una petición\ndesde fuera, con la clave publicable que viaja dentro de tu app, y mira qué\nvuelve.",[10,279,280],{},"Esta es la diferencia sobre la que gira todo el artículo. El advisor lee tu\nconfiguración. Una petición lee tus filas. Son dos preguntas distintas, y una\ntabla puede aprobar la primera y suspender la segunda, que es exactamente lo que\nhace una política de lectura permisiva.",[216,282],{"alt":283,"caption":284,"src":285},"Dos lectores fuera de un límite punteado del proyecto. Una lupa llega solo al panel de ajustes de dentro y vuelve con un círculo punteado vacío. La petición de una persona pasa de largo hasta las filas de la tabla y vuelve con ellas.","El advisor se detiene en tus ajustes. Una petición desde fuera sigue hasta las filas, y por eso los dos pueden decir cosas distintas de la misma tabla.","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fsettings-versus-answer-1600x600.png",[10,287,288,289,293,294,298],{},"Hicimos esa petición a gran escala. Entre el 12 y el 14 de agosto de 2026\npasamos nueve comprobaciones externas a 30.998 apps en producción publicadas\ndesde Lovable, Base44, Replit, v0 y Bolt. De las 3.680 apps con Supabase donde\nla comprobación pudo completarse, 2.096 tenían al menos una tabla que respondió\ncon filas a una petición anónima. Eso es un 57 %, y es una proporción de las\napps de las que pudimos obtener una respuesta clara, no de todo lo que\nescaneamos. Entre las apps hechas con Bolt fueron 27 de 35, una muestra lo\nbastante pequeña como para leerla como una dirección y no como una tasa. El\n",[225,290,292],{"href":291},"\u002Fresearch\u002Fvibe-coded-app-security-2026","conjunto de datos completo está publicado",",\ny ",[225,295,297],{"href":296},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","de qué es proporción ese 57 %","\nrepasa el recuento.",[10,300,301,302,234],{},"Puedes hacer tú mismo esa petición contra una tabla con un navegador y tu propia\nclave publicable. Si prefieres no ir tabla por tabla, nuestro escaneo gratuito\nle pregunta a tu app en producción desde fuera y te dice qué tablas\nrespondieron. Tarda unos 20 segundos y no necesita cuenta:\n",[225,303,305],{"href":304},"\u002F#scan","escanea tu app",[37,307,309],{"id":308},"necesito-una-copia-de-seguridad-antes-de-cambiar-políticas-de-rls","¿Necesito una copia de seguridad antes de cambiar políticas de RLS?",[10,311,312],{},"Para cualquier tabla en la que tu app escriba, sí. Para una tabla de solo\nlectura que solo estás cerrando, el riesgo es que tu app se quede en blanco, no\nque se pierdan datos.",[10,314,315],{},"Aquí conviene separar dos cosas distintas, porque solo una tiene que ver con el\narreglo.",[10,317,318,321,322,324,325,328],{},[14,319,320],{},"Lo que una política permisiva ya permitió."," Si la regla de la tabla era\n",[26,323,189],{}," en vez de ",[26,326,327],{},"FOR SELECT",", entonces quien la encontrara\npodía cambiar y borrar filas además de leerlas, y cerrarla hoy no hace nada\nrespecto a ayer. Esa versión suele aparecer como un mensaje de soporte sobre\ndatos que cambiaron solos, o como una tabla que de pronto está vacía.",[10,330,331,334],{},[14,332,333],{},"El arreglo en sí."," Reescribir políticas en una docena de tablas es un cambio\nsobre una base de datos en producción, escrito por las mismas herramientas que\nprovocaron el problema. Una migración que borra una política y la vuelve a crear\nmal es un martes cualquiera, y el camino de vuelta es una copia de cómo estaba\ntodo hace una hora.",[10,336,337,338,342,343,347],{},"En un plan de pago de Supabase tienes la copia de anoche en la consola. En el\nplan gratuito no hay nada a lo que volver, porque\n",[225,339,341],{"href":340},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","el plan gratuito no hace ninguna copia automática",".\nSi ese es tu caso, haz una antes de tocar una política:\n",[225,344,346],{"href":345},"\u002Fblog\u002Fback-up-supabase-free-tier","cómo respaldar una base de datos de Supabase en el plan gratuito","\nes la versión de diez minutos.",[37,349,351],{"id":350},"de-qué-guarda-una-copia-reeve-care","De qué guarda una copia Reeve Care",[10,353,354],{},"De tu base de datos de Supabase, copiada según un calendario, guardada fuera de\ntu cuenta de Supabase, cifrada y releída antes de que la fecha de tu panel se\nmueva. Los archivos que subieron tus usuarios viajan con ella en cuanto conectas\nuna clave de Storage.",[10,356,357,358,361],{},"Dos límites, dichos por delante. Las copias son ",[14,359,360],{},"solo de Supabase",": si tus\ndatos viven en otro sitio lo decimos, en vez de venderte una suscripción que\nvigila una caja vacía. Y la clave de Storage se pide aparte, porque Supabase no\nemite una clave de solo lectura para archivos, así que la que copia tus subidas\ntambién puede escribir. La que copia tu base de datos no. Conectarla es\nopcional, y la base de datos se respalda igual.",[10,363,364],{},"La restauración es la parte que importa para este artículo. Poner una copia\nantigua encima de una base de datos en producción es el botón que más miedo da\ndel producto, así que Care copia primero el estado actual y solo después\nreproduce el que elegiste. La restauración tiene su propio deshacer.",[216,366],{"alt":367,"caption":368,"src":369},"Un límite punteado alrededor de una base de datos, con la marca de Reeve Care al lado. El paso uno es una flecha que sale del límite hacia una copia nueva. El paso dos es una flecha que devuelve la copia guardada.","Lo que pasa cuando pulsas restaurar. El estado actual se copia fuera antes de reproducir nada, así que pulsar el botón también tiene vuelta atrás.","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Frestore-takes-a-copy-first-1600x520.png",[10,371,372],{},"La otra mitad de Care es a la que este artículo lleva apuntando. Una política\nque se aflojó durante una migración no es algo que encuentres mirando, así que\nla misma comprobación externa se repite según un calendario y te avisa cuando\ncambia la respuesta. El uptime, un informe mensual y el escaneo van en la misma\nsuscripción.",[10,374,375,376,380,381,234],{},"Lo que una copia no hace es escribir tus políticas, y ninguna copia convierte\nuna tabla abierta en cerrada. Esas tablas siguen siendo cosa tuya. Lo que cambia\nla copia es lo que pasa cuando el arreglo sale torcido.\n",[225,377,379],{"href":378},"\u002Fsupabase-backups","Qué respalda Reeve en Supabase, cada cuánto y qué hace una restauración","\ndibuja el ciclo entero, y los planes y sus precios están en la\n",[225,382,384],{"href":383},"\u002Fpricing","página de precios",[37,386,388],{"id":387},"qué-hacer-esta-semana","Qué hacer esta semana",[390,391,392],"key-takeaways",{},[393,394,395,403,409,412,419],"ul",{},[396,397,398,399,402],"li",{},"Vacía primero las entradas \"RLS disabled in public\". Son las tablas donde no se consulta absolutamente nada, y el arreglo es una línea ",[26,400,401],{},"alter table"," en cada una.",[396,404,405,406,408],{},"Después abre Authentication → Policies y lee la condición de cada política que haya sobrevivido. Un ",[26,407,96],{}," en una política de lectura es invisible para el advisor y está de par en par para un desconocido.",[396,410,411],{},"Decide tabla por tabla si te sentirías cómodo publicando su contenido en una página. Esa es la pregunta que el linter no puede responder por ti, y con una política de lectura permisiva es la única que importa.",[396,413,414,415,418],{},"Pon ",[26,416,417],{},"alter table ... enable row level security;"," en cada migración que cree una tabla, y vuelve a ejecutar el advisor después de cada una. El valor por defecto del dashboard solo se aplica a las tablas que creas con clics.",[396,420,421],{},"Haz una copia de tu base de datos antes de reescribir políticas en una tabla en producción, y mira en qué plan de Supabase estás para saber si ya tienes una.",[10,423,424,425,429,430,434],{},"Empieza por la tabla que más vergüenza te daría como página pública. La\n",[225,426,428],{"href":427},"\u002Fchecklist","lista de seguridad en 10 minutos"," cubre esto junto con el resto de\nlo que conviene comprobar en una app recién lanzada, y la\n",[225,431,433],{"href":432},"\u002Fis-your-supabase-app-safe","guía de seguridad de Supabase"," repasa qué más suele\nquedarse abierto.",{"title":28,"searchDepth":436,"depth":436,"links":437},3,[438,440,441,442,443,444,445,446],{"id":39,"depth":439,"text":40},2,{"id":63,"depth":439,"text":64},{"id":85,"depth":439,"text":86},{"id":237,"depth":439,"text":238},{"id":273,"depth":439,"text":274},{"id":308,"depth":439,"text":309},{"id":350,"depth":439,"text":351},{"id":387,"depth":439,"text":388},"Fundamentos de seguridad","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcover-1200x630.png","Un panel de dashboard con varias tablas, una señal de aviso junto a una de ellas y nada junto a las demás.","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.",false,"md",[454,457,460,463,466],{"q":455,"a":456},"¿\"RLS disabled in public\" es un error o un aviso?","Un error, y es el nivel más alto que usa el advisor. La entrada dice \"Table public.\u003Cname> is public, but RLS has not been enabled.\" Las dos entradas relacionadas son más discretas: una tabla con el interruptor encendido y ninguna política se reporta como INFO, y una política cuya condición es siempre verdadera se reporta como WARN. Esos niveles describen la confianza del linter en lo que puede ver en tu configuración, no el tamaño de tu problema.",{"q":458,"a":459},"¿Activar Row Level Security va a romper mi app?","Al instante, sí, y eso es el interruptor haciendo su trabajo. Supabase documenta que los datos dejan de ser accesibles por la API con una clave publicable mientras no haya políticas definidas, así que en cuanto ejecutas la línea tus listas vuelven vacías y tus pantallas se quedan en blanco. La app vuelve cuando añades una política que dice quién puede ver qué filas. El error que hay que evitar es añadir una que permita a todo el mundo, porque esa versión también hace que la app funcione.",{"q":461,"a":462},"Activé RLS y ahora no carga nada. ¿Qué ha pasado?","No se ha roto nada. Con Row Level Security encendido y sin políticas escritas, Postgres (el motor de base de datos que hay debajo de Supabase) rechaza todas las peticiones, incluidas las de tu propia app, y el advisor cambia su error por una entrada INFO que dice que la tabla tiene RLS activado pero ninguna política. Escribe una política para las filas que tu app debe mostrar, empezando por la que compara al visitante identificado con la columna de propietario de la fila.",{"q":464,"a":465},"Mi tabla no está marcada y aun así cualquiera puede leerla. ¿Por qué?","Lo más probable es que Row Level Security esté encendido y haya una política de lectura cuya condición es USING (true). El advisor sí tiene una regla para las políticas siempre verdaderas, y se salta las de lectura a propósito, porque el acceso público de lectura es algo razonable para un catálogo de productos o una lista de artículos publicados. Nada en tu dashboard sabe si tu tabla guarda locales o clientes, así que esa comprobación es cosa tuya.",{"q":467,"a":468},"¿Necesito Row Level Security si mi app solo habla con mi propio servidor?","Si el navegador de verdad nunca habla con Supabase y no hay ninguna clave publicable en el código que tu web envía a los visitantes, entonces la Data API no es una vía de entrada y las políticas no son lo que protege esas tablas. Eso es raro en una app hecha con Lovable, Bolt o v0, porque esos constructores conectan el navegador directamente a Supabase por defecto. Abre tu propia web, mira si la URL del proyecto y la clave publicable están en la página, y deja que esa respuesta lo decida.","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",[471,472,473,474,475,476,477,478],"rls disabled in public","aviso supabase rls desactivado","supabase security advisor","supabase database linter","supabase lint 0013","table is public but rls has not been enabled","activar rls supabase","rls policy always true",{},true,"Supabase: qué omite \"RLS disabled in public\"","\u002Fblog\u002Fsupabase-rls-disabled-in-public","2026-09-09",{"title":5,"description":450},"blog\u002Fsupabase-rls-disabled-in-public",[487,488,489],"\"RLS disabled in public\" significa una sola cosa: una tabla de tu esquema public tiene Row Level Security apagado, así que puede leerla cualquiera que tenga la dirección de tu proyecto y tu clave publicable.","No dice nada de una tabla donde encendiste el interruptor y luego escribiste una política que deja leer a todo el mundo. Existe una regla para las políticas siempre verdaderas y esa regla se salta las de lectura a propósito.","Arregla las tablas marcadas y después comprueba el resto desde fuera, porque el advisor lee tu configuración y nunca le pregunta a tu base de datos qué recibe de verdad un desconocido.","Jklv5fdoi9rtB0GHIR4eKVZm6g36KtVlzha8DM5_wZ4",[492,499,505,511,517,523,529,535,541,547,553,559,565,571,577,578,584,590,596,602,608,614,620,626,632,637,643,649,654,660,666,672,678,684,690,695,700,706,711,716,721,727],{"path":493,"title":494,"description":495,"published":496,"category":497,"image":498,"draft":451},"\u002Fblog\u002Fsupabase-backup-auth-users","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","Backups","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":500,"title":501,"description":502,"published":503,"category":447,"image":504,"draft":451},"\u002Fblog\u002Fdomain-and-certificate-expiry","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":506,"title":507,"description":508,"published":509,"category":447,"image":510,"draft":451},"\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":512,"title":513,"description":514,"published":515,"category":447,"image":516,"draft":451},"\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":518,"title":519,"description":520,"published":521,"category":447,"image":522,"draft":451},"\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":524,"title":525,"description":526,"published":527,"category":447,"image":528,"draft":451},"\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":530,"title":531,"description":532,"published":533,"category":447,"image":534,"draft":451},"\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":536,"title":537,"description":538,"published":539,"category":447,"image":540,"draft":451},"\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":542,"title":543,"description":544,"published":545,"category":447,"image":546,"draft":451},"\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":548,"title":549,"description":550,"published":551,"category":497,"image":552,"draft":451},"\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":554,"title":555,"description":556,"published":557,"category":497,"image":558,"draft":451},"\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":560,"title":561,"description":562,"published":563,"category":497,"image":564,"draft":451},"\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":566,"title":567,"description":568,"published":569,"category":447,"image":570,"draft":451},"\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":572,"title":573,"description":574,"published":575,"category":447,"image":576,"draft":451},"\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":482,"title":5,"description":450,"published":483,"category":447,"image":469,"draft":451},{"path":579,"title":580,"description":581,"published":582,"category":447,"image":583,"draft":451},"\u002Fblog\u002Frotate-supabase-service-role-key","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":585,"title":586,"description":587,"published":588,"category":447,"image":589,"draft":451},"\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":591,"title":592,"description":593,"published":594,"category":447,"image":595,"draft":451},"\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":597,"title":598,"description":599,"published":600,"category":447,"image":601,"draft":451},"\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":603,"title":604,"description":605,"published":606,"category":447,"image":607,"draft":451},"\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":609,"title":610,"description":611,"published":612,"category":447,"image":613,"draft":451},"\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":615,"title":616,"description":617,"published":618,"category":447,"image":619,"draft":451},"\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":621,"title":622,"description":623,"published":624,"category":497,"image":625,"draft":451},"\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":627,"title":628,"description":629,"published":630,"category":447,"image":631,"draft":451},"\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":345,"title":633,"description":634,"published":635,"category":497,"image":636,"draft":451},"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":638,"title":639,"description":640,"published":641,"category":447,"image":642,"draft":451},"\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":644,"title":645,"description":646,"published":647,"category":447,"image":648,"draft":451},"\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":232,"title":650,"description":651,"published":652,"category":447,"image":653,"draft":451},"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":655,"title":656,"description":657,"published":658,"category":447,"image":659,"draft":451},"\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":661,"title":662,"description":663,"published":664,"category":497,"image":665,"draft":451},"\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":667,"title":668,"description":669,"published":670,"category":497,"image":671,"draft":451},"\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":673,"title":674,"description":675,"published":676,"category":447,"image":677,"draft":451},"\u002Fblog\u002Fsupabase-storage-bucket-public","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":679,"title":680,"description":681,"published":682,"category":447,"image":683,"draft":451},"\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":685,"title":686,"description":687,"published":688,"category":497,"image":689,"draft":451},"\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":296,"title":691,"description":692,"published":693,"category":447,"image":694,"draft":451},"¿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":696,"title":697,"description":698,"published":693,"category":447,"image":699,"draft":451},"\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":701,"title":702,"description":703,"published":704,"category":447,"image":705,"draft":451},"\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":340,"title":707,"description":708,"published":709,"category":497,"image":710,"draft":451},"¿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":227,"title":712,"description":713,"published":714,"category":447,"image":715,"draft":451},"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":717,"title":718,"description":719,"published":714,"category":497,"image":720,"draft":451},"\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":722,"title":723,"description":724,"published":725,"category":497,"image":726,"draft":451},"\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":728,"title":729,"description":730,"published":725,"category":447,"image":731,"draft":451},"\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",1790150954094]