Web Security

Seguridad Web

La seguridad no es una funcionalidad que se añade al final. XSS, CSRF, CORS y una autenticación segura son la base que todo desarrollador web debe comprender.

intermediate15 min readUpdated 15 sept 2026
comment.js
js
// comment.js
function renderComment(text) {
  const el = document.createElement("p");
  // textContent escapes markup, so
  // <script> is shown as text, not run
  el.textContent = text;
  return el;
}
Regla de oro
Nunca confíes en el cliente
Riesgo principal
Cross-site scripting
Transporte
HTTPS en todas partes
Sesiones
Cookies HttpOnly y Secure
Defensa en profundidad
Codificar, validar, restringir
Referencia
OWASP Top 10

Por que importa

Por qué la seguridad es responsabilidad de todos

Protege a tus usuarios

Un solo error de XSS puede exponer cuentas, datos y dinero. Los fallos de seguridad son los bugs más costosos que puedes desplegar.

Protege la sesión

Las cookies, los tokens y la protección CSRF deciden si un atacante puede actuar en nombre de tu usuario.

Protege los datos

El hashing de contraseñas, la validación de entradas y el principio de menor privilegio mantienen las brechas contenidas.

La imagen completa

Los tres frentes de la seguridad web

No confíes en nada que venga del cliente, protege la sesión y configura correctamente las defensas del navegador.

Entradas no confiables

Asume lo peor

Todo lo que provenga del cliente puede ser falsificado, así que valida y codifica en el servidor.

El navegador

Ejecutar

Cabeceras como CSP, HSTS y los flags de las cookies permiten que el navegador haga cumplir tus reglas.

El servidor

Decidir

La autenticación, la autorización y el acceso a los datos pertenecen al servidor, nunca al cliente.

Seguridad de un vistazo

Amenazas y defensas

XSS

Scripts inyectados que se ejecutan en tu página. Evítalo con la codificación de salida.

CSRF

Solicitudes falsificadas que utilizan las cookies de la víctima. Evítalo con tokens y SameSite.

CORS

Una regla del navegador sobre qué orígenes pueden leer las respuestas.

Autenticación

Sesiones, tokens, hashing y autenticación de múltiples factores.

HTTPS

Cifra el tráfico y habilita HSTS.

CSP

Restringe qué scripts, estilos y conexiones puede utilizar una página.

Una breve historia

Cómo la web aprendió a defenderse

  1. 2005

    XSS se vuelve masivo

    El cross-site scripting se convierte en una de las vulnerabilidades web más reportadas.

    05
  2. 2008

    Se endurece la política de mismo origen

    Los navegadores endurecen las reglas sobre las lecturas cross-origin y el acceso a cookies.

    08
  3. 2012

    Content Security Policy

    CSP ofrece a los sitios una forma de declarar en qué fuentes debe confiar el navegador.

    12
  4. 2014

    HTTPS en todas partes

    Let's Encrypt y HSTS impulsan la web hacia el cifrado universal.

    14
  5. Hoy

    Seguro por defecto

    Los frameworks y plataformas modernos incluyen valores predeterminados más seguros, pero los desarrolladores aún deben configurarlos.

    Hoy

La guia completa

Seguridad Web: Todo lo que necesitas saber

Por qué la seguridad es responsabilidad de todos

La seguridad web no es un asunto especializado que alguien más maneja. Cada formulario, cada comentario renderizado, cada cookie y cada endpoint de una API es una oportunidad para cometer un error que exponga a tus usuarios. El coste de un bug de seguridad es inusualmente alto: pérdida de datos, ruptura de la confianza y riesgos legales.

La buena noticia es que la mayoría de los ataques siguen un número reducido de patrones y la mayoría de las defensas están bien documentadas. Esta guía cubre lo esencial: cross-site scripting, cross-site request forgery, CORS, autenticación segura y los headers del navegador que hacen cumplir tus reglas.

La regla de oro

Nunca confíes en el cliente. Cualquier dato que provenga del navegador puede ser falsificado: valores de formularios, headers, campos ocultos, precios, IDs de usuario y el estado de JavaScript. La validación en el lado del cliente es para mejorar la experiencia de usuario; el servidor debe validar y autorizar todo nuevamente.

Este único principio es la base de casi cualquier defensa. Si asumes que la entrada de datos es hostil y que los permisos deben verificarse en el servidor, la mayoría de las vulnerabilidades desaparecen antes siquiera de ser escritas.

Cross-site scripting (XSS)

El XSS es la vulnerabilidad web grave más común. Ocurre cuando datos controlados por un atacante son tratados como código. Existen tres tipos principales: almacenado (guardado en el servidor y servido a otros usuarios), reflejado (devuelto en una respuesta) y basado en el DOM (introducido por JavaScript en el lado del cliente).

La defensa principal es la codificación de salida (output encoding): codifica los datos según el contexto donde aparezcan. En el DOM, utiliza textContent en lugar de innerHTML.

// safe.js
const el = document.createElement("p");
el.textContent = userComment; // escaped

// If you truly need HTML, sanitise it
import DOMPurify from "dompurify";
el.innerHTML = DOMPurify.sanitize(userHtml);

En el servidor, utiliza motores de plantillas que escapen los datos por defecto y nunca construyas SQL o HTML mediante concatenación de strings. Para las bases de datos, utiliza siempre consultas parametrizadas o un ORM para que la entrada nunca pueda convertirse en SQL.

Content Security Policy

Una Content Security Policy es un encabezado de respuesta que le indica al navegador qué fuentes puede utilizar una página. Una política estricta convierte muchos errores de XSS en simples errores inofensivos en la consola.

Content-Security-Policy:
  default-src 'self';
  script-src 'self';
  object-src 'none';
  base-uri 'self';
  frame-ancestors 'none';

Comienza con Content-Security-Policy-Report-Only para recopilar violaciones sin romper el sitio y, posteriormente, aplícala. Evita unsafe-inline y unsafe-eval siempre que sea posible, y utiliza nonces o hashes para los scripts inline que no puedas eliminar.

Cross-site request forgery (CSRF)

El CSRF engaña al navegador para que envíe una solicitud autenticada utilizando las cookies de la víctima. Si tu sitio utiliza sesiones basadas en cookies y un endpoint que cambia el estado acepta una solicitud simple, la página de un atacante puede activarlo.

Defensas, por capas:

  • Cookies SameSite. SameSite=Lax o Strict evita que las cookies se envíen en solicitudes cross-site en los navegadores modernos.
  • Tokens Anti-CSRF. Un token por sesión incluido en los formularios y verificado en el servidor.
  • Verificar el origen. Rechazar las solicitudes que cambien el estado cuyo encabezado Origin no sea tu sitio.
  • Nunca mutar en GET. Utiliza POST, PUT, PATCH o DELETE para realizar cambios.

CORS

CORS es una regla del navegador sobre qué orígenes pueden leer las respuestas de tu API. Por defecto, una página no puede leer una respuesta de un origen distinto a menos que el servidor lo permita mediante Access-Control-Allow-Origin.

Hay dos puntos que suelen malinterpretarse:

  • CORS protege el navegador del usuario, no tu servidor. Otros servidores pueden llamar a tu API libremente; solo la autorización en el lado del servidor puede detenerlos.
  • Un Access-Control-Allow-Origin: * permisivo combinado con credenciales no está permitido, y reflejar orígenes arbitrarios es peligroso.

Configura CORS explícitamente para los orígenes en los que confíes, y mantén la autenticación y autorización en el servidor.

Autenticación segura

La autenticación es el área donde los errores resultan más costosos.

  • Hashea las contraseñas con bcrypt, scrypt o Argon2; nunca uses texto plano ni cifrado reversible.
  • Utiliza cookies HttpOnly, Secure y SameSite para las sesiones, de modo que JavaScript no pueda leer el token.
  • Prioriza los tokens de corta duración con refresh y rotalos periódicamente.
  • Añade autenticación de múltiples factores para cuentas sensibles.
  • Implementa rate-limit en el login y bloquea el acceso tras fallos repetidos.
  • Nunca pongas secretos en el código del cliente: cualquier cosa que se envíe al navegador es pública.

La comparación anterior muestra el balance entre el uso de cookies frente a localStorage. Los tokens localStorage son convenientes pero pueden ser leídos por cualquier script, por lo que un solo XSS puede robar la sesión. Las cookies HttpOnly eliminan ese riesgo.

Otros aspectos esenciales

  • HTTPS en todas partes, con HSTS para prevenir ataques de degradación (downgrade attacks).
  • Valida y codifica la entrada en el servidor para cada campo.
  • Aplica el principio de menor privilegio a los usuarios de la base de datos, API keys y roles de la nube.
  • Configura cabeceras de seguridad: CSP, HSTS, X-Content-Type-Options: nosniff, Referrer-Policy y frame-ancestors.
  • Mantén las dependencias actualizadas y audítalas regularmente.
  • No reveles detalles en los mensajes de error o stack traces en producción.
  • Registra y monitorea los eventos de autenticación y los fallos de permisos.

Mejores prácticas

  • Trata todas las entradas del cliente como no confiables y valídalas en el servidor.
  • Codifica la salida según su contexto; utiliza textContent y sanitiza cualquier HTML.
  • Usa consultas parametrizadas para todo acceso a la base de datos.
  • Almacena las sesiones en cookies HttpOnly, Secure y SameSite.
  • Añade una Content Security Policy y comienza con el modo report-only.
  • Usa SameSite junto con tokens anti-CSRF para solicitudes que modifiquen el estado.
  • Mantén los secretos en el servidor y rotalos periódicamente.

Errores comunes

  • Usar innerHTML con datos de usuario.
  • Colocar tokens de sesión en localStorage.
  • Confiar en la validación del lado del cliente o en campos ocultos de formularios.
  • Construir SQL mediante concatenación de strings.
  • Asumir que CORS es un mecanismo de control de acceso.
  • Incluir API keys en el código del front-end.

Próximos pasos

La seguridad es una práctica, no una lista de tareas que se termina. Fundaméntala en el protocolo HTTP, aplícala en el servidor Node.js y gestiona los secretos de forma segura al desplegar con Docker. Lee el OWASP Top 10 y luego audita de principio a fin un formulario de tu propia aplicación; casi siempre encontrarás algo que valga la pena corregir.

Renderizado de contenido de usuario

textContent trata la entrada como texto. innerHTML la analiza como marcado, lo que convierte cualquier entrada de usuario en una potencial inyección de scripts.

Preferir
const el = document.createElement("p");
el.textContent = comment;
// <b>hi</b> renders literally
Evitar
el.innerHTML = comment;
// <img src=x onerror=alert(1)>
// executes

Almacenamiento de tokens de sesión

Una cookie HttpOnly, Secure y SameSite no es legible por JavaScript, por lo que un bug de XSS no puede robar la sesión.

Preferir
res.cookie("session", token, {
  httpOnly: true,
  secure: true,
  sameSite: "lax",
  maxAge: 1000 * 60 * 60,
});
Evitar
localStorage.setItem("token", token);
// readable by any script,
// stolen by any XSS

Preguntas frecuentes

Preguntas frecuentes

Keep learning

Related topics from the roadmap.

$ comienza a aprender

Listo para aprender Web Security?

Nuestro tutorial interactivo te guia a traves de Web Security paso a paso — con quizzes y codigo real que puedes ejecutar en el navegador.