Desmitificando CORS: ¿Por qué NO es la armadura que protege tu Backend?
Como desarrolladores, hemos visto este error un millón de veces en la consola del navegador: Cross-Origin Resource Sharing Error
. Nuestra reacción casi instintiva suele ser buscar en Google, copiar una configuración en nuestro servidor y seguir adelante una vez que el mensaje rojo desaparece.
Durante mucho tiempo, yo (y muchos otros) operé bajo una creencia fundamental pero errónea: que CORS era un escudo de seguridad para mi backend. Que era el servidor quien activamente bloqueaba estas solicitudes maliciosas.
Hasta que un día, un colega me hizo una pregunta que desmoronó mi percepción:
“Si CORS realmente protege tu backend, ¿por qué herramientas como Postman, Insomnia o cURL pueden llamar a tu API sin ningún problema y sin ninguna configuración especial de CORS?”
La pregunta fue un golpe de claridad. Nunca hemos añadido la "huella" de Postman a nuestra lista blanca de CORS, y sin embargo, cada petición funciona a la perfección. ¿Por qué?
La respuesta revela la verdadera naturaleza de CORS: es una historia sobre quién tiene el poder de proteger a quién.
La Falsa Sensación de Seguridad
La confusión es comprensible. Configuramos las políticas de CORS en el servidor, por lo que parece lógico que sea el servidor quien las aplique. Pero la realidad es más sutil y mucho más interesante.
Para entenderlo, imaginemos un escenario clásico que expone una vulnerabilidad conocida como CSRF (Cross-Site Request Forgery).
-
Inicias Sesión: Abres tu navegador y visitas la página de tu banco,
mi-banco.com
. Ingresas tus credenciales y el frontend realiza las llamadas necesarias a la API del banco,api-banco.com
. Como resultado, tu navegador almacena las cookies de sesión que te mantienen autenticado. -
Visitas un Sitio Malicioso: Luego, en otra pestaña, navegas a un sitio de apariencia inofensiva,
sitio-engañoso.com
, que te prometió ver fotos de gatitos. -
El Ataque Silencioso: Sin que lo sepas, ese sitio ejecuta un script en segundo plano. Este script intenta realizar una transferencia de dinero desde tu cuenta:
// Script malicioso en sitio-engañoso.com
fetch("https://api-banco.com/transferencia?destino=12345&monto=5000", {
method: "POST",
credentials: "include" // ¡La clave del ataque!
});
Si no existiera CORS, esto es lo que pasaría:
-
El navegador ve una petición a
api-banco.com
. -
La opción
credentials: "include"
le dice al navegador que debe adjuntar cualquier cookie relevante que tenga para ese dominio. ¡Y las tiene, porque iniciaste sesión antes! -
La API del banco recibe la petición, ve una cookie de sesión válida y piensa: "Esta es una solicitud de un usuario autenticado. ¡Procedamos con la transferencia!".
-
Resultado: Acabas de perder 5,000 unidades de tu moneda.

¿Cómo nos Salva CORS?
Cuando el script en sitio-engañoso.com
intenta hacer la petición, el navegador moderno interviene y dice: "Un momento. Este script se origina en sitio-engañoso.com
, pero la petición va a api-banco.com
. Esto es una solicitud de origen cruzado (cross-origin). Debo ser cauteloso".
Antes de enviar la petición POST
real, el navegador envía una petición de "verificación previa" (conocida como preflight request) usando el método OPTIONS
. Esta petición le pregunta al servidor:
Navegador: "Hola, api-banco.com
. Un sitio en sitio-engañoso.com
quiere enviarte una petición POST
con credenciales. ¿Le das permiso?"
El servidor, que ha sido configurado correctamente por sus desarrolladores, responde con unos encabezados (headers
) específicos:
Servidor: "Hola, navegador. Solo permito peticiones que provengan de https://mi-banco.com
."
(Técnicamente, responde con el encabezado: Access-Control-Allow-Origin: https://mi-banco.com
)
El navegador recibe esta política, la revisa y concluye:
Navegador: "La petición viene de sitio-engañoso.com
, pero el servidor solo permite mi-banco.com
. No coinciden. Voy a bloquear esta solicitud."
El resultado es el famoso error de CORS que vemos en la consola. La petición POST
maliciosa nunca llega al servidor. El navegador la detiene antes de que pueda causar daño.
La Pieza Final del Rompecabezas: Postman
Ahora podemos responder a la pregunta inicial. Postman no es un navegador. No implementa la Política del Mismo Origen (Same-Origin Policy). Es una herramienta para hacer peticiones HTTP directas. No le importan los orígenes ni las políticas de seguridad del navegador. Simplemente envía la solicitud y te muestra la respuesta cruda del servidor.
CORS no protege tu backend de Postman, de un script en Python o de un ataque directo a tu servidor. CORS protege al usuario y su navegador de sitios web maliciosos que intentan abusar de sus sesiones.
Hagamos una pequeña conclusión
La historia de CORS es un recordatorio poderoso de que en el desarrollo de software, entender el "porqué" es tan crucial como saber el "cómo".
-
El rol del Backend: Definir la política de seguridad (
Access-Control-Allow-Origin
). -
El rol del Navegador: Hacer cumplir esa política para proteger al usuario.
Así que la próxima vez que te enfrentes a un error de CORS, recuerda que no estás luchando contra una fortaleza en tu servidor. Estás trabajando con una característica de seguridad del navegador diseñada para mantener el ecosistema web un lugar más seguro.
Y nunca dejes de hacer preguntas. La curiosidad que nos lleva a cuestionar lo que creemos saber es nuestro verdadero superpoder como desarrolladores. Es el motor del aprendizaje auténtico.