Gabriel Neuman
Gabriel Neuman
💡 Aprendizaje13 de mayo de 2026·gabrielneuman.com·Gabriel Neuman

Lo que el vibe coding te deja sin revisar

Hicimos un análisis de vulnerabilidades completo del sitio y parcheamos los problemas reales. Lo que aprendí sobre seguridad en proyectos vibe-coded.

💡 Aprendizaje clave

El vibe coding entrega rápido pero acumula deuda de seguridad invisible — un audit de 2 horas la paga entera.

#seguridad#next-js#claude-code#vibe-coding#owasp

Resumen del día

Hoy no hubo features nuevas. Hubo algo más útil: revisamos todo el sitio con ojos de atacante. Partimos de un reporte de ciberseguridad externo, lo validamos contra el código real, y parcheamos lo que tenía riesgo concreto. Total: 8 archivos modificados, cero funcionalidad rota.


El problema con el vibe coding y la seguridad

Cuando construyes rápido con IA, el código funciona. Las features aparecen. Los tests pasan. Pero hay una categoría de problemas que el vibe coding sistemáticamente ignora: los que no rompen nada hoy pero te pueden quemar mañana.

LO QUE EL VIBE CODING OPTIMIZA
✓ Velocidad de entrega
✓ Funcionalidad visible
✓ UX y diseño
✓ SEO y conversión
✗ Superficie de ataque
✗ Validación de inputs
✗ Aislamiento de terceros
✗ Sanitización de HTML
LO QUE UN AUDIT DE 2H CUBRE
✓ iframes sin sandbox
✓ dangerouslySetInnerHTML sin sanitizar
✓ Validación inconsistente en APIs
✓ Params de URL sin re-validar
✓ Headers de seguridad
✓ Exposición de keys
✓ Dependencias vulnerables
✓ Auth en rutas protegidas

La trampa es que nada de esto falla en desarrollo. Un iframe sin sandbox muestra los testimonios igual. Un dangerouslySetInnerHTML sin sanitizar renderiza el markdown igual. El form sin Zod acepta datos igual. Solo falla cuando alguien malo llega con inputs maliciosos.


Qué hicimos hoy

Paso 1: Analizar el reporte vs. el código real

El reporte externo tenía 5 hallazgos. Al validarlos contra el código, 3 eran falsos positivos:

Hallazgo del reporte ¿Existe? Por qué no
Google Maps API key expuesta ❌ No Esa key no existe en el proyecto
Sin CSP configurada ❌ No Hay CSP completa en next.config.ts
Next.js desactualizado ❌ No 15.5.12, versión actual

Lección: Los reportes automáticos generan ruido. Siempre validar contra el código antes de actuar.

Los 2 hallazgos reales:

  • iframes de SocialJuice sin sandbox — 5 instancias en el sitio
  • dangerouslySetInnerHTML en SlideRenderer sin sanitizar — datos de presentaciones inyectados directo al DOM

Paso 2: Priorizar sin paranoia

No todo lo que suena a vulnerabilidad vale el esfuerzo. El criterio que usé:

ESFUERZO DEL FIX → RIESGO REAL → HACER YA PLANEAR SI HAY TIEMPO NO TOCAR iframes sandbox Zod en /lead sanitizeHTML slides Rate limit → Redis CSP sin unsafe-inline Tipar @ts-expect-error

Paso 3: Los fixes

iframes de SocialJuice (5 archivos) — agregué sandbox y referrerPolicy:

<!-- Antes -->
<iframe src="https://embed.socialjuice.io/..." allowFullScreen />

<!-- Después -->
<iframe
  src="https://embed.socialjuice.io/..."
  allowFullScreen
  sandbox="allow-scripts allow-popups allow-forms allow-same-origin"
  referrerPolicy="no-referrer"
/>

Si SocialJuice es comprometido, el sandbox limita lo que puede hacer dentro del iframe. Sin él, un script malicioso en embed.socialjuice.io corre con acceso completo al DOM de gabrielneuman.com.

SlideRendererrenderBody() y renderHeading() ahora pasan por sanitizeMarkdownHtml() antes del dangerouslySetInnerHTML. La función ya existía en el proyecto, nadie la había conectado acá.

/api/p/[id]/lead — reemplazado el .trim() manual por schema Zod completo con tipos, longitudes máximas y validación de email. Más limpio y más seguro.

/api/cms/crm/contacts/[email] — una línea de Zod después del decodeURIComponent para rechazar cualquier string que no sea email válido antes de que llegue a MongoDB.


El proceso que funcionó

FLUJO DE AUDIT PARA PROYECTOS VIBE-CODED
1
Tomar el reporte externo → validar cada hallazgo contra el código real antes de actuar
2
Separar falsos positivos de hallazgos reales → no gastar tiempo en lo que no existe
3
Priorizar por riesgo real × esfuerzo → no por lo que suena más dramático
4
Un fix a la vez, verificar que nada se rompe → no hacer refactor masivo
5
Documentar lo que queda pendiente → el deuda técnica que vale pagar después vs. nunca

Aprendizaje clave

El vibe coding no es inseguro por naturaleza — es inseguro por omisión. Cuando le pides a la IA "hazme un form que guarde leads en MongoDB", lo hace. Pero no te va a preguntar "¿quieres validación Zod o solo .trim()?" a menos que se lo pidas.

La deuda de seguridad del vibe coding se acumula en silencio. Un audit cada 3-4 meses cubre esa brecha. No necesitas ser experto en OWASP — necesitas un checklist y tiempo para leer el código con ojos críticos.

Lo que más me llamó la atención hoy: sanitizeMarkdownHtml ya existía en el proyecto. Alguien (yo, hace meses) la escribió conscientemente. Pero SlideRenderer nunca la usó. El código seguro existía — nadie lo conectó.

La herramienta de seguridad más subutilizada siempre es la que ya tienes.


Pendientes

  • Migrar rate limiter a Upstash Redis cuando el tráfico justifique (hoy no urgente)
  • Hacer audit similar en Naira landing — mismo patrón de iframes y forms
  • Commit y deploy de los 8 archivos modificados hoy