Saltar al contenido

Fundamentos de seguridad

¿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.

Vlad Tkachenko10 min de lectura
Seis llamadores distintos alcanzan un mismo servidor, y la misma respuesta vuelve hacia cada uno de ellos.

En resumen

  • Un comodín CORS solo es un riesgo de seguridad cuando detrás de él responde algo privado. Por sí solo permite leer cosas que cualquiera podía descargar ya.
  • La cabecera es una instrucción para el navegador de tu visitante y llega después de que la respuesta ya se haya enviado. Fuera de un navegador nadie la lee, así que restringirla deja un endpoint abierto igual de abierto.
  • Lo que merece una tarde es un servidor que devuelve como eco el sitio web que está preguntando y además permite credenciales. Eso sí deja que otra web lea datos como tu usuario con la sesión iniciada.

Tu escaneo volvió con una línea que se lee como una alarma: tu API está abierta a cualquier web. O alguien con conocimientos técnicos miró lo que devuelve tu servidor y te dijo que tu aplicación tiene un comodín CORS, que es el carácter *, que al parecer significa todo el mundo.

Aquí está la parte que guía tras guía cuenta mal: el comodín casi nunca es lo que abrió tu API. Es una instrucción que tu servidor adjunta a sus respuestas, dirigida a los navegadores de gente que está sentada en otras webs, y llega después de que la respuesta ya haya salido. Restringirlo impide que la página de otra web lea tus datos. No hace nada contra alguien que las lea sin navegador ninguno.

¿Es un comodín CORS un riesgo de seguridad?

Por sí solo, casi nunca. Se convierte en uno en el momento en que detrás responde algo privado.

El comodín es el valor * en una cabecera de respuesta llamada Access-Control-Allow-Origin, y significa que el código de cualquier web puede leer esa respuesta en concreto. Eso suena a una declaración sobre quién puede llegar a tus datos. Es una declaración sobre quién puede leer lo que tu servidor ya ha enviado.

La dirección que comprueba un escaneo es aquella desde la que se sirve tu aplicación. En la mayoría de builders esa dirección reparte tus páginas, tus imágenes y tu código compilado, y todo eso llega a cada visitante por diseño. Un comodín sobre eso concede permiso para leer archivos que cualquiera podía descargar ya con solo abrir tu web.

Así que el hallazgo es una pregunta y no un veredicto, y la pregunta es qué hay detrás de la cabecera. Si la respuesta es tu página de inicio, no ha pasado nada. Si la respuesta es una lista de tus clientes, esa lista ya estaba al alcance de cualquiera que tuviera la dirección.

Qué hace realmente Access-Control-Allow-Origin

Le dice al navegador de tu visitante si la página que tiene en pantalla puede mirar una respuesta que tu servidor ya ha enviado.

El orden lo es todo, y va al revés de como casi todo el mundo se lo imagina. Una página en alguna otra web ejecuta un trozo de código que le pide datos a tu aplicación. La petición sale. Tu servidor la recibe, ejecuta lo que sea que ejecute y devuelve la respuesta entera. Solo entonces el navegador lee la cabecera de esa respuesta y decide si entrega el contenido a la página que lo pidió. La propia guía de CORS de MDN lo resume en una línea: el servidor tiene que dar su consentimiento con Access-Control-Allow-Origin para compartir la respuesta con el script.

Tus datos salieron del edificio en ambos casos. Lo que decide la cabecera es si un trozo concreto de código, ejecutándose dentro del navegador de una persona concreta, llega a verlos.

Ambos llamadores reciben una respuesta, porque el servidor la envía antes de que se compruebe nada. La barrera del carril superior es el navegador, y en el carril inferior no hay ningún navegador.

El navegador es lo único en esa historia que lee la cabecera. Un script en un servidor, una herramienta de línea de comandos, un scraper, una aplicación móvil: ninguno la consulta, porque se escribió para un navegador y no hay navegador de por medio. Envían la misma petición, reciben la misma respuesta y leen cada byte.

Restringir CORS no hace privado un endpoint abierto

Porque CORS vive dentro de los navegadores, y quien se está sirviendo de tus datos no tiene motivo para usar uno.

Esta es la parte que le cuesta una tarde a la gente. Ven el hallazgo del comodín, estrechan la cabecera a su propio dominio, despliegan de nuevo, escanean otra vez, y la dirección que repartía filas de clientes sigue repartiendo filas de clientes. Siempre lo hizo. El único llamador que llegó a detenerse fue la página web de otra persona.

Lo que alguien intentaComodín *Solo tu dominioCualquier origen devuelto como eco, con credenciales
Abrir la dirección en una pestaña del navegadorFuncionaFuncionaFunciona
Leerla desde un script o una terminalFuncionaFuncionaFunciona
La página de otra web leyéndolaFuncionaBloqueadoFunciona
Otra web leyéndola como tu usuario con la sesión iniciadaBloqueadoBloqueadoFunciona

Lee la última fila dos veces, porque es donde se cae el consejo genérico. Un comodín a secas no puede usarse para leer datos que pertenecen a tu visitante con la sesión iniciada. Los navegadores rechazan esa combinación de plano, y la guía de CORS de MDN lo dice directamente: si una petición lleva una cookie y la respuesta vuelve con Access-Control-Allow-Origin: *, el navegador bloquea el acceso a la respuesta y registra un error de CORS en la consola. Así que el comodín, precisamente, es lo que hace imposible ese ataque en concreto.

La columna que sí entrega los datos de un usuario con la sesión iniciada es la tercera, y para eso hace falta que el servidor escriba la dirección del propio llamador dentro de su respuesta.

El ajuste de CORS que sí es peligroso

Un servidor que lee la cabecera Origin de la petición, escribe ese mismo valor dentro de su propia respuesta y envía Access-Control-Allow-Credentials: true junto a ella.

Nadie se propone hacer esto. Aparece al final de una tarde intentando que un comodín funcione con peticiones autenticadas y descubriendo que nunca lo hará. Devolver como eco el origen que ha preguntado parece la salida: toda web que deba estar permitida lo está, los errores de consola cesan, la funcionalidad sale. Lo que el servidor está diciendo en realidad es que decide el llamador, y eso incluye una página que nadie ha escrito todavía.

Esto es lo que permite. Tu clienta tiene la sesión iniciada en tu aplicación, con una cookie de sesión en su navegador. En otra pestaña abre un sitio que no tiene nada que ver contigo. El código de ese sitio le pide su cuenta a tu API. Su navegador adjunta la cookie, porque adjuntar cookies es lo que hacen los navegadores. Tu servidor lee un Origin del que nunca ha oído hablar, lo estampa en la respuesta como permiso y añade que las credenciales están bien. El navegador comprueba, encuentra coincidencia y entrega los datos de tu clienta a una página que ella no sabía que estaba leyéndolos.

El llamador aporta el nombre, y el servidor escribe ese nombre en el pase. Quien pregunta está en la lista, y eso es lo que distingue este caso de un comodín.

En nuestro barrido de agosto de 2026 esto apareció en 61 de las 30.926 aplicaciones donde la comprobación pudo obtener respuesta. De los tres hallazgos de CORS, es el único que alcanza datos que están detrás de un inicio de sesión.

Con qué frecuencia aparece un comodín, y quién lo decide

En su mayoría lo decide tu builder. En ese mismo barrido, 5.727 de esas 30.926 aplicaciones enviaban un comodín, y el mejor predictor individual de si la tuya lo hace es la plataforma que la publicó.

La comprobación de CORS reportó al menos un hallazgo en 5.418 de las 5.419 aplicaciones de Base44 donde obtuvo respuesta, y en 8 de las 18.518 de Lovable. Replit quedó en medio, con 1.129 de 3.037. Una horquilla así de amplia es lo que parece un ajuste por defecto del hosting visto desde fuera: casi total en una plataforma, casi ausente en otra, a lo largo de miles de aplicaciones cuyos dueños nunca coordinaron nada.

Tres hallazgos distintos componen la comprobación de CORS en las 30.926 aplicaciones: un comodín en 5.727 de ellas, una dirección que responde con datos y sin inicio de sesión en 3.852, y la forma del origen devuelto como eco en 61. Suman más que la propia comprobación, porque muchas aplicaciones tienen dos de las tres. Cada cifra de aquí sale de nuestro escaneo de 30.998 aplicaciones vibe-coded en producción, que publica cada una junto con la base sobre la que se midió.

Lo que puedes cambiar de todo eso se reparte igual. El comodín lo envía quien sirve tu aplicación, y en una aplicación vibe-coded eso suele ser el builder. Lo que vuelve cuando un desconocido le pide datos a una de tus direcciones se decidió dentro de tu aplicación, por ti o por el builder que escribe código en tu nombre.

Cómo comprobar tu propia aplicación

Dos cosas que mirar, y la segunda es la que decide si algo de esto importa.

¿Tu aplicación envía un comodín? Abre tu aplicación en producción, pulsa F12 para abrir las herramientas de desarrollo del navegador, haz clic en Network y recarga la página. Haz clic en la primera petición de la lista y lee el panel Response Headers. Una línea que ponga access-control-allow-origin: * es el hallazgo. Que no haya ninguna línea así significa que tu servidor no comparte nada entre orígenes con nadie.

¿Qué responde detrás? Quédate en la pestaña Network y recarga tu aplicación con la sesión iniciada, atento a las peticiones que vuelven como JSON. Esas son las direcciones de las que tu aplicación saca datos. Copia cada URL, abre una ventana de navegación privada para estar sin sesión iniciada y pégalas de una en una. Todo lo que vuelva con filas reales, en lugar de un error o una lista vacía, es legible por cualquiera en internet que tenga esa URL. Eso es cierto hoy, diga lo que diga tu cabecera CORS, y sigue siendo cierto después de que la estreches.

Nuestro escaneo gratuito hace la segunda comprobación por ti: lee el código de tu aplicación en busca de las direcciones que llama, pide cada una sin inicio de sesión y reporta las que respondieron con datos. Tarda unos 20 segundos y no necesita cuenta: escanea tu aplicación.

Si tu aplicación habla con Supabase directamente desde el navegador, hay un tercer sitio donde mirar, porque las reglas de cada tabla deciden quién puede leer qué filas y activarlas no es lo mismo que estar protegido.

Qué hacer ahora mismo

Qué hacer

  • Trata un hallazgo de comodín como una pregunta sobre qué hay detrás de la cabecera. En la dirección desde la que se sirve tu aplicación, suele permitir leer archivos que cada visitante descarga igualmente.
  • Cierra la sesión y abre todas las direcciones de datos que llama tu aplicación. Todo lo que devuelva filas reales a un navegador sin sesión es público para todo el mundo, diga lo que diga la cabecera.
  • Arregla una dirección abierta en la propia dirección: exige un inicio de sesión y responde a un desconocido con un 401. Estrechar la cabecera CORS la deja alcanzable por todo excepto por las páginas web de otras personas.
  • Si tu servidor devuelve como eco el origen que ha preguntado y envía Access-Control-Allow-Credentials: true, sustitúyelo hoy por una lista de tus propios dominios. Es el único caso de aquí que deja a otra web leer datos como tu usuario con la sesión iniciada.
  • Si la cabecera viene del hosting de tu builder y no puedes cambiarla, dedica el tiempo a los endpoints. Ahí es donde están tus datos.

La costumbre que merece la pena mantener es la pasada sin sesión por tus propias direcciones de datos, porque cada funcionalidad nueva añade una más y en pantalla no se ve nada distinto cuando una de ellas empieza a responder. Reeve Care vuelve a ejecutar este escaneo contra tu aplicación en producción de forma periódica y te avisa por correo cuando un resultado empeora: qué vigila y cuánto cuesta.

Si prefieres resolverlo todo de una sentada, la lista de seguridad de 10 minutos cubre esto junto al resto de lo que una aplicación recién lanzada suele dejar abierto, y qué claves son seguras en tu frontend es la otra mitad de la pregunta con la que suele llegar la gente.

Preguntas frecuentes

Mi escaneo dice que mi API está abierta a cualquier web. ¿Tengo que arreglarlo?

Mira primero qué responde detrás. Un comodín en la dirección desde la que se sirve tu aplicación suele permitir leer tus páginas, tus imágenes y tu código compilado, y todo eso lo descarga igualmente cada visitante. Arréglalo cuando una dirección detrás de esa cabecera devuelva datos reales a alguien que no ha iniciado sesión, y arréglalo en esa dirección exigiendo un inicio de sesión.

¿Restringir CORS a mi propio dominio hace privada mi API?

No. CORS es una regla que los navegadores se aplican a sí mismos, así que solo gobierna código que se ejecuta en la página web de otra persona. Un script, un comando de terminal o un scraper envían la misma petición y leen la misma respuesta, porque ninguno consulta la cabecera. Si una dirección devuelve tus datos sin inicio de sesión, lo hace para todo el mundo, diga lo que diga la cabecera.

¿Puede otra web leer los datos de mis usuarios con la sesión iniciada por culpa de un comodín?

Con un comodín a secas, no. Los navegadores rechazan esa combinación: la guía de CORS de MDN indica que, cuando una petición lleva una cookie y la respuesta vuelve con Access-Control-Allow-Origin puesto en el comodín, el navegador bloquea el acceso a la respuesta y registra un error de CORS. La versión que sí funciona es un servidor que devuelve como eco el origen que ha preguntado, junto con Access-Control-Allow-Credentials puesto en true.

¿Cómo cambio la cabecera CORS en una aplicación de Lovable o Base44?

Muchas veces no puedes, porque la cabecera la envía el hosting al que publica tu builder y se aplica a todas las aplicaciones de esa plataforma. Conviene saberlo antes de dedicarle una semana. Lo que siempre puedes cambiar es lo que tus propios endpoints devuelven a una petición sin inicio de sesión, y ahí es donde corresponde el arreglo de todos modos.

Mi escaneo también marcó endpoints de API abiertos. ¿Es el mismo hallazgo?

Es otro, y el más grave de los dos. Un comodín describe quién puede leer una respuesta. Un endpoint abierto significa que la respuesta contenía tus datos y llegó sin que nadie iniciara sesión. Lo segundo es cierto para un navegador, para un script y para un desconocido con la URL por igual, y estrechar tu cabecera CORS no cambia nada de eso.

Escrito por

Vlad Tkachenko

Fundador de Reeve

Me paso el día mirando apps creadas con Lovable, Bolt, v0, Cursor y Replit, y la corta lista de errores que aparecen en ellas una y otra vez.

Más sobre el autor

Sigue leyendo

¿No sabes cómo está tu propia app?

Haz un escaneo gratuito y obtén una nota clara de la A a la F en unos 20 segundos. Sin cuenta y sin tarjeta.

Analizar mi app gratis

Comprobación externa automatizada, no una auditoría completa. La ausencia de hallazgos no es garantía de seguridad.