21 nov 2025·8 min de lectura

CSRF y XSS en apps web generadas por IA: arregla patrones rápido

CSRF y XSS aparecen a menudo en apps web generadas por IA cuando el código de UI se crea automáticamente. Aprende patrones vulnerables y una checklist para parchear agujeros sin reescribir pantallas.

CSRF y XSS en apps web generadas por IA: arregla patrones rápido

Por qué aparecen CSRF y XSS en apps construidas por IA

CSRF y XSS aparecen con frecuencia en apps web creadas por IA por una razón simple: muchos prototipos se construyen para verse bien y funcionar en una demo, no para aguantar tráfico real. Una página de login que “funciona localmente” puede seguir siendo insegura una vez desplegada, compartida y usada por personas que no eres tú.

Lo que “funciona localmente” oculta es la brecha entre un entorno privado de desarrollo y una aplicación en vivo. En local rara vez tratas con cookies reales entre pestañas, contenido de terceros, texto generado por usuarios a escala o extensiones del navegador que alteran el comportamiento de las páginas. En producción, esas cosas aparecen rápido, y un punto inseguro puede convertirse en una puerta de entrada a muchas páginas.

Los prototipos generados por IA también tienden a saltarse lo básico de seguridad porque los prompts se centran en las características. El modelo suele elegir la ruta más corta: renderizar contenido de usuario directamente, guardar tokens en lugares inseguros o enviar peticiones que cambian estado sin protección sólida. En una demo se ve bien, pero deja vacíos como tokens CSRF faltantes o HTML inyectado en la página.

Pequeños patrones pueden tener un gran radio de impacto. Un componente que usa dangerouslySetInnerHTML para renderizar “notas formateadas” puede convertir la entrada de un usuario en un script que se ejecute para todos los visitantes. Un botón “Eliminar” que llama a una API sin chequear CSRF puede permitir que un atacante dispare acciones usando la sesión iniciada de una víctima.

“Sin reescribir la UI” es realista, con límites. Usualmente no necesitas rediseñar pantallas ni reconstruir componentes desde cero. Añades protección bajo la superficie: defaults de render seguro, wrappers consistentes para peticiones y cheques en el servidor que rechacen solicitudes inseguras. La UI puede verse idéntica mientras la app se vuelve mucho más difícil de abusar.

Si heredaste una base de código generada por IA y ves estos patrones, un primer movimiento práctico es una auditoría rápida para encontrar los pocos huecos de alto impacto que vuelven todo lo demás riesgoso, y luego parchearlos sin cambiar cómo se ve la app. FixMyMess típicamente empieza justo ahí: diagnóstico del código primero, luego reparaciones dirigidas.

CSRF vs XSS en lenguaje llano

CSRF y XSS se confunden porque ambos pueden llevar a “alguien hizo algo en mi app que yo no esperaba”. La diferencia está en dónde ocurre el control del atacante.

CSRF (Cross-Site Request Forgery) en una frase: engaña al navegador de un usuario autenticado para que envíe una petición real que tu servidor aceptará.

XSS (Cross-Site Scripting) en una frase: permite que código controlado por el atacante se ejecute dentro de tu sitio en el navegador del usuario.

Una forma rápida de recordarlo: CSRF abusa del login del usuario (usualmente cookies). XSS abusa de tu página.

Cómo se encadenan

Son malos por separado, pero peores juntos. Una cadena común se ve así:

  1. Un bug XSS se ejecuta en tu app y lee algo sensible (como un token CSRF en la página o un JWT en localStorage).
  2. El atacante usa ese secreto para enviar peticiones autenticadas que parecen legítimas.
  3. Esas peticiones realizan acciones (cambiar email, añadir un admin, transferir créditos) sin que el usuario lo note.

Por eso el “añadiremos CSRF después” a menudo falla si ya existe un hueco XSS.

Señales simples de que podrías tener cada problema

Si usas autenticación basada en cookies, el riesgo CSRF es probable cuando acciones importantes funcionan con un solo POST y sin un token por petición, o cuando tu API acepta peticiones sin chequear el header Origin o Referer. El riesgo también aumenta con sesiones de larga duración (“recordarme”) y apps que confían en “es un dashboard privado” como protección.

El riesgo XSS es probable cuando renderizas contenido de usuario con dangerouslySetInnerHTML (o similar), insertas HTML crudo desde un editor WYSIWYG o Markdown sin sanitizar, construyes strings HTML y los pones con innerHTML, o reflejas la entrada del usuario en la página (comentarios, nombres, términos de búsqueda).

Si heredaste un prototipo generado por IA, estos dos problemas aparecen mucho en builds rápidos. El camino más rápido es confirmar cuál riesgo es real en tu app y luego parchearlo sin cambiar el layout de la UI.

Patrones vulnerables de XSS para buscar primero

XSS suele colarse cuando una UI construida por IA toma un atajo para “verse bien” y termina tratando texto como HTML. Empieza por encontrar cada lugar donde la app convierte contenido controlado por el usuario en marcado.

Las señales más rápidas

El código generado frecuentemente incluye unos atajos de alto impacto:

  • dangerouslySetInnerHTML usado para formato rápido, resaltados o insertar snippets ricos.
  • Contenido de usuario renderizado como HTML (comentarios, biografías, tickets de soporte, vistas previas de markdown).
  • HTML construido por concatenación de strings (template strings que contienen <div> / <a> / <img>).
  • Datos no confiables colocados en atributos (especialmente href, src, style o data-*) o manejadores de eventos inline como onclick="...".
  • Helpers de “sanitización” copiados que solo eliminan algunas etiquetas, usan regex, o solo escapan < y >.

Un fallo realista: un dashboard muestra un campo “Release notes” sacado de la base de datos. Alguien pega <img src=x onerror=alert(1)> y de repente cada admin que abra la página ejecuta ese código. También puede robar tokens de sesión, cambiar texto de la UI o enviar acciones en silencio.

Qué buscar en el código

Usa búsquedas simples primero. El objetivo es inventariar, no arreglar aún.

- dangerouslySetInnerHTML
- innerHTML =
- insertAdjacentHTML
- onClick="  onerror="  onload="
- href={user
- `<div`  `</` (dentro de template strings)

Si heredaste un prototipo de herramientas como v0, Replit o Cursor, estos atajos aparecen mucho. Trata cualquier función de sanitización casera como sospechosa hasta que se demuestre lo contrario. FixMyMess suele ver “sanitizadores” que fallan con payloads en SVG, atributos de evento o URLs javascript:.

Patrones vulnerables de CSRF para buscar primero

CSRF aparece cuando tu app confía demasiado en una cookie del navegador. Muchos prototipos generados por IA “simplemente funcionan” en dev porque siempre estás autenticado, pero el mismo diseño se vuelve riesgoso en producción.

Empieza buscando cualquier petición que cambie datos pero que no pruebe que el usuario realmente quiso hacerlo. La forma más rápida es mirar rutas del servidor y llamadas API del frontend lado a lado.

Patrones de alto riesgo a revisar hoy

Los patrones comunes de CSRF incluyen:

  • Peticiones POST/PUT/DELETE que confían en una cookie de sesión pero no envían un token CSRF (o no lo validan en el servidor).
  • Cookies de autenticación sin una política SameSite clara (o SameSite=None sin una razón fuerte).
  • Endpoints GET que cambian estado (por ejemplo: /api/deleteUser?id=123 o /api/toggle?id=...).
  • Pensar “habilitamos CORS, así estamos seguros”. CORS controla qué sitios pueden leer respuestas, no qué sitios pueden enviar una petición.
  • Múltiples subdominios que comparten cookies de forma confusa, especialmente cuando el dominio de la cookie es demasiado amplio.

Un ejemplo rápido: un dashboard de prototipo tiene un botón que llama GET /api/approveInvoice?id=42. Si un atacante logra que un admin cargue una página que dispara esa URL, el navegador podría enviar la cookie de admin automáticamente.

Trampas con cookies y subdominios

Si tu app usa app.example.com y api.example.com, sé explícito con el scope de las cookies y qué puede enviar peticiones autenticadas. Dominios de cookie amplios más cheques CSRF faltantes son una trampa común de “funcionó en local”.

Si quieres una auditoría rápida, FixMyMess puede señalar estos patrones CSRF rápidamente (incluyendo problemas de scope de cookie) antes de tocar la UI.

Parchear CSRF sin cambiar el layout de la UI

Repara una app construida por IA
Desde v0, Cursor, Replit, Lovable o Bolt: arreglamos código generado por IA que no puede salir a producción.

La mayoría de arreglos CSRF viven en cookies, headers y middleware del servidor. Por eso normalmente puedes asegurar CSRF sin rediseñar una sola página.

Elige una estrategia CSRF

Dos enfoques comunes funcionan bien con frontends generados por IA:

  • Token sincronizador: el servidor crea un token, lo guarda en la sesión y lo exige en cada petición que cambie estado.
  • Doble envío de cookie: el servidor pone una cookie CSRF y exige el mismo valor en un header (o en el body). No se necesita sesión en el servidor.

Si tu app ya usa cookies para auth, el doble envío de cookie más un header suele ser lo menos disruptivo. La UI permanece igual. Añades un header en tu cliente API.

Chequeos en el backend que no tocan la UI

Pon la aplicación de CSRF donde entran las peticiones al backend: middleware, una clase base de controladores o un guard request central. Haz que aplique a métodos inseguros (POST, PUT, PATCH, DELETE) y solo para tráfico autenticado por cookie del navegador.

Un patrón práctico es:

  • Poner una cookie CSRF en la carga inicial de la página o después del login.
  • Exigir X-CSRF-Token en peticiones inseguras.
  • Comparar el token del header con el token de la cookie (rechazar si falta o no coinciden).
  • Omitir cheques CSRF para endpoints que usan Authorization headers (API keys, bearer tokens) en lugar de cookies.
  • Loguear rechazos con ruta y origen para detectar rupturas accidentales rápido.

Confirma también las configuraciones de cookie mientras estás allí. Usa SameSite=Lax por defecto, Secure en producción (HTTPS) y HttpOnly para cookies de auth. Para cookies CSRF específicamente, puede que necesites HttpOnly=false si el navegador debe leerla para copiarla en un header.

Si tienes APIs usadas por código de navegador y por código servidor (SSR, cron jobs, webhooks), sepáralas: rutas basadas en cookie obtienen cheques CSRF; rutas basadas en token no. Los equipos suelen pedir a FixMyMess que haga esta separación claramente cuando un prototipo generado por IA empieza a fallar en producción.

Parchear XSS sin cambiar el layout de la UI

Arreglar XSS no tiene por qué significar un rediseño. La mayoría de las veces puedes mantener los mismos componentes y rutas y solo cambiar cómo se renderizan texto y HTML. Esto es común en apps construidas por IA: la UI se ve bien, pero los defaults de render son inseguros.

Haz que “solo texto” sea el default

Trata cada string como no confiable, incluso si vino de tu propia base de datos. Comentarios, nombres de perfil, “notas”, mensajes de soporte y cualquier cosa producida por un LLM puede llevar HTML oculto.

Concéntrate en unos pocos patrones que cierran la mayoría de las brechas:

  • Elimina o limita estrictamente dangerouslySetInnerHTML (y APIs similares en otros frameworks).
  • Renderiza contenido de usuario como texto plano por defecto (sin interpretación HTML).
  • Si debes permitir rich text, sanitízalo con una librería reconocida y una allowlist pequeña.
  • Centraliza la codificación de salida en un solo lugar (un helper/componente) para que las correcciones apliquen en todas partes.
  • Trata el Markdown también como no confiable (Markdown puede producir HTML según el parser).

Si realmente necesitas HTML (por ejemplo, un editor de “release notes”), sanitiza justo antes de renderizar y permite solo un conjunto pequeño de etiquetas (como b, i, em, strong, a). Evita manejadores de evento inline, estilos inline y atributos desconocidos.

// Example pattern (React): sanitize before using dangerouslySetInnerHTML
const safeHtml = sanitize(userProvidedHtml, { allowTags: ['b','i','em','strong','a'] });
return <div dangerouslySetInnerHTML={{ __html: safeHtml }} />;

Añade una CSP como red de seguridad

Una Content Security Policy (CSP) no arreglará un mal render, pero puede limitar el daño si algo se cuela.

Empieza simple y prueba tu app, aflojando solo lo necesario:

  • Bloquea scripts inline cuando sea posible.
  • Permite scripts solo desde tu propio dominio.
  • Prohíbe URLs javascript: en enlaces.
  • Evita unsafe-eval a menos que no tengas opción.

Si heredaste un prototipo generado por IA y no sabes de dónde viene el HTML inseguro, un buen flujo es encontrar cada ruta de render arriesgada, reemplazarla por defaults seguros y luego añadir CSP para atrapar lo que quede.

Hardening paso a paso en menos de un día

Puedes cerrar la mayoría de huecos CSRF y XSS sin tocar el layout. El truco es trabajar primero como tester y luego parchear la superficie más pequeña.

Empieza mapeando cómo se mueve la data. Haz un inventario rápido de dónde entra la data (formularios, query params, cookies, webhooks, campos rich text) y dónde se muestra al usuario (tablas, toasts, páginas de perfil, paneles de admin). Esto suele revelar rutas “ocultas” como una página de settings interna que nunca se revisó.

Luego haz visibles tus arreglos. Activa logs en el servidor para fallos CSRF (tokens rechazados, cheques de origin faltantes). Para XSS, añade una señal clara cuando la sanitización remueve contenido. Si un usuario reporta “mi texto desapareció”, quieres ver qué se eliminó y por qué.

Un plan de parches rápido

  • Añade protección CSRF a cada ruta que cambie estado (POST, PUT, PATCH, DELETE) usando middleware compartido, y confirma que las cookies tengan defaults sensatos (HttpOnly, Secure, SameSite).
  • Estandariza cómo el cliente envía el token (header o campo oculto) para no arreglarlo de cinco maneras distintas.
  • Busca dangerouslySetInnerHTML y patrones similares. Elimínalos cuando puedas, o aíslos en un componente único que siempre sanitice.
  • Sanitiza HTML no confiable en un único límite (justo antes de renderizar, o al guardar). Elige uno, documéntalo y mantén la consistencia.
  • Añade una CSP básica y recorre tus flujos principales para atrapar scripts inline accidentales.

Después, prueba como un usuario normal: regístrate, inicia sesión, actualiza un perfil, envía un formulario y usa acciones de admin. Intenta las mismas acciones en un segundo navegador donde no estés autenticado. Si algo falla, los logs deberían decir si fue la protección CSRF o la sanitización.

Si heredaste una base de código generada por IA, FixMyMess puede correr una auditoría rápida y aplicar estos parches con verificación humana experta, de modo que obtengas mejoras de seguridad sin una reescritura completa.

Ejemplo: dashboard de prototipo que falla en producción

Arregla la autenticación basada en cookies de forma segura
Arreglamos flujos de autenticación rotos, cookies inseguras y cheques CSRF faltantes en un sprint de remediación.

Una configuración común es un “admin dashboard” más un cuadro de comentarios público. La UI se ve bien: los admins pueden aprobar usuarios, emitir reembolsos y cambiar precios. Los visitantes pueden dejar feedback que aparece en el feed del dashboard.

El XSS se cuela cuando los comentarios se renderizan como HTML. Un patrón típico es un componente React que usa dangerouslySetInnerHTML para que saltos de línea y enlaces “simplemente funcionen”. Si un visitante escribe algo que se convierte en código script, puede ejecutarse dentro del navegador del admin cuando este abra el dashboard.

El CSRF aparece cuando las acciones de admin confían solo en cookies para auth. Los botones llaman endpoints como /api/admin/refund, y el servidor asume que “cookie presente” significa “el admin aprobó esta acción”. Si un admin está autenticado y visita una página maliciosa en otra pestaña, esa página puede enviar un formulario oculto o una petición a tu app y el navegador adjuntará la cookie del admin.

Un camino de ataque realista: el atacante publica un “comentario” que se ejecuta en la sesión del admin y luego desencadena peticiones que cambian estado contra endpoints sin CSRF. No es magia, es el navegador haciendo lo que siempre hace.

Arreglos mínimos que mantienen las mismas pantallas y UX:

  • Deja de renderizar HTML crudo de los comentarios. Renderiza texto por defecto, o sanitiza y permite solo un conjunto pequeño y seguro (negrita, cursiva, enlaces).
  • Añade protección CSRF a cada petición que cambie estado y exígela en POST/PUT/PATCH/DELETE.
  • Ajusta las cookies de sesión a SameSite=Lax (o Strict donde sea posible) y HttpOnly.
  • Requiere cheques de Origin o Referer para acciones de admin sensibles como respaldo.

Los equipos suelen traer este dashboard exacto a FixMyMess cuando “funciona localmente” pero falla en una revisión de seguridad real. La buena noticia es que normalmente puedes parchearlo sin cambiar la UI.

Errores comunes y falsos arreglos

Muchos parches rápidos parecen “seguros” porque silencian una alerta o detienen un exploit obvio. El problema real suele ser que el mismo patrón inseguro existe en dos o tres lugares que no revisaste.

Una trampa común es escapar la entrada una vez (quizá en el handler del formulario) y luego renderizar la misma data por otro camino que omite el escape. Ejemplo: un campo “notas” se escapa al guardar, pero un panel de vista previa usa dangerouslySetInnerHTML para formato y vuelve a introducir ejecución de scripts.

Otro falso arreglo es sanitizar solo en el navegador y confiar en el resultado en el servidor. Los atacantes no usan tu UI. Envian peticiones directamente, así que el servidor debe validar y la app debe codificar la salida sin confiar en el cliente.

La gente también asume que JSON es “seguro”. No lo es. Si tomas campos JSON y los inyectas en HTML (templates, tooltips, toasts, componentes rich text), aún puedes tener XSS. El formato de respuesta no es protección; cómo lo renderizas sí.

Los widgets de terceros suelen olvidarse. Chats, snippets de analytics, editores markdown y componentes embed pueden inyectar HTML o scripts. Incluso si tu código está limpio, una configuración insegura de un widget puede deshacer tu trabajo.

Para CSRF, un error frecuente es proteger un endpoint y dejar otro que también cambia estado abierto. La UI puede llamar /settings/update, pero también existe /settings/save o /api/admin/promote que aún acepta cookies sin chequear tokens CSRF.

Chequeos rápidos de realidad que detectan la mayoría de apps “arregladas pero aún vulnerables”:

  • Busca cada ruta de render de contenido de usuario, no solo el formulario que lo recoge.
  • Fuerza validación server-side y codificación de salida, incluso si el cliente sanitiza.
  • Revisa rutas que cambian estado (POST, PUT, PATCH, DELETE) y confirma que todas requieren protección CSRF.
  • Inventaría scripts y componentes de terceros y revisa cómo inyectan contenido.

Los equipos a menudo traen un prototipo a FixMyMess que “funciona” en demos pero falla estos chequeos en producción. Las victorias más rápidas suelen venir de cerrar las rutas de render adicionales y los endpoints olvidados, no de reescribir la UI.

Checklist rápida antes de lanzar

Comienza con una auditoría gratis
Obtén una auditoría de código gratuita para encontrar los huecos de CSRF y XSS que oculta tu prototipo.

Antes de exponer un prototipo generado por IA a usuarios reales, haz una pasada centrada en dos escapes comunes: cambios de estado sin protección CSRF y contenido no confiable que puede convertirse en script.

  • Protege cada ruta que cambie estado (POST/PUT/PATCH/DELETE). Exige un token CSRF (o defensa equivalente) y rechaza peticiones que lo carezcan.
  • Asegura las cookies: pon Secure y HttpOnly cuando sea posible, y elige un valor SameSite que coincida con tus flujos (cuidado con redirecciones de terceros y apps embebidas).
  • No renderices HTML no confiable a menos que pase por un sanitizador con allowlist. Si no necesitas HTML, renderiza texto plano.
  • Añade una CSP y prueba tus páginas principales con ella activada. Una política que bloquee scripts inline atrapa muchos caminos accidentales de XSS.
  • Vuelve a probar registro, login, reseteo de contraseña y logout tras los cambios. Los arreglos de seguridad a menudo rompen auth en maneras pequeñas (tokens no enviados, cookies no puestas, redirecciones en loop).

Luego ejecuta un pequeño conjunto de tests pre-despliegue:

  • Prueba la app en una ventana privada y confirma que las cookies se comportan como esperas tras el login.
  • Envía una petición que cambie estado sin token CSRF y confirma que falla.
  • Pega una sonda XSS inocua (como <img src=x onerror=alert(1)>) en cualquier campo que luego aparezca en una página; confirma que se renderiza como texto y no se ejecuta.
  • Abre páginas clave con CSP activada y confirma que nada esencial se rompe (botones, modales, envíos de formularios).

Si heredaste una base de código generada por IA y estas comprobaciones destapan un lío de casos borde, FixMyMess puede auditar y parchear las partes riesgosas rápidamente sin forzar una reescritura de UI.

Siguientes pasos si heredaste una base de código generada por IA

Empieza por decidir si necesitas parches rápidos o un sprint corto de limpieza. Si la app es pequeña, tiene un login simple y solo unos pocos formularios, a menudo puedes cerrar los mayores huecos CSRF y XSS sin tocar la UI. Si el código tiene lógica de autenticación copiada y pegada, muchas llamadas fetch duplicadas y renderizado HTML por todas partes, parchear puede convertirse en un juego de whack-a-mole.

Los parches rápidos suelen bastar cuando tienes pocas acciones de escritura y todas pasan por un wrapper cliente, el texto generado por usuarios se muestra en unos pocos componentes evidentes y las sesiones/cookies se comportan consistentemente en la app.

Planifica una limpieza cuando veas llamadas fetch duplicadas, propiedad poco clara de cookies/tokens o endpoints admin “temporales” que se lanzaron en producción.

Para obtener una revisión rápida y útil, entrega al revisor un mapa simple de lo que existe hoy. El objetivo es encontrar los puntos calientes donde se ocultan estos problemas, no criticar tu UI.

Aquí hay lo que preparar (incluso un doc aproximado sirve):

  • Una lista de cada endpoint que cambia datos (método + ruta + quién puede llamarlo)
  • Cómo funciona la auth (cookies vs headers, dónde se crea la sesión, comportamiento de logout)
  • Dónde se renderiza o inyecta HTML (helpers de render, markdown, rich text, previsualizaciones de email)
  • Cualquier embeds de terceros o entradas de contenido de usuario (comentarios, campos de perfil, uploads)
  • Dónde viven secretos (archivos env, bundle cliente, logs de CI)

Una auditoría corta suele detectar patrones riesgosos rápido: cheques CSRF faltantes en sesiones basadas en cookie, renderizado HTML inseguro y lugares donde datos no confiables llegan al DOM.

Si la app ya está fallando en producción, considera un sprint de remediación dirigido: arregla las vulnerabilidades top, añade guardrails (tokens, sanitización, defaults seguros) y luego refactoriza solo los peores ofensores.

Si quieres una segunda opinión, FixMyMess (fixmymess.ai) se especializa en arreglar bases de código generadas por IA desde herramientas como Lovable, Bolt, v0, Cursor y Replit, incluyendo problemas como flujos de auth rotos, secretos expuestos, CSRF/XSS y endurecimiento de seguridad, manteniendo la UI intacta.