NullBreach | AI-Powered AppSec Chat
Ecosistema de NullBreach | AI-Powered AppSec Chat, un portafolio de seguridad de aplicaciones de código abierto y sin fines comerciales. Reúne la aplicación con chat y análisis de código orientado a OWASP, la página de presentación, el repositorio con licencia MIT y la documentación de la API.
Por Valentina Ramírez
Publicado: 16 de junio de 2026 · Actualizado: 5 de octubre de 2026
- Problema
- Un hallazgo de seguridad sirve poco si no dice qué tan grave es y cómo se corrige.
- Solución
- Se pega un fragmento de código y se recibe un análisis con severidad, impacto y remediación, o se pregunta en un chat de seguridad.
- Resultado
- En producción y de código abierto con licencia MIT.
01 App
Aplicación Next.js con chat de seguridad y análisis de código orientado a OWASP. Ver detalleOcultar
- Next.js
- React
- TypeScript
- Tailwind CSS
- NextAuth
- Prisma
- PostgreSQL
- OpenAI API
- Vercel
El problema
Un hallazgo de seguridad sirve poco si no dice qué tan grave es, qué impacto tiene y cómo se corrige. Y una duda puntual sobre un fragmento de código rara vez justifica montar y afinar un escáner de reglas.
Hallazgos sin remediación
Una lista de patrones no basta si no explica la severidad, el impacto y cómo corregir el riesgo.
Dudas que se pierden
Una consulta de seguridad resuelta hoy se vuelve a necesitar mañana, y sin historial hay que repetirla.
Una IA que se toma con criterio
La respuesta de un modelo puede equivocarse. Hay que presentarla como asistencia de análisis, no como el resultado de un escáner determinista.
Resultados
- Chat y análisis de código con la OpenAI Responses API, con límites de 4.000 y 20.000 caracteres aplicados antes de llamar al modelo.
- Preguntas, respuestas y análisis guardados por usuario en Prisma Postgres, con el historial del chat visible en pantalla.
- Código abierto con licencia MIT, referencia de API con Swagger UI y OpenAPI, y un endpoint de salud.
- Entrega con staging y producción separados, migraciones aplicadas en el despliegue y pruebas E2E contra lo desplegado.
Ver detalle técnico AbrirOcultar detalle técnico
Qué construí
- 01
Un repositorio con dos superficies: la landing pública, un sitio estático en Astro (apps/landing), y el producto autenticado en Next.js (App Router, React y TypeScript), con su frontend (app y components) y su backend (app/api, lib y prisma). Hay un único despliegue, que también sirve la salida estática de la landing.
- 02
Montada bajo wavival.dev/nullbreach con Vercel Microfrontends: el portafolio es la aplicación por defecto y NullBreach es un proyecto hijo independiente. Next.js reescribe el prefijo público y toda navegación y llamada a la API pasa por una función única de rutas (appPath).
- 03
Análisis y chat en el servidor: el cliente envía el texto a una ruta que exige sesión, valida que no esté vacío ni supere el límite (4.000 caracteres la pregunta, 20.000 el código, con 413 si lo supera) y solo entonces llama a la OpenAI Responses API. La clave de OpenAI y el modelo (variable de entorno) viven solo en el servidor y en un único módulo.
- 04
La instrucción del modelo pide consejo práctico basado en OWASP; la de análisis pide explicar severidad, impacto y remediación. La respuesta es texto libre, se muestra como texto plano y no como HTML, y se guarda junto con la pregunta o el código enviado.
- 05
Autenticación con NextAuth: credenciales (correo y clave con bcrypt, costo 12, de 8 a 128 caracteres) y Google OAuth opcional, con sesiones JWT en cookies HTTP-only. Una cuenta de Google se enlaza por correo normalizado.
- 06
Recuperación de clave: se genera un token aleatorio, se guarda solo su hash SHA-256 con una hora de vigencia y un solo uso, y el enlace sale por Brevo. La respuesta no revela si el correo existe.
- 07
Prisma ORM sobre Prisma Postgres con cuatro modelos: usuarios, historial de chat (pregunta, respuesta y modelo), análisis de código y tokens de recuperación. Borrar un usuario borra en cascada sus registros, y hay índices por usuario y fecha. El historial en pantalla muestra las diez últimas preguntas.
- 08
Autorización en dos capas: un proxy rechaza con 401 las rutas privadas de chat, análisis e historial antes de ejecutarlas, y cada ruta vuelve a comprobar la sesión. Cabeceras contra framing, sniffing de tipo, fuga de referrer y permisos del navegador innecesarios.
- 09
Documentación de la API en docs/api.md, con Swagger UI y un documento OpenAPI servidos por la propia aplicación, y un endpoint de salud que comprueba la base de datos sin llamar a OpenAI.
- 10
Entrega con compuertas: ramas de trabajo hacia dev, stg y main, un solo camino y siempre por PR. GitHub Actions construye, aplica migraciones, despliega, comprueba la salud y corre Playwright contra el despliegue. Staging y producción usan bases Prisma Postgres y secretos separados, y los despliegues automáticos de Git están desactivados.
- 11
CI en cada PR: lint, formato, tipos, validación de Prisma, pruebas con cobertura y build, además de commitlint, auditoría de dependencias de severidad alta y escaneo de secretos con gitleaks.
Análisis de código
Pega un fragmento y recibe hallazgos orientados a OWASP con severidad, impacto y remediación.
Chat de seguridad
Pregunta sobre vulnerabilidades, controles y desarrollo seguro, y recibe una respuesta práctica.
Historial
Las diez últimas preguntas del chat quedan a la vista, guardadas en tu cuenta.
Cuenta
Registro con correo y clave, ingreso con Google y recuperación de clave por correo.
Landing bilingüe
Página pública en español e inglés, indexable, con las rutas privadas fuera del índice.
API documentada
Referencia en docs/api.md, Swagger UI, documento OpenAPI y endpoint de salud.
Del fragmento al hallazgo
- 01 El usuario pega un fragmento de código en el analizador.
- 02 El proxy y la ruta comprueban la sesión, que el texto no esté vacío y que no supere 20.000 caracteres.
- 03 El servidor llama a la OpenAI Responses API con instrucciones para analizar el código según OWASP y explicar severidad, impacto y remediación.
- 04 La respuesta se guarda como análisis del usuario y se devuelve para mostrarla como texto.
Diseño
- 01
Interfaz de terminal: paneles con comandos de prompt como $ nullbreach scan ./src y tipografía monoespaciada.
- 02
Landing con un solo h1, encabezados ordenados, referencias de navegación, enlace para saltar al contenido y foco visible por teclado, con animaciones que respetan prefers-reduced-motion.
- 03
Rutas en español e inglés con canónica y alternates por idioma. El sitemap lista solo las dos landings, y el robots y los metadatos dejan fuera la API, el ingreso y el área privada.
- 04
Las respuestas del modelo se muestran como texto con saltos de línea y no como HTML, y los errores usan role alert con mensajes que no revelan detalles internos.
Decisiones de arquitectura
01 Dos superficies en un solo despliegue VerCerrar
- Contexto
- El producto necesita una landing pública e indexable, un frontend autenticado y un backend con base de datos y proveedor de IA.
- Trade-off
- Separarlos en despliegues distintos añade contratos y operación que un proyecto de una persona no necesita todavía. Con Astro para la landing y Next.js para el producto, cada superficie usa la herramienta que le conviene, pero hay que mantener sus rutas sincronizadas.
- Decisión
- La landing se construye con Astro y se publica como archivos estáticos dentro del despliegue de Next.js, que sirve las rutas exactas de la landing y deja el resto del prefijo al producto.
02 Montada bajo wavival.dev con Microfrontends VerCerrar
- Contexto
- La app debe vivir en el mismo dominio del portafolio sin atar su ciclo de despliegue al de él.
- Trade-off
- El prefijo /nullbreach obliga a mantener sincronizados microfrontends.json, los rewrites, el basePath de NextAuth y cada enlace y llamada a la API.
- Decisión
- Vercel Microfrontends enruta /nullbreach al proyecto independiente, y una función única de rutas (appPath) construye todas las URLs del navegador.
03 Un modelo de lenguaje como asistencia, en un solo módulo VerCerrar
- Contexto
- Revisar código a mano exige conocimiento de seguridad y tiempo para explicar impacto y corrección.
- Trade-off
- La respuesta es texto libre y puede equivocarse: no es la salida de un escáner y no reemplaza una revisión experta.
- Decisión
- Un único módulo de servidor llama a la OpenAI Responses API con instrucciones basadas en OWASP. La clave nunca llega al navegador y los límites de tamaño se aplican antes de la llamada y de guardar.
04 NextAuth con credenciales y Google VerCerrar
- Contexto
- Cada persona debe ver solo su propio historial y sus propios análisis.
- Trade-off
- Las sesiones JWT no guardan estado en el servidor, y enlazar Google por correo supone confiar en el correo verificado por Google.
- Decisión
- Credenciales con bcrypt y Google OAuth opcional, con sesión JWT en cookie HTTP-only. Los datos se consultan siempre por el identificador del usuario de la sesión.
05 Recuperación de clave con token de un solo uso VerCerrar
- Contexto
- Quien olvida la clave necesita recuperarla sin que la respuesta revele qué correos tienen cuenta.
- Trade-off
- Depende de un proveedor de correo externo, y sin él configurado el enlace solo se imprime en desarrollo.
- Decisión
- Token aleatorio de 32 bytes, solo su hash SHA-256 guardado, una hora de vigencia, un solo uso y la misma respuesta exista o no la cuenta.
06 Autorización en dos capas VerCerrar
- Contexto
- Las rutas de chat y análisis llaman a un proveedor de pago y escriben en la base de datos.
- Trade-off
- Comprobar la sesión dos veces duplica una línea en cada ruta, pero un cambio en el proxy no deja una ruta abierta.
- Decisión
- Un proxy responde 401 a las rutas privadas antes de ejecutarlas y cada ruta repite la comprobación.
07 Un solo camino de entrega, con compuertas VerCerrar
- Contexto
- Una aplicación con claves de IA y base de datos no debe llegar a producción sin pasar por staging.
- Trade-off
- Los PR de promoción y las comprobaciones desplegadas agregan pasos, y las bases de staging y producción se mantienen por separado.
- Decisión
- Ramas de trabajo hacia dev, stg y main siempre por PR. GitHub Actions construye, migra, despliega, comprueba la salud y corre Playwright. Los despliegues automáticos de Git están desactivados.
Aprendizajes
Un modelo de lenguaje que revisa código debe presentarse como asistencia de análisis y no como una verificación determinista.
Autenticar y limitar el tamaño antes de llamar a un proveedor de pago protege el costo y la base de datos al mismo tiempo.
Una landing estática en Astro puede viajar dentro del despliegue de la aplicación y conservar su propio SEO, sin pagar el costo de dos despliegues.
Roadmap
Ahora
- Aplicación en producción con chat de seguridad, análisis de código, cuentas y recuperación de clave.
Siguiente
- Mostrar los análisis guardados y permitir borrar el historial y la cuenta.
- Límite de frecuencia en el chat y en el análisis, que llaman a un proveedor de pago.
- Verificar el correo de las cuentas con clave antes de que Google pueda enlazarse a ellas.
02 Landing
Landing estática en Astro, indexable y en español e inglés. Ver detalleOcultar
- Astro
- TypeScript
- SEO
- Vercel
Ver detalle técnico AbrirOcultar detalle técnico
Qué construí
- 01
Sitio estático en Astro dentro del mismo repositorio (apps/landing), separado de la aplicación Next.js. Sirve las rutas públicas /nullbreach y /nullbreach/en.
- 02
Contenido: resumen del producto, límites técnicos, información de la autora y datos de contacto, en español e inglés.
- 03
SEO técnico propio: datos estructurados, URL canónicas, directivas de robots y sitemap generado con @astrojs/sitemap.
- 04
La salida estática de Astro se publica dentro del despliegue de Next.js, que sirve las rutas exactas de la landing (/nullbreach, /nullbreach/en, sitemap y robots) y deja /nullbreach/:path* para las rutas del producto.
- 05
La landing no contiene secretos de ejecución. El producto autenticado (inicio de sesión, chat, análisis e historial) no es indexable.