← Todos los checks
SeguridadSeveridad típica: Alto

Detector de CORS permisivo

Comprueba si tu política CORS refleja cualquier origen con credenciales, exponiendo datos de tus usuarios.

Qué comprueba

Este escaner comprueba tu politica CORS para ver si acepta peticiones desde cualquier origen a la vez que permite enviar credenciales. Esta combinacion es la configuracion mas peligrosa posible de CORS. Solo mira como respondes a peticiones de otros dominios, no accede a datos.

Por qué importa

Si reflejas cualquier origen con credenciales, un sitio malicioso puede hacer peticiones a tu API usando la sesion de un usuario y leer la respuesta. Eso expone datos privados de tus usuarios a terceros. Suele ocurrir por copiar una configuracion abierta de ejemplos o tutoriales.

Cómo se arregla

Sustituye el origen comodin por una lista concreta de dominios de confianza que realmente necesiten acceder a tu API. Si no necesitas enviar credenciales entre dominios, desactiva esa opcion. Revisa la configuracion CORS de tu backend o framework y evita reflejar automaticamente el origen recibido.

Cómo funciona esta comprobación

Scanaris vuelve a pedir tu página principal con una cabecera Origin de un dominio inventado, como haría el navegador si otra web intentara llamarte, y mira qué responde tu servidor. Si Access-Control-Allow-Origin devuelve ese mismo origen y además Access-Control-Allow-Credentials vale true, abre un hallazgo de severidad alta: tu servidor refleja cualquier origen con credenciales. Si responde con el comodín * junto con credenciales, abre uno de severidad baja: los navegadores rechazan esa combinación, pero delata una configuración hecha a ciegas. Solo se prueba la URL escaneada; si tu API vive en otra ruta o dominio, pruébala con el comando de más abajo.

Qué hace un atacante con esto

Monta una página en cualquier dominio con un fetch a tu API usando credentials: 'include'. Cuando uno de tus usuarios, con sesión abierta, visita esa página, el navegador adjunta sus cookies, tu servidor responde con los datos del usuario y, como la política CORS lo permite, la página del atacante los lee. Perfil, pedidos, mensajes, lo que devuelva la API. El usuario no ve nada: ocurre en segundo plano.

Por qué ocurre

CORS existe para que el navegador bloquee por defecto las lecturas entre dominios. Cuando una llamada falla en desarrollo (la app en un puerto, la API en otro), la solución rápida que sugieren los tutoriales y las herramientas de IA es "permitir todos los orígenes", y para que funcionen las cookies se añade "con credenciales". En producción eso significa que la protección quedó desactivada. Más detalle en CORS mal configurado: el fallo silencioso que expone a tus usuarios.

Cómo arreglarlo

  • Lista explícita de orígenes. Solo los dominios que de verdad llaman a tu API desde el navegador. En Express: cors({ origin: ['https://app.tudominio.com'], credentials: true }). En Next.js, en el Route Handler, compara el Origin con tu lista antes de devolverlo. En Nuxt, con routeRules y la opción cors o un middleware de servidor.
  • Nunca reflejes el origen. Copiar el valor de Origin en la respuesta "porque así funciona todo" es el error exacto que mide el check.
  • Si no necesitas cookies entre dominios, quita Access-Control-Allow-Credentials. Sin credenciales, un * en una API pública de solo lectura es aceptable.
  • Añade Vary: Origin cuando la respuesta dependa del origen, para que ninguna caché sirva a un dominio la respuesta de otro.
  • Cookies con SameSite=Lax o Strict como segunda barrera: aunque CORS fallara, el navegador no las enviaría desde otro sitio.

Comprueba que está arreglado

curl -sI -H "Origin: https://evil.example" https://tudominio.com/api/me | grep -i "access-control"

Lo correcto es que no aparezca Access-Control-Allow-Origin para ese origen, o que aparezca con tu dominio y no con evil.example. Prueba también con tu propio dominio en Origin para confirmar que tu app sigue funcionando.

Preguntas frecuentes

Mi API es pública y sin login. ¿Es un problema?

No, si no hay cookies ni cabeceras de autorización. Access-Control-Allow-Origin: * sin credenciales es la configuración correcta para una API abierta.

Tengo varios subdominios que llaman a la API.

Lístalos todos o valida el Origin contra un patrón estricto de tu dominio raíz. Nunca valides con "contiene tudominio.com": tudominio.com.evil.example lo cumple.

¿Y localhost para desarrollar?

Añádelo solo en el entorno de desarrollo, con una variable de entorno. Un http://localhost:3000 en la lista de producción es un origen que cualquier programa en el ordenador del usuario puede usar.

Compruébalo en tu web

Escanea tu web gratis y mira si este y otros 44 checks pasan, con un prompt de arreglo por cada fallo.

Escanear mi web gratis

Del blog

Checks relacionados