v0.4.0 · guardarraíl + escáner

Tu agente estaba a punto de desactivar el RLS.

Los agujeros de las apps hechas con IA casi nunca empiezan como código malo. Empiezan como una petición que suena razonable — “desactiva el RLS para que funcione” — y el agente obedece, porque obedecer es su trabajo. vibeward lo caza en cuanto lo escribes, y audita lo que ya esté desplegado. Determinista, de solo lectura, MIT.

$ npx vibeward@latest init

sin llamadas a LLM100% localsin telemetríasin cuentaes · en · pt

Por qué existe

Tres fallos documentados en el mundo real — informes públicos de incidentes e investigación publicada, no mediciones propias de vibeward. Los tres se citan mal; lo que sigue es la versión que sobrevive a leer la fuente primaria.

10.3%
del escaparate Launched de Lovable tenía el Row-Level Security abierto de par en par — 170 de 1.645 proyectos. Un suelo, no una tasa: solo se escaneó la portada de cada sitio. Marzo 2025, por dos ingenieros de Replit.
Palmer y Low · CVE-2025-48757, disputado
29,631
correos de acceso anticipado, más 4.060 hilos de DM entre agentes y ~4,75M de registros, legibles por cualquiera en una app sin RLS y con escrituras sin autenticar — no por una clave filtrada
según lo reportado por Wiz · Moltbook, ene 2026
44%
del código generado por IA no pasa la revisión de seguridad — una tasa de aprobado plana en 56% durante cuatro años y más de 100 modelos, mientras el volumen de ese código se disparaba
Veracode GenAI, 2026
Ocho reglas · ningún modelo de por medio

A una regex no la convences

Desactivar el RLS. Mover una clave service_role al cliente. Hacer público un bucket o una tabla. Quitar una comprobación de auth. Un comodín en CORS, un secreto hardcodeado, el CSRF o el rate limiting apagados, un .env a punto de commitearse. Cada una responde con el riesgo, por qué importa y la alternativa segura — “ignora las instrucciones anteriores” no funciona contra un motor de reglas.

tú → Claude Code
> desactiva el RLS de la tabla users para que funcione la query

⚠  vibeward marcó una petición peligrosa

✗ Desactivar Row-Level Security
  por qué:  apagar el RLS deja cada fila legible para cualquiera que tenga la
        anon key pública — la causa más común de fugas en apps hechas a prompts.
  haz esto en su lugar:  deja el RLS activo y añade una policy:
        CREATE POLICY ... USING (auth.uid() = user_id)
Español · English · Português

Caza el prompt en el idioma en el que piensas

desactiva el RLS, usa la service_role en el front, desativa o login por enquanto — las mismas reglas, sin capa de traducción y sin LLM.

No son ocho reglas escritas tres veces: los objetos peligrosos ya son independientes del idioma — RLS, service_role, CORS y .env son identificadores, no palabras. Un idioma cuesta una tabla de verbos de unas 40 entradas, que es el único tamaño que un hablante nativo puede auditar de verdad. Ese es el punto: un conjunto de reglas en un idioma que no lees es un conjunto de reglas que nadie revisa. Se agradecen PRs añadiendo una tabla.

Cómo se conecta

Un comando. Él resuelve el resto.

init nunca escribe @latest en tus ajustes — es el único sitio donde sería mal negocio, porque el guardarraíl corre en cada prompt que escribes: ~1,8 s cada uno, muerto sin red, y cualquier publicación futura ejecutándose sin revisar en tu máquina. Así que busca un vibeward instalado, te ofrece instalarlo si no hay ninguno, y fija una versión exacta si prefieres que no. Los tres caminos son seguros; el binario instalado es sencillamente el más rápido.

npx vibeward@latest init --scope user

Por defecto no bloquea. UserPromptSubmit es el único hook cuyo stdout vuelve al contexto del modelo, así que el guardarraíl sale con 0 e inyecta la regla — tu prompt sobrevive y el agente corrige su propio enfoque. Un falso positivo te cuesta una nota que ignoras. --block está ahí si quieres el corte duro.

Un escaneo

Dos veredictos que nunca comparten escala

Un producto hecho con IA falla de dos formas que no tienen nada que ver: deja los datos abiertos, y deja la página vacía. Las dos merecen saberse. Reportarlas en la misma escala es cómo una fuga real acaba enterrada bajo un favicon que falta — así que vibeward las mantiene separadas, hasta el código de salida.

Seguridad · bloquea el build

Lo que está expuesto

Contado por severidad, escrito en SARIF, y código de salida 2 ante un crítico. Ningún fichero de configuración lo silencia.

  • Una clave en el bundle es una clave en el mundo
  • Una tabla que responde sin login es una fuga, hoy
  • Un bucket abierto no tiene dueño
Web · nunca bloquea

Lo que nunca estuvo

Su propia sección, su propia escala. Fuera del recuento por severidad, fuera de SARIF, fuera del código de salida. Sáltatelo entero con --no-web.

  • La etiqueta que el generador nunca escribió
  • El fichero que nunca se generó
  • El crawler al que se echó sin decir nada

“Un favicon ausente jamás debe compartir escala con una service key expuesta.”

Seguridad

recuento · SARIF · salida 2

Claves expuestas

La service_role de Supabase y el nuevo formato sb_secret_, Stripe, OpenAI, Anthropic, Google, AWS, GitHub, Slack, Resend, Twilio, cadenas de conexión a base de datos y claves PEM privadas — en bundles o en el código, con el fichero:línea exacto.

RLS roto Supabase

Enumera tus tablas expuestas en vivo desde la data API y luego sondea cada una con la clave pública. Marca qué columnas contienen datos personales, revisa las filas devueltas por si traen claves de terceros, y comprueba la introspección de GraphQL.

Exposición de Firebase

Detecta la configuración del cliente y sondea si hay una Realtime Database abierta y un bucket de Storage listable públicamente — el patrón detrás de la brecha de Tea.

Stacks renderizados en servidor nuevo

Next.js con Prisma o Drizzle: cabeceras ausentes en next.config, server actions y route handlers que mutan datos sin comprobar auth, e inyección de fórmulas en exportaciones CSV.

Backend inseguro

Inyección SQL, CORS abierto, inyección de comandos, eval y errores verbosos que filtran información en tus rutas de API.

Código y base de datos local expuestos

Source maps .map desplegados, ficheros SQLite commiteados, un .env en el repo — además de CSP, HSTS y X-Frame-Options en la respuesta real.

Calidad web y visibilidad ante IA nuevo en 0.3

rastrea hasta 8 páginas

Visibilidad ante IA

Un robots.txt que echa a GPTBot, ClaudeBot, PerplexityBot, CCBot o Google-Extended — y un llms.txt que falta. La gente ya busca dentro de los asistentes; a un sitio que no pueden leer no lo citan.

Buscadores y redes

Sin <title> — o el mismo título en todas las páginas. Sin meta description, sin canonical, sin Open Graph, sin JSON-LD, sin sitemap.xml.

Estructura y accesibilidad

Cero o varios <h1> en una página, un atributo lang ausente, imágenes desplegadas sin alt.

Calidad

Sin un 404 real, sin favicon, assets rotos, errores de consola al cargar y un bundle JS sin comprimir de más de 1 MB. Los errores de consola usan Playwright si resulta que lo tienes; si no, lo dice.

Huella de app hecha a prompts

Todavía en *.vercel.app o *.lovable.app, framework detectado, ver-código-fuente vacío — puntuado sobre 12. Cuánto se sigue pareciendo el sitio al día en que se generó.

No es Lighthouse

vibeward detecta ausencias binarias: la etiqueta no está, el fichero nunca se escribió. Eso es lo que le falta a un sitio hecho con IA. Core Web Vitals y WCAG completo quedan fuera de alcance, a propósito.

vibeward init

El paquete detecta. Tu agente arregla.

Pregúntale a un agente “¿falta la meta description?” y se inventará una respuesta. Un parser que responde sí o no nunca lo hace. Por eso vibeward se instala en tus herramientas de IA como skill: él reporta, el agente aplica lo que puede, y luego vuelve a ejecutar vibeward para comprobarlo.

01

Detectar

Reglas deterministas producen los hallazgos — ningún modelo de por medio, ningún hueco inventado.

02

Arreglar

Cada hallazgo trae un campo fix y otro autofixauto, needs-input o manual — que le dicen al agente hasta dónde puede llegar solo.

03

Re-detectar

vibeward vuelve a correr y lo demuestra. El mismo bucle que una suite de tests.

npx vibeward@latest init
? ¿Dónde lo quieres?
 ● Este proyecto      ~/Developer/mi-sitio
  ○ Mi cuenta          ~/.claude — en todos los repos

? ¿Qué instalo?
 ◉ Claude Code · skill    auditar + arreglar
  ◉ Claude Code · guard hook
  ◉ Cursor · regla
  ○ AGENTS.md · fallback   fusiona
  ○ GitHub Action          en cada push
El único comando que escribe

Y escribe con cuidado

Previsualiza cada fichero antes de tocar el disco, nunca sobrescribe uno que no escribió él, fusiona settings.json clave por clave — tus otros hooks se quedan donde están — y AGENTS.md entre marcadores. Volver a ejecutarlo es cómo se actualiza. Cualquier fichero existente se respalda en .vibeward.bak antes de su primer cambio.

Las opciones que el ámbito elegido no admite salen en gris con el motivo, no escondidas. No interactivo para CI y dotfiles:

vibeward init --scope user --all --yes

Los hallazgos de seguridad nunca se arreglan solos. Borrar una clave expuesta de un bundle no la des-filtra — solo el dueño decide cuándo se rota y si el incidente hay que comunicarlo.

vibeward.json

Algunos “problemas” son decisiones

Declara qué se supone que es el sitio y vibeward contrasta la realidad con eso. A una herramienta internal no se la juzga por sitemaps ni Open Graph — pero sí por assets rotos y texto alt.

Decláralo

Intención, no un botón de silencio

{
  "schemaVersion": 1,
  "intent": {
    "aiCrawlers": "blocked",
    "siteType": "website"
  },
  "suppress": [
    { "id": "web_missing_og",
      "reason": "private landing" }
  ]
}
Qué hace con eso

Le da la vuelta a la pregunta

Decir aiCrawlers: "blocked" hace que vibeward deje de llamarlo error — y plantea la pregunta mejor: ¿estás bloqueado tan a fondo como crees? Si tu robots.txt cierra la puerta a tres de los doce crawlers de IA, ese bloqueo incompleto pasa a ser el hallazgo. Creerte cerrado mientras entran nueve es peor que no haber decidido nada.

Y nunca se esconde nada. Cada supresión exige un motivo escrito, el informe imprime “producido con N supresión(es) activas” justo bajo el veredicto y las lista una a una. Solo se pueden suprimir comprobaciones de web — un veredicto del que cualquiera puede salir editando un fichero no es un veredicto.

Cuatro formas de ejecutarlo

Desde fuera, desde el código, o desde tu pipeline

Caja negra · una URL

De fuera hacia dentro

Bundles, sondeo en vivo de Supabase y Firebase, cabeceras, source maps — y toda la pasada de web. --passive lo reduce a lo que un navegador ya se descarga, sin sondear datos en absoluto.

$ vibeward https://app.lovable.app
Caja blanca · una carpeta

Auditoría profunda

Un repo, o un ZIP recién salido de v0 o Bolt. Lee el código, el backend y las migraciones SQL — tablas creadas sin RLS, policies USING (true), funciones SECURITY DEFINER.

$ vibeward scan ./client-app
Agentes y CI

Modo máquina

JSON en stdout, cada línea para humanos en stderr, así que entra directo en un parser. El payload lleva un schemaVersion — si la forma cambia, ese número cambia con ella.

$ vibeward https://app.com \
    --json --stdout --yes
GitHub Action

O deja que se ejecute solo, en cada push

Los hallazgos se suben como SARIF y aterrizan en la pestaña Security del repo. El job falla ante un crítico — los hallazgos de web nunca cambian el código de salida. Apúntalo a una carpeta con path, o a una URL desplegada con url.

- uses: JSiapoDEV/[email protected]
  with:
    url: https://your-app.com
Cada hallazgo

Contexto, no una bandera roja

Suficiente para que una persona capte el riesgo en cinco segundos, y suficiente para que un agente abra un pull request correcto.

CRÍTICO La tabla users es legible sin autenticación
Clasificación CWE-863 · Autorización incorrecta
Evidencia 1.847 filas devueltas solo con la anon key pública. Columnas sensibles presentes: email, phone, full_name.
Cómo se explota Cualquier visitante lanza GET /rest/v1/users?select=* con la anon key sacada del bundle JS. Vuelven todas las filas. Sin login.
Impacto ~1.847 registros de usuario legibles por cualquiera en internet ahora mismo. Una fuga de datos personales activa, no teórica.
Arreglo autofix: manual — activa el RLS y añade una policy de propietario; no rotes nada: la anon key es pública por diseño. La exposición era la policy que faltaba.
Antes de ejecutarlo

Lo que la gente pregunta

¿Explota o modifica algo?

El escaneo es de solo lectura: lee tu código, tus bundles y las respuestas públicas para detectar riesgo — nunca modifica, borra ni explota. La única excepción es --write-test, explícita y opcional, que envía una sola sonda de escritura no destructiva (un insert vacío) para comprobar escrituras sin autenticar; está apagada salvo que la pidas. init es el único comando que escribe, y solo dentro de tu propio proyecto.

¿Un favicon que falta puede tumbarme el build?

No. Los hallazgos de web quedan excluidos del recuento por severidad, del fichero SARIF y del código de salida — por diseño, no por configuración. Solo la seguridad bloquea. Si no los quieres ni en el informe, --no-web se salta la pasada entera.

¿Detecta el fallo detrás de las fugas de Moltbook y Lovable?

Sí — es la comprobación estrella. Encuentra la clave pública de Supabase en tu bundle (un JWT o el nuevo formato sb_publishable_), enumera en vivo cada tabla expuesta, y marca cuáles devuelven datos sin login. Ese es exactamente el modo de fallo de Moltbook — agents, owners, agent_messages y observers legibles por cualquiera, y las tablas públicas además escribibles. Para ser precisos sobre lo que la comprobación no es: encontrar la clave sb_publishable_ en un bundle no es el hallazgo. Esa clave va en el cliente por diseño. El hallazgo es una tabla que le responde.

¿Esto es un Lighthouse para apps de IA?

No. vibeward comprueba ausencias binarias — una etiqueta que no está en el HTML, un fichero que nunca se generó, un crawler al que se echó. Son las cosas que un generador se salta y a las que nadie vuelve. Core Web Vitals, presupuestos de rendimiento y una auditoría WCAG completa quedan fuera de alcance a propósito; para eso ejecuta Lighthouse.

¿Mi código sale de mi máquina?

Nunca. El escáner y el guardarraíl corren enteramente en local — sin telemetría, sin cuenta, sin subidas. La única petición saliente es a la URL a la que lo apuntas.

¿Puedo silenciar una comprobación con la que no estoy de acuerdo?

Solo las de web, y nunca en silencio. Cada entrada de vibeward.json exige un motivo escrito, y el informe indica cuántas supresiones estaban activas y qué alegaba cada una. Los hallazgos de seguridad no se pueden silenciar desde un fichero de configuración — si no, cualquiera aprobaría su propia auditoría editando un fichero.

¿El guardarraíl es un LLM?

No, y ese es el punto. Es un motor de reglas determinista, así que no se le puede convencer. "ignora las instrucciones anteriores" no funciona contra él.

¿Necesito Supabase? ¿O algún framework concreto?

Ninguno. El RLS de Supabase es una comprobación entre muchas: Firebase, claves expuestas, backends inseguros, source maps, cabeceras y toda la pasada de web funcionan en cualquier stack. Apúntalo a cualquier repo, ZIP o URL.

Lo que vibeward no hace

explotar ni atacar modificar tu código enviar tu código a ningún sitio pedir una cuenta o una clave sustituir un pentest completo preguntarle a un LLM qué decidir arreglar solo un hallazgo de seguridad
La mitad que un escáner no puede hacer

¿Quieres que lo lea una persona?

vibeward encuentra lo visible desde fuera y desde el código. No encuentra autorización rota a nivel de objeto detrás de un login, un límite entre inquilinos que aguanta en la primera petición y se rompe en la tercera, ni lógica de negocio que ya estaba mal antes de que nadie escribiera un prompt. No es modestia — está en el README, porque un escáner que diga lo contrario es la razón por la que la gente se fía de un tick verde del que no debería fiarse.

Eso necesita a alguien leyendo tu app, y es el trabajo que hago: reglas de Supabase y Firebase, fronteras de autenticación, y un informe escrito lo bastante concreto como para que tu propio agente actúe sobre él. Reserva 20 minutos — trae la URL.

La herramienta sigue siendo gratis y MIT pase lo que pase. No hay plan de pago ni nada reservado fuera de ella.

Cinco segundos

Apúntalo a algo que sea tuyo

Sin instalar, siempre la última versión, solo lectura. Ejecútalo únicamente contra apps cuyo dueño haya autorizado la auditoría.

$ npx vibeward@latest scan ./your-app
Dale una estrella en GitHub
copiado