“Renovar el escaparate pero dejar la vieja puerta trasera sin cerrar, y fuera del plano.”
Los endpoints que olvidaste haber publicado
Cambiar la UI no borra la API que hay detrás. Quitas un botón, la pantalla queda limpia, y la ruta a la que llamaba ese botón sigue viva y sigue respondiendo. A lo largo de las iteraciones, una app construida con IA los acumula: versiones antiguas de endpoints, rutas de debug y de prueba añadidas "solo para comprobar algo", acciones de admin que nunca se protegieron. Son invisibles en la app y totalmente alcanzables por cualquiera que conozca, o adivine, la URL.
El cambio mental: tu frontera de seguridad es el conjunto de rutas a las que tu servidor responderá, no el conjunto de enlaces de tu interfaz. Un atacante lee tu bundle de JavaScript para enumerar las rutas, ignora tu UI por completo y las llama directamente. Quitado-de-la-pantalla no es quitado-del-servidor.
Webhooks: cualquiera puede hacer ese POST
Un webhook es una URL pública en tu servidor a la que llama un proveedor (Stripe, GitHub, un servicio de correo) para avisarte de que algo ocurrió. El truco: la URL es pública, así que cualquiera puede llamarla, incluido un atacante enviando un "pago completado" o "suscripción mejorada" falsificados para desbloquear funciones de pago gratis. El proveedor firma cada llamada real con un secreto compartido; si no verificas esa firma, estás confiando en las afirmaciones de desconocidos sobre tu propio negocio.
// Verify the signature BEFORE trusting anything in the payload.
const sig = req.headers.get("stripe-signature");
let event;
try {
event = stripe.webhooks.constructEvent(rawBody, sig, process.env.STRIPE_WEBHOOK_SECRET);
} catch {
return new Response("bad signature", { status: 400 }); // forged or tampered
}
// Only now is it safe to act on event.typeCORS y límites de peticiones
Dos ajustes que las herramientas de IA hacen mal porque la versión permisiva hace desaparecer los errores. CORS controla qué scripts de otros sitios web pueden llamar a tu API desde un navegador; una herramienta atascada en un error cross-origin a menudo lo configurará para permitirlo todo, lo que, combinado con credenciales, puede permitir que cualquier sitio actúe como tu usuario. Restríngelo a tus propios orígenes. Y el rate limiting: sin él, el login y el registro quedan abiertos a fuerza bruta, los endpoints caros quedan abiertos a abusos que disparan tu factura y tus datos quedan abiertos al scraping.
- CORS: permite solo tus orígenes reales, nunca '*' junto con credenciales.
- Limita por usuario y por IP, sobre todo en auth, registro, restablecimiento de contraseña y todo lo que cueste dinero ejecutar.
- Pon los endpoints caros o sensibles primero tras autenticación; el rate limiting es una red de seguridad, no la primera línea.
El inventario que necesitas
No puedes asegurar una superficie que no has cartografiado. Una vez, antes de lanzar, enuméralo:
- Lista todas las rutas que el servidor sirve de verdad, desde el código y el bundle, no desde el menú.
- Para cada una: ¿está pensada para ser pública? Si no, ¿autentica y autoriza (capítulo 4)?
- Borra las rutas muertas, de debug y de versiones antiguas; la superficie más pequeña es la más segura.
- Para cada webhook entrante, confirma la verificación de firma, y luego confirma que rechaza una llamada sin firmar.
Este inventario es también la entrada de la checklist de lanzamiento del próximo capítulo. No puedes marcar "todos los endpoints están autorizados" hasta que sepas cuáles son todos los endpoints.
Una línea por cada uno
- Tu superficie de ataque es cada ruta que responde el servidor, no cada enlace de la UI; quitado-de-la-pantalla no es quitado-del-servidor.
- Las URLs de webhook son públicas; sin verificación de firma, cualquiera puede falsificar eventos como 'pago completado'.
- CORS en '*' y la falta de rate limits son valores permisivos que las herramientas de IA usan para silenciar errores; ambos son agujeros.
- Inventaría cada endpoint antes de lanzar: ¿debe ser público, está autorizado, se pueden borrar las rutas muertas, están verificados los webhooks?
Adónde ir ahora