[{"data":1,"prerenderedAt":998},["ShallowReactive",2],{"blog-es-api-key-leaked-what-to-do":3,"blog-index-es":645},{"id":4,"title":5,"body":6,"category":601,"cover":602,"coverAlt":603,"description":604,"draft":605,"extension":606,"faq":607,"image":622,"keywords":623,"meta":632,"navigation":633,"ogTitle":634,"path":635,"published":636,"seo":637,"stem":638,"tldr":639,"updated":636,"__hash__":644},"blog_es\u002Fblog\u002Fapi-key-leaked-what-to-do.md","Tu clave API se filtró. El orden en el que hay que actuar",{"type":7,"value":8,"toc":587},"minimark",[9,13,16,21,24,32,35,57,65,69,72,79,82,88,94,100,104,267,270,280,302,306,309,363,368,372,375,382,385,388,392,395,404,409,414,424,428,431,434,437,440,445,449,455,463,474,483,501,510,527,538,542,579],[10,11,12],"p",{},"El aviso suele llegar por un informe de escaneo, por GitHub diciéndote que ha\naparecido un secreto en uno de tus repositorios, o por alguien que pulsó F12 en\ntu sitio y te mandó una captura. Por donde sea que te haya llegado, ya sabes que\nuna clave API tuya se filtró y no sabes por dónde empezar.",[10,14,15],{},"Esta es la parte que guía tras guía se equivoca: dan la misma respuesta para\ncualquier clave, y la respuesta siempre es rotarla. Algunas de esas claves están\npensadas para ser públicas y no necesitan nada. De las demás, algunas están\nengordando una factura mientras lees esto, y otras hicieron todo su daño el día\ndel despliegue. Son tres situaciones distintas, y el primer paso es distinto en\ncada una.",[17,18,20],"h2",{"id":19},"primero-esa-clave-es-realmente-un-secreto","Primero: ¿esa clave es realmente un secreto?",[10,22,23],{},"A menudo no, y los números están lo bastante desequilibrados como para decirlo\nsin rodeos.",[10,25,26,27,31],{},"Escaneamos 31.056 aplicaciones en vivo y leímos el JavaScript que cada una envía\nal navegador. La comprobación que busca credenciales pudo responder en todas, y\n1.332 volvieron con al menos una clave que merecía un aviso. ",[28,29,30],"strong",{},"1.142 de ellas\neran claves API de Google",", que es el único tipo del grupo que suele estar\njusto donde le corresponde.",[10,33,34],{},"Una clave API de Google en una página web es lo que hace funcionar Google Maps.\nLa clave dice qué proyecto paga, y lo que impide que un desconocido gaste a tu\ncosta es la restricción puesta en la clave y no su secreto. La guía de Google es\nclara en las dos mitades: \"Unrestricted API keys are insecure\", y \"You are\nfinancially responsible for charges caused by abuse of unrestricted API keys.\"\nEl arreglo para una clave así es abrirla en la Cloud Console y añadir dos\nrestricciones, una que nombre tu sitio web y otra que nombre las API que de\nverdad llamas. La clave en sí nunca cambia.",[10,36,37,38,42,43,46,47,50,51,56],{},"La otra familia que va en el navegador son las claves publicables. Una clave de\nStripe ",[39,40,41],"code",{},"pk_live_",", y una de Supabase ",[39,44,45],{},"sb_publishable_"," o ",[39,48,49],{},"anon",", están hechas\npara que las lea cada visitante que tengas.\n",[52,53,55],"a",{"href":54},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Qué claves son seguras en tu frontend","\nes la versión de cuatro caracteres de esa prueba.",[10,58,59,60,64],{},"Si prefieres no recorrer tu bundle a mano, nuestro escaneo gratuito lee tu sitio\nen vivo, enumera las claves que ve desde fuera y dice de qué tipo es cada una:\n",[52,61,63],{"href":62},"\u002Fsecurity-scanner","escanea tu aplicación",". Tarda unos 20 segundos y no pide\ncuenta.",[17,66,68],{"id":67},"mi-clave-api-se-filtró-qué-hago-primero","Mi clave API se filtró. ¿Qué hago primero?",[10,70,71],{},"Averigua si la clave tiene un contador.",[10,73,74,75,78],{},"Una clave con contador te cobra cada petición. La de Google, la de OpenAI, la de\nAnthropic y una clave de AWS con los permisos equivocados detrás son todas\ncontadores: el tráfico de otra persona aterriza en tu factura, a un ritmo que\nelige esa persona y que tú no ves. Una clave sin contador lee o escribe tus\ndatos en su lugar. Una clave ",[39,76,77],{},"service_role"," de Supabase es el ejemplo más claro,\ny nada en ella cuesta dinero por hora.",[10,80,81],{},"Esa única pregunta fija el orden.",[10,83,84,87],{},[28,85,86],{},"Si la clave tiene un contador, párala ahora."," La función que la usaba queda\nrota hasta que despliegues el reemplazo, y ese es el intercambio correcto,\nporque la factura es la única parte de esto que sigue creciendo mientras\nplanificas.",[10,89,90,93],{},[28,91,92],{},"Si la clave lee datos y se publicó en tu bundle, la lectura ya ocurrió."," Cada\nvisitante que cargó la página tiene una copia, y también cada rastreador que fue\na buscar exactamente esa cadena. Nada empeora mientras averiguas el orden\ncorrecto, y lo que conviene acertar es no quedarte fuera de tu propia aplicación\npor el camino.",[95,96],"diagram",{"alt":97,"caption":98,"src":99},"Dos carriles, cada uno empieza con la misma llave. En el de arriba la llave lleva a una esfera cuya aguja ha recorrido buena parte del arco, y de ahí a un montón de monedas, todo en ámbar. En el de abajo la llave lleva a una tabla con todas las filas encendidas en rojo, y en el lugar de la esfera hay un círculo vacío de puntos.","La llave de arriba te está costando dinero mientras lees esto. La de abajo hizo todo lo que iba a hacer el día del despliegue.","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fdoes-it-have-a-meter-1600x660.png",[17,101,103],{"id":102},"qué-puede-hacer-realmente-cada-tipo-de-clave","Qué puede hacer realmente cada tipo de clave",[105,106,107,129],"table",{},[108,109,110],"thead",{},[111,112,113,117,120,123,126],"tr",{},[114,115,116],"th",{},"Clave",[114,118,119],{},"Gasta dinero",[114,121,122],{},"Lee tus datos",[114,124,125],{},"¿Se puede restringir en su lugar?",[114,127,128],{},"¿Reemplazarla rompe la aplicación?",[130,131,132,154,169,188,205,227,248],"tbody",{},[111,133,134,142,145,148,151],{},[135,136,137,138,46,140],"td",{},"Supabase ",[39,139,45],{},[39,141,49],{},[135,143,144],{},"No",[135,146,147],{},"Solo las filas que tus reglas permiten",[135,149,150],{},"Su sitio es el navegador",[135,152,153],{},"No aplica",[111,155,156,161,163,165,167],{},[135,157,158,159],{},"Stripe ",[39,160,41],{},[135,162,144],{},[135,164,144],{},[135,166,150],{},[135,168,153],{},[111,170,171,177,180,182,185],{},[135,172,173,174],{},"Google ",[39,175,176],{},"AIza…",[135,178,179],{},"Sí, en tu factura de Cloud",[135,181,144],{},[135,183,184],{},"Sí, y Google dice que pruebes eso primero",[135,186,187],{},"Restringirla no. Rotarla sí puede.",[111,189,190,193,196,199,202],{},[135,191,192],{},"Clave de OpenAI o Anthropic",[135,194,195],{},"Sí, al ritmo que marque un extraño",[135,197,198],{},"Los archivos y asistentes del proyecto",[135,200,201],{},"No existe una variante publicable",[135,203,204],{},"Sí, hasta que la tenga un servidor tuyo",[111,206,207,215,218,221,224],{},[135,208,158,209,46,212],{},[39,210,211],{},"sk_live_",[39,213,214],{},"rk_live_",[135,216,217],{},"Sí",[135,219,220],{},"Sí, clientes y registros de pago",[135,222,223],{},"Una clave restringida es la versión estrecha",[135,225,226],{},"No, hay una ventana de siete días",[111,228,229,236,239,242,245],{},[135,230,231,232,235],{},"AWS ",[39,233,234],{},"AKIA…"," y su mitad secreta",[135,237,238],{},"Sí, incluido cómputo por hora",[135,240,241],{},"Tus buckets de S3",[135,243,244],{},"Deactivate, y es reversible",[135,246,247],{},"No, puedes tener dos claves a la vez",[111,249,250,257,259,262,264],{},[135,251,137,252,46,255],{},[39,253,254],{},"sb_secret_",[39,256,77],{},[135,258,144],{},[135,260,261],{},"Cada fila de cada tabla",[135,263,144],{},[135,265,266],{},"Sí, en un proyecto antiguo",[10,268,269],{},"Dos notas sobre esa tabla, porque ambas cambian lo que haces a continuación.",[10,271,272,273,276,277,279],{},"Una clave de acceso de AWS son dos cadenas, un identificador que empieza por\n",[39,274,275],{},"AKIA"," y una mitad secreta, y AWS exige las dos juntas para firmar una petición.\nAsí que una cadena ",[39,278,275],{}," sola en un bundle no se puede usar, y la razón para\ntratarla como urgente de todos modos es que las dos mitades casi siempre se\npegan juntas. Abre el archivo y busca la segunda antes de decidir en qué caso\nestás.",[10,281,282,283,287,288,287,292,296,297,301],{},"El detalle de cada proveedor vive con cada proveedor:\n",[52,284,286],{"href":285},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","una clave de OpenAI",",\n",[52,289,291],{"href":290},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","una clave API de Google",[52,293,295],{"href":294},"\u002Fblog\u002Fstripe-secret-key-in-frontend","una clave secreta de Stripe"," y\n",[52,298,300],{"href":299},"\u002Fblog\u002Frotate-supabase-service-role-key","una clave service_role de Supabase",",\nque es la única con un procedimiento propio.",[17,303,305],{"id":304},"parar-la-clave-y-reemplazar-la-clave-son-dos-botones-distintos","Parar la clave y reemplazar la clave son dos botones distintos",[10,307,308],{},"Cada proveedor de esa tabla te da los dos, y el pánico va a por el segundo.",[310,311,312,319,338,347],"ul",{},[313,314,315,318],"li",{},[28,316,317],{},"Google."," Restringir una clave no cambia la cadena, así que tu aplicación\nsigue funcionando. Su guía de seguridad lo pone por delante de todo lo demás:\n\"First try to restrict your API keys\", y rotar es la tercera opción, para\ncuando una restricción no es posible.",[313,320,321,324,325,328,329,333,334,337],{},[28,322,323],{},"Stripe."," ",[28,326,327],{},"Expire key"," para una clave por sí sola, sin reemplazo de por\nmedio. Su postura sobre cuándo usarlo no tiene matices: \"If a restricted or\nsecret API key is exposed or compromised, rotate it immediately even if you\naren't sure anyone saw it.\" También separan las dos palabras que todo el mundo\nusa como sinónimos. ",[330,331,332],"em",{},"Exposure"," es que la clave se haya vuelto visible donde no\ndebía. ",[330,335,336],{},"Compromise"," es la prueba de que alguien la usó.",[313,339,340,324,343,346],{},[28,341,342],{},"AWS.",[28,344,345],{},"Deactivate"," es el control, y lo útil es que se puede deshacer. AWS\ndice que no borres la clave vieja mientras sigas comprobando: \"we recommend\nthat you do not immediately delete the first access key. Instead, choose\nActions and then choose Deactivate.\" Si resulta que algo que olvidaste todavía\nla necesita, la vuelves a encender.",[313,348,349,352,353,355,356,358,359,362],{},[28,350,351],{},"Supabase, en un proyecto antiguo."," Hay un interruptor, y cubre las dos\nclaves heredadas. ",[39,354,49],{}," y ",[39,357,77],{}," están firmadas por el mismo secreto,\nasí que desactivar la que quieres matar detiene también la que usa tu\nfrontend.\n",[52,360,361],{"href":299},"Los cuatro pasos que evitan eso","\nconviene leerlos antes de tocar el interruptor y no después.",[95,364],{"alt":365,"caption":366,"src":367},"Un panel con dos interruptores. El de la izquierda está bajado y dibujado en ámbar, con una llave tachada al lado. El de la derecha está subido y dibujado en turquesa, con una llave al lado y una flecha que lleva a una ventana de aplicación que funciona.","Dos controles, y solo el de la izquierda cierra el agujero. Cuál coges primero es la decisión de la que trata este artículo.","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Ftwo-switches-1600x600.png",[17,369,371],{"id":370},"leer-el-registro-del-periodo-en-que-la-clave-estuvo-fuera","Leer el registro del periodo en que la clave estuvo fuera",[10,373,374],{},"La ventana se abre con el despliegue que publicó la clave y se cierra cuando la\nparaste. Ese rango de fechas es el filtro que aplicas al registro del proveedor.",[10,376,377,378,381],{},"Todos los proveedores de la tabla guardan uno. Stripe muestra los registros de\npeticiones de una sola clave, desde el menú de tres puntos junto a esa clave en\nla página de API Keys. AWS pone una fecha de último uso en cada clave de acceso\nen la consola de IAM sin configurar nada, y guarda las llamadas en sí en\nCloudTrail. Google grafica el uso por clave en la Cloud Console, que es además\nla lectura que su propia guía te pide hacer antes de cambiar nada de una clave.\nSupabase conserva registros de API y de base de datos del proyecto, y\n",[52,379,380],{"href":299},"cómo acotar la ventana en una clave de Supabase","\nexplica qué buscar en ellos.",[10,383,384],{},"Lo que buscas es tráfico que no puedas explicar: peticiones a tablas o endpoints\nque tu aplicación nunca toca, volumen a horas en que nadie la usaba,\neliminaciones que nadie hizo. Después mira los datos en sí, porque un mensaje de\nsoporte sobre un registro que cambió solo es como se descubre la mayoría de\nestos casos, y llega semanas más tarde.",[10,386,387],{},"A menudo no puedes estar seguro, y Stripe dice lo mismo de su propia detección:\n\"Stripe doesn't guarantee detection of all exposed or compromised keys.\" Así que\n\"nada en el registro\" es un resultado, y vale la pena anotarlo con el rango de\nfechas al lado.",[17,389,391],{"id":390},"rotar-sin-dejar-la-aplicación-parada","Rotar sin dejar la aplicación parada",[10,393,394],{},"Tres de los cuatro proveedores de arriba te dan una ventana en la que la clave\nvieja y la nueva funcionan a la vez, y eso es lo que evita una caída.",[10,396,397,399,400,403],{},[28,398,323],{}," \"When you rotate a key in the Dashboard, both the old and new keys\nwork for up to 7 days.\" El diálogo también tiene una opción ",[28,401,402],{},"Now",", y su\ndocumentación es explícita: si la eliges, la clave vieja se borra. Ese es el\nbotón de la emergencia con contador y no el de una migración tranquila. Su\nconsejo sobre cuándo soltar la vieja es una medición y no una fecha: revisa sus\nregistros de peticiones y hazla expirar solo cuando su volumen lleve unas horas\no unos días a cero.",[10,405,406,408],{},[28,407,317],{}," Rotar crea la clave nueva con todas las restricciones de la vieja y,\nen sus palabras, \"both the old and new key are accepted\" durante la ventana en\nla que mueves tus aplicaciones. Si borras la vieja demasiado pronto y algo se\nrompe, hay vuelta atrás: una clave API de Google borrada se puede restaurar\ndentro de los 30 días.",[10,410,411,413],{},[28,412,342],{}," La secuencia está en su documentación y empieza por la clave nueva:\ncrea la segunda clave de acceso mientras la primera sigue activa, mueve cada\naplicación a ella, revisa la fecha de último uso de la vieja, desactívala y solo\nentonces bórrala. Un techo con el que contar: un usuario de IAM puede tener como\nmucho dos claves de acceso, así que una tercera aplicación que siga con una\nclave vieja no tiene adónde ir.",[10,415,416,418,419,355,421,423],{},[28,417,351],{}," Sin ventana. La rotación directa de las\nclaves heredadas ",[39,420,49],{},[39,422,77],{}," ya no está soportada, así que invalidar\nuna es una migración al nuevo par de claves, y el orden de los cuatro pasos es\nlo que mantiene la aplicación en pie.",[17,425,427],{"id":426},"sigue-estando-en-tu-historial-de-git","Sigue estando en tu historial de Git",[10,429,430],{},"Lo está, y la documentación de GitHub sobre eso empieza mandándote a otro sitio.",[10,432,433],{},"Su página sobre eliminar datos sensibles te devuelve a la clave: \"if the\nsensitive data you need to remove is a secret (e.g. password\u002Ftoken\u002Fcredential),\nas is often the case, then as a first step you need to revoke and\u002For rotate that\nsecret\", y después: \"Once the secret is revoked or rotated, it can no longer be\nused for access, and that may be sufficient to solve your problem. Going through\nthe extra steps to rewrite the history and remove the secret may not be\nwarranted.\"",[10,435,436],{},"La razón que dan es lo que un force push no alcanza. Después de reescribir tu\nhistorial, los commits viejos siguen ahí \"In any clones or forks of your\nrepository\" y \"Directly via their SHA-1 hashes in cached views on GitHub\". El\nsoporte puede limpiar las vistas en caché y las referencias en pull requests si\nlo pides, y marca su propia raya: \"will only assist in the removal of sensitive\ndata in cases where we determine that the risk can't be mitigated by rotating\naffected credentials.\" Un fork se queda con su copia en cualquier caso, y GitHub\nno puede darte los datos de contacto de su dueño.",[10,438,439],{},"Así que el orden que describen es el práctico: revocar la clave y después\ndecidir si reescribir el historial compensa sus efectos secundarios. Revocar\nalcanza copias que una reescritura no alcanza, incluida la de un clon del que no\nsabes nada y la de una captura que alguien guardó.",[95,441],{"alt":442,"caption":443,"src":444},"Tres documentos idénticos y apagados, un fork, el clon de alguien y una vista en caché, cada uno sujetando todavía la misma llave ámbar. Una sola línea turquesa cruza la imagen y tacha las tres llaves.","La misma llave, en tres copias que no puedes borrar. Revocarla tacha las tres de una vez.","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fone-line-covers-every-copy-1600x520.png",[17,446,448],{"id":447},"que-la-siguiente-no-entre-en-el-bundle","Que la siguiente no entre en el bundle",[10,450,451,454],{},[28,452,453],{},"Una clave entra en tu bundle por un despliegue, y los despliegues siguen\npasando."," Cada uno es otra oportunidad de que un valor que pusiste en un panel\nde secretos acabe en un archivo que el navegador descarga. Por eso una\ncomprobación hecha el mes pasado describe la aplicación del mes pasado.",[10,456,457],{},[28,458,459,462],{},[52,460,461],{"href":62},"Nuestro escaneo gratuito"," responde a la pregunta con la\nque llegaste.",[310,464,465,468,471],{},[313,466,467],{},"las nueve comprobaciones contra tu URL en vivo, en unos 20 segundos",[313,469,470],{},"cada clave que ve desde fuera, clasificada y no solo encontrada",[313,472,473],{},"una nota y los hallazgos, sin cuenta",[10,475,476],{},[28,477,478,482],{},[52,479,481],{"href":480},"\u002Fpricing","Reeve Monitor"," repite esas comprobaciones sin que lo pidas.",[310,484,485,488,495,498],{},[313,486,487],{},"las nueve comprobaciones cada hora, en hasta tres aplicaciones",[313,489,490,491,494],{},"un mensaje cuando un resultado ",[28,492,493],{},"cambia",", para que la clave que salió en el\ndespliegue de anoche no espere a que mires",[313,496,497],{},"si la aplicación responde, cada 60 segundos",[313,499,500],{},"un informe mensual de lo que vio",[10,502,503],{},[28,504,505,509],{},[52,506,508],{"href":507},"\u002Fsupabase-backups","Reeve Care"," guarda una copia de tu base de datos de\nSupabase, para las claves que pueden escribir.",[310,511,512,515,518,521,524],{},[313,513,514],{},"una copia cifrada cada noche, guardada donde tu proyecto no llega",[313,516,517],{},"cada copia verificada antes de contar, contando las filas de cada tabla",[313,519,520],{},"una restauración con un clic cuando la necesites",[313,522,523],{},"también tus archivos subidos, en cuanto conectes una credencial de Storage",[313,525,526],{},"todo lo que hace Monitor",[10,528,529,530,532,533,537],{},"Una clave filtrada que solo puede leer deja tus datos donde estaban. Una clave\n",[39,531,77],{},", o una de AWS con permisos de escritura, puede vaciar una tabla,\ny por mucho que rotes después las filas no vuelven.\n",[52,534,536],{"href":535},"\u002Fblog\u002Fai-agent-deleted-my-database","El día en que un agente de IA borró una base de datos de producción","\ncuenta cómo se ve eso desde dentro.",[17,539,541],{"id":540},"qué-hacer-ahora-mismo","Qué hacer ahora mismo",[543,544,545],"key-takeaways",{},[310,546,547,558,561,570,573,576],{},[313,548,549,550,46,552,554,555,557],{},"Identifica la clave antes de tocarla. Una clave ",[39,551,49],{},[39,553,45],{}," de Supabase y una ",[39,556,41],{}," de Stripe están donde deben estar, y de las 1.332 aplicaciones en las que encontramos una clave que merecía aviso, 1.142 tenían una clave API de Google, que pide una restricción en lugar de una rotación.",[313,559,560],{},"Pregúntate si tiene un contador. Si las peticiones de otra persona aterrizan en tu factura, para la clave ahora y deja que la función se rompa.",[313,562,563,564,566,567,569],{},"Usa el control que para igual que el que reemplaza: ",[28,565,327],{}," en Stripe, ",[28,568,345],{}," en AWS, una restricción por sitio y por API en Google.",[313,571,572],{},"Reemplázala después dentro de la ventana del proveedor. Stripe te da siete días con las dos claves activas, Google acepta ambas mientras migras, y AWS te deja tener dos claves de acceso a la vez.",[313,574,575],{},"Lee el registro del proveedor para el periodo entre el despliegue y la parada, y anota lo que encontraste, incluido \"nada\".",[313,577,578],{},"Deja el historial de Git para el final. Una vez revocada la clave, la propia guía de GitHub dice que reescribir el historial puede no merecer la pena en absoluto.",[10,580,581,582,586],{},"Si prefieres recorrer todo esto como una lista, la\n",[52,583,585],{"href":584},"\u002Fchecklist","checklist de seguridad en 10 minutos"," cubre esto y las otras cosas\nque conviene apagar en una aplicación recién lanzada.",{"title":588,"searchDepth":589,"depth":589,"links":590},"",3,[591,593,594,595,596,597,598,599,600],{"id":19,"depth":592,"text":20},2,{"id":67,"depth":592,"text":68},{"id":102,"depth":592,"text":103},{"id":304,"depth":592,"text":305},{"id":370,"depth":592,"text":371},{"id":390,"depth":592,"text":391},{"id":426,"depth":592,"text":427},{"id":447,"depth":592,"text":448},{"id":540,"depth":592,"text":541},"Fundamentos de seguridad","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcover-1200x630.png","Una tarjeta de acceso con una llave dibujada, delante de un panel de interruptores cuyo primer interruptor está bajado en posición de apagado.","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.",false,"md",[608,610,613,616,619],{"q":68,"a":609},"Averigua si la clave puede gastar dinero. Una clave que te cobra por petición te está costando algo ahora mismo, así que párala de inmediato y asume que la función que la usa se rompe unos minutos. Una clave que solo lee datos ya ha sido leída si era pública, así que tómate el tiempo de hacer el reemplazo en un orden que no te deje fuera de tu propia aplicación.",{"q":611,"a":612},"¿Revocar o rotar primero?","Revocar primero si la clave tiene un contador. Parar la clave vieja y emitir una nueva son dos controles separados en cada proveedor, y solo el primero cierra el agujero. La excepción es una clave que puedes restringir en su lugar: Google te dice que pruebes una restricción por sitio y por API antes de rotar una clave API de Google siquiera.",{"q":614,"a":615},"¿Cómo sé si alguien usó mi clave?","Reduce la ventana al periodo entre el despliegue que publicó la clave y el momento en que la paraste, y lee el registro del proveedor para ese rango. Stripe muestra registros de peticiones por clave, AWS muestra una fecha de último uso en la clave de acceso y guarda las llamadas en CloudTrail, Google grafica el uso por clave, y Supabase conserva registros de API y de base de datos. Buscas peticiones a cosas que tu aplicación nunca toca y tráfico a horas en que nadie la estaba usando. A menudo no puedes estar seguro, y ese es un resultado normal.",{"q":617,"a":618},"¿Rotar la clave romperá mi aplicación?","Normalmente no, si usas la ventana que te da el proveedor. Stripe mantiene la clave vieja y la nueva funcionando juntas hasta siete días. Google emite la clave nueva con las restricciones de la vieja y acepta ambas mientras migras. AWS te deja tener dos claves de acceso a la vez, así que la nueva ya está activa antes de que se vaya la vieja. La excepción es un proyecto antiguo de Supabase, donde el interruptor que desactiva las claves heredadas se lleva por delante la clave de tu frontend.",{"q":620,"a":621},"La clave está en mi historial de Git. ¿Basta con borrar el archivo?","No, y reescribir el historial probablemente tampoco sea la respuesta. La documentación de GitHub dice que revoques o rotes el secreto primero, y que una vez hecho eso, meterse a reescribir el historial puede no merecer la pena. Un force push no alcanza las copias en forks y clones, ni las vistas en caché a las que se llega por el hash del commit. Dejar la clave inservible cubre todas las copias de una vez.","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",[624,625,626,627,628,629,630,631],"clave api filtrada que hacer","api key filtrada","mi clave api es pública","clave api comprometida","rotar clave api filtrada","encontré mi api key en github","api key expuesta en el frontend","qué puede hacer alguien con mi clave api",{},true,"Tu clave API se filtró. Qué hacer, en orden","\u002Fblog\u002Fapi-key-leaked-what-to-do","2026-10-09",{"title":5,"description":604},"blog\u002Fapi-key-leaked-what-to-do",[640,641,642,643],"Si una clave API se filtró, lo primero que hay que hacer depende de qué clave sea. Las claves publicables van en tu frontend y no necesitan nada.","Si es un secreto de verdad, averigua si la clave puede gastar dinero. Es la única parte de esto que tiene un reloj corriendo.","Parar una clave y reemplazar una clave son dos controles distintos en cada proveedor, y casi todos te dan una ventana en la que las dos claves funcionan.","Después lee el registro del proveedor para el periodo en que la clave estuvo fuera, y deja en paz tu historial de Git hasta que la clave esté muerta.","ms8edW6my2DDWJGQQ3H4SKT3jGo4uZQ_AdxyE2AmXKY",[646,652,658,659,665,671,677,683,689,695,701,707,713,719,726,732,738,743,749,755,761,767,773,779,784,790,796,802,808,814,820,826,832,838,844,849,855,861,867,873,878,884,890,896,902,908,914,920,926,932,938,944,949,954,960,965,971,977,983,988,994],{"path":647,"title":648,"description":649,"published":650,"category":601,"image":651,"draft":605},"\u002Fblog\u002Fstorage-upload-violates-row-level-security","\"Row-level security policy for table objects\" al subir","\"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.","2026-10-11","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",{"path":653,"title":654,"description":655,"published":656,"category":601,"image":657,"draft":605},"\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":635,"title":5,"description":604,"published":636,"category":601,"image":622,"draft":605},{"path":660,"title":661,"description":662,"published":663,"category":601,"image":664,"draft":605},"\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":666,"title":667,"description":668,"published":669,"category":601,"image":670,"draft":605},"\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":672,"title":673,"description":674,"published":675,"category":601,"image":676,"draft":605},"\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":678,"title":679,"description":680,"published":681,"category":601,"image":682,"draft":605},"\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":684,"title":685,"description":686,"published":687,"category":601,"image":688,"draft":605},"\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":690,"title":691,"description":692,"published":693,"category":601,"image":694,"draft":605},"\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":696,"title":697,"description":698,"published":699,"category":601,"image":700,"draft":605},"\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":702,"title":703,"description":704,"published":705,"category":601,"image":706,"draft":605},"\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":708,"title":709,"description":710,"published":711,"category":601,"image":712,"draft":605},"\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":714,"title":715,"description":716,"published":717,"category":601,"image":718,"draft":605},"\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":720,"title":721,"description":722,"published":723,"category":724,"image":725,"draft":605},"\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":727,"title":728,"description":729,"published":730,"category":724,"image":731,"draft":605},"\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":733,"title":734,"description":735,"published":736,"category":724,"image":737,"draft":605},"\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":739,"title":740,"description":741,"published":736,"category":601,"image":742,"draft":605},"\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":744,"title":745,"description":746,"published":747,"category":601,"image":748,"draft":605},"\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":750,"title":751,"description":752,"published":753,"category":601,"image":754,"draft":605},"\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":756,"title":757,"description":758,"published":759,"category":724,"image":760,"draft":605},"\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":762,"title":763,"description":764,"published":765,"category":601,"image":766,"draft":605},"\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":768,"title":769,"description":770,"published":771,"category":601,"image":772,"draft":605},"\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":774,"title":775,"description":776,"published":777,"category":601,"image":778,"draft":605},"\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":294,"title":780,"description":781,"published":782,"category":601,"image":783,"draft":605},"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":785,"title":786,"description":787,"published":788,"category":601,"image":789,"draft":605},"\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":791,"title":792,"description":793,"published":794,"category":601,"image":795,"draft":605},"\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":797,"title":798,"description":799,"published":800,"category":601,"image":801,"draft":605},"\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":803,"title":804,"description":805,"published":806,"category":601,"image":807,"draft":605},"\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":809,"title":810,"description":811,"published":812,"category":724,"image":813,"draft":605},"\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":815,"title":816,"description":817,"published":818,"category":724,"image":819,"draft":605},"\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":821,"title":822,"description":823,"published":824,"category":724,"image":825,"draft":605},"\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":827,"title":828,"description":829,"published":830,"category":601,"image":831,"draft":605},"\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":833,"title":834,"description":835,"published":836,"category":601,"image":837,"draft":605},"\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":839,"title":840,"description":841,"published":842,"category":601,"image":843,"draft":605},"\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":299,"title":845,"description":846,"published":847,"category":601,"image":848,"draft":605},"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":850,"title":851,"description":852,"published":853,"category":601,"image":854,"draft":605},"\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":856,"title":857,"description":858,"published":859,"category":601,"image":860,"draft":605},"\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":862,"title":863,"description":864,"published":865,"category":601,"image":866,"draft":605},"\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":868,"title":869,"description":870,"published":871,"category":601,"image":872,"draft":605},"\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":285,"title":874,"description":875,"published":876,"category":601,"image":877,"draft":605},"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":879,"title":880,"description":881,"published":882,"category":601,"image":883,"draft":605},"\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":885,"title":886,"description":887,"published":888,"category":724,"image":889,"draft":605},"\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":891,"title":892,"description":893,"published":894,"category":601,"image":895,"draft":605},"\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":897,"title":898,"description":899,"published":900,"category":724,"image":901,"draft":605},"\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":903,"title":904,"description":905,"published":906,"category":601,"image":907,"draft":605},"\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":909,"title":910,"description":911,"published":912,"category":601,"image":913,"draft":605},"\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":915,"title":916,"description":917,"published":918,"category":601,"image":919,"draft":605},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","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":921,"title":922,"description":923,"published":924,"category":601,"image":925,"draft":605},"\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":927,"title":928,"description":929,"published":930,"category":724,"image":931,"draft":605},"\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":933,"title":934,"description":935,"published":936,"category":724,"image":937,"draft":605},"\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":939,"title":940,"description":941,"published":942,"category":601,"image":943,"draft":605},"\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":290,"title":945,"description":946,"published":947,"category":601,"image":948,"draft":605},"¿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":535,"title":950,"description":951,"published":952,"category":724,"image":953,"draft":605},"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":955,"title":956,"description":957,"published":958,"category":601,"image":959,"draft":605},"\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":961,"title":962,"description":963,"published":958,"category":601,"image":964,"draft":605},"\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":966,"title":967,"description":968,"published":969,"category":601,"image":970,"draft":605},"\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":972,"title":973,"description":974,"published":975,"category":724,"image":976,"draft":605},"\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":978,"title":979,"description":980,"published":981,"category":601,"image":982,"draft":605},"\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":984,"title":985,"description":986,"published":981,"category":724,"image":987,"draft":605},"\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":989,"title":990,"description":991,"published":992,"category":724,"image":993,"draft":605},"\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":54,"title":995,"description":996,"published":992,"category":601,"image":997,"draft":605},"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",1791705962944]