El cifrado del transporte: HTTPS/TLS
HTTPS es HTTP sobre TLS (Transport Layer Security). Cifra el tráfico entre cliente y servidor, garantiza integridad (nadie altera los datos en tránsito) y autenticidad (el certificado prueba que hablas con el servidor real, no con un atacante en medio). En producción, todo va por HTTPS: las contraseñas, los tokens de sesión y las cookies viajan en claro sin él.
Refuerza con la cabecera HSTS (Strict-Transport-Security), que obliga al
navegador a usar siempre HTTPS para tu dominio.
CORS: quién puede llamar a tu API
El navegador aplica la política del mismo origen (same-origin policy): por
defecto, una página de a.com no puede leer respuestas de una API en b.com.
CORS (Cross-Origin Resource Sharing) es el mecanismo por el que el servidor
autoriza explícitamente orígenes concretos con cabeceras como
Access-Control-Allow-Origin. No uses * con credenciales: lista solo los
orígenes de confianza.
CSP: Content Security Policy
La cabecera Content-Security-Policy declara de qué fuentes puede el
navegador cargar scripts, estilos e imágenes. Es la defensa más fuerte contra
XSS: aunque un atacante inyecte <script>, el navegador se niega a
ejecutarlo si no procede de una fuente permitida.
Content-Security-Policy: default-src 'self'; script-src 'self'
Cabeceras de seguridad: helmet
En Express, helmet es un middleware que fija de golpe un conjunto de
cabeceras de seguridad sensatas (CSP, HSTS, X-Content-Type-Options,
X-Frame-Options contra clickjacking, etc.):
const helmet = require("helmet");
app.use(helmet());
OWASP Top: los riesgos clásicos
El OWASP Top 10 lista los riesgos web más habituales. Tres imprescindibles:
Inyección SQL. Concatenar entradas del usuario dentro de una consulta deja ejecutar SQL arbitrario. La defensa es usar consultas parametrizadas (prepared statements): los datos viajan separados del texto SQL y nunca se interpretan como código.
// ❌ vulnerable: concatena la entrada db.query("SELECT * FROM users WHERE email = '" + email + "'"); // ✅ parametrizada: el driver escapa el valor db.query("SELECT * FROM users WHERE email = $1", [email]);XSS (Cross-Site Scripting). El atacante consigue que el navegador de la víctima ejecute su JavaScript inyectándolo en una página. Se previene escapando (convirtiendo a entidades HTML) cualquier dato del usuario antes de pintarlo, y reforzando con CSP.
CSRF (Cross-Site Request Forgery). Un sitio malicioso provoca que el navegador de la víctima, ya autenticada, envíe una petición a tu API aprovechando sus cookies. Se mitiga con tokens CSRF y cookies
SameSite.
Sanear y escapar entradas
Regla de oro: valida la entrada (rechaza lo que no encaja con lo esperado), sanea (elimina lo peligroso) y escapa al salir según el contexto (HTML, SQL, shell). Escapar al renderizar es lo que neutraliza el XSS.
Gestión de secretos y escaneo de dependencias
Las claves, contraseñas y tokens nunca se escriben en el código ni se suben
al repositorio: van en variables de entorno o en un gestor de secretos
(Vault, AWS Secrets Manager). Y como la mayor parte de tu código son
dependencias de terceros, escanéalas en busca de vulnerabilidades conocidas con
npm audit (y herramientas como Dependabot o Snyk) de forma continua.