Para encontrar vulnerabilidades de seguridad en tu código con IA, ejecuta primero los escáneres deterministas rápidos (secretos, dependencias, reglas estáticas), luego dale a un agente de programación una clase de vulnerabilidad cada vez y pídele que siga cómo se mueve la entrada no confiable por tu código. Trata cada hallazgo como una afirmación que hay que verificar, corrígelo con un test de regresión y mantén al agente lejos de los secretos reales en todo momento.
Esta guía trata de auditar tu propio código, de forma defensiva. Si quieres saber cómo evitar que el propio agente haga daño (inyección de prompts, comandos destructivos, servidores MCP maliciosos), lee primero seguridad de los agentes de programación con IA; este artículo da por hecho que esas protecciones ya están en su sitio. Los nombres de herramientas y comandos de abajo siguen la documentación oficial a octubre de 2026.
En qué es bueno una auditoría con IA, y en qué no
Los escáneres estáticos y los agentes de programación encuentran bugs distintos, y por eso te conviene usar ambos.
| Escáneres deterministas | Agente de programación | |
|---|---|---|
| Punto fuerte | Patrones conocidos, versiones de paquetes con vulnerabilidades conocidas, formatos de secretos | Lógica: quién puede llamar a esta ruta, de dónde viene este valor, qué olvidó una comprobación |
| Punto débil | No ven la lógica de negocio; mucho ruido en patrones seguros | Falsos positivos, problemas que se le escapan, respuestas distintas en cada ejecución |
| Coste | Segundos, repetible | Tokens, más lento, no repetible |
| Mejor uso | Control en CI en cada cambio | Auditoría dirigida de zonas de riesgo y código nuevo |
Un agente brilla en casos como un endpoint que comprueba que has iniciado sesión pero nunca comprueba que el pedido que estás leyendo es tuyo. Ninguna regex ve eso. En cambio, un agente no se dará cuenta de forma fiable de que el lodash de tu lockfile tiene tres años; npm audit sí.
Lo que no hace ninguno de los dos: probar tu sistema en marcha. Un agente lee el código fuente de tu copia local. Un almacenamiento en la nube mal configurado, una regla del firewall o un token filtrado en un registro de chat quedan fuera de su vista.
Antes de empezar: una configuración segura
Una auditoría de seguridad es una tarea de mucha lectura, así que configúrala de esa manera.
- Trabaja en una rama o en un git worktree. La auditoría y las correcciones deben ser fáciles de revisar y fáciles de descartar.
- Empieza en solo lectura. En Claude Code, usa el modo plan (Shift+Tab o
/plan) para la auditoría en sí; en Codex,/permissions→ Read Only o--sandbox read-only. Pasa a permitir ediciones solo cuando vayas a corregir. - Mantén los secretos fuera de su alcance. No pegues claves, tokens ni el contenido de
.enven un prompt, nunca. Si el agente necesita saber que existe una variable, basta con el nombre. Lo que debe leer es un.env.examplecon valores falsos. - Usa credenciales de desarrollo. Si el agente ejecuta tus tests, esos tests deben hablar con una base de datos local o de staging con claves desechables, nunca con producción.
Paso 1: ejecuta los escáneres deterministas
Tardan segundos y le dan al agente pistas concretas. Todos se pueden ejecutar gratis en local.
# Secrets in git history and in the working tree (gitleaks v8.19+)
gitleaks git -v .
gitleaks dir -v .
# Known-vulnerable dependencies
npm audit --audit-level=high
pip-audit -r requirements.txt
# Static analysis rules for your languages
semgrep scan --config auto
Algunas notas de la documentación oficial:
- gitleaks dividió su antiguo comando
detectengit(escanea commits) ydir(escanea archivos) en la v8.19.0; los comandos antiguos siguen funcionando, pero ya no aparecen en la ayuda. - En npm audit,
--audit-levelsolo cambia el código de salida, no el informe.npm audit fixhace una instalación real;npm audit fix --forcepuede instalar actualizaciones mayores de SemVer, así que no lo ejecutes a ciegas. - pip-audit sin argumentos audita el entorno de Python actual;
-raudita un archivo de requisitos. - Semgrep con
--config autodescarga del Semgrep Registry reglas adaptadas a tu proyecto, así que necesita acceso a la red. Añade--errorpara que termine con código 1 cuando haya hallazgos, que es lo que quieres en CI.
Guarda la salida en un archivo. En el paso 3 se la pasarás al agente en lugar de volver a escribirla.
Paso 2: audita una clase de vulnerabilidad cada vez
“Encuentra bugs de seguridad en este repositorio” te da una lista superficial. Un prompt enfocado por clase te da un análisis real. El OWASP Top 10:2025 es un buen mapa; estas son las clases que más vale la pena auditar primero en una aplicación web típica:
| Clase | Qué pedirle al agente que siga | Señal típica |
|---|---|---|
| Control de acceso roto | Cada ruta que lee o cambia un registro: ¿comprueba que el registro pertenece a quien llama? | findById(req.params.id) sin filtro de propietario o de tenant |
| Inyección (SQL, shell, XSS) | Cada lugar donde la entrada del usuario llega a una consulta, un comando de shell o HTML | Concatenación de cadenas en SQL, exec con entrada, renderizado de HTML sin escapar |
| Fallos de autenticación | Login, sesión, restablecimiento de contraseña y manejo de tokens | Tokens de restablecimiento que nunca caducan, login sin límite de intentos |
| SSRF | Cada petición del lado del servidor cuya URL viene del usuario | fetch(req.body.url) sin lista de permitidos |
| Secretos en el repositorio | Claves en el código, tokens en la configuración, credenciales en los tests | Cadenas que parecen claves; gitleaks será más fiable |
| Cadena de suministro | Dependencias, scripts de instalación, permisos de los workflows de CI | Actions sin versión fijada, permissions: amplios en los workflows |
Un prompt que funciona, en modo plan:
Audita este repositorio en busca de control de acceso roto. No edites archivos.
1. Lista cada ruta HTTP que lee, actualiza o borra un registro por ID.
2. Para cada una, encuentra de dónde viene la identidad de quien llama y si
la consulta se limita a los registros que le pertenecen (usuario o tenant).
3. Informa solo de las rutas en las que puedas demostrar que falta la comprobación.
Para cada hallazgo indica: file:line, la ruta, de dónde viene el ID,
por qué el middleware existente no lo cubre y una gravedad
(alta/media/baja). Si no estás seguro, dilo en lugar de adivinar.
Repite la misma estructura para inyección, autenticación y SSRF. Una clase por conversación mantiene enfocada la ventana de contexto, y puedes ejecutarlas en paralelo en sesiones separadas.
Para la inyección, ayuda decirle al agente cómo es lo “seguro” en tu stack, para que no marque cada consulta:
Usamos consultas parametrizadas con db.query(sql, params) en todas partes.
Encuentra cualquier lugar que construya SQL, comandos de shell o HTML a partir
de datos de la petición sin pasar por los params de db.query, execFile con un
array de argumentos o el escapado del motor de plantillas. Ignora el código de tests/.
Paso 3: usa las revisiones de seguridad integradas
Varios agentes ya incluyen una revisión de seguridad que no tienes que escribir tú.
/security-review de Claude Code. La referencia oficial de comandos lo describe como un análisis de los cambios de tu rama actual en busca de vulnerabilidades de seguridad: revisa el diff entre tu rama y la rama por defecto de origin y busca riesgos como inyección, problemas de autenticación y exposición de datos. Necesita un remoto origin. Solo cubre los cambios de tu rama, así que ejecútalo antes de abrir un pull request. El repositorio claude-code-security-review de Anthropic explica cómo personalizarlo: copia su security-review.md en .claude/commands/ y añade tus propias reglas, por ejemplo qué patrones son seguros en tu código.
Plugin security-guidance de Claude Code. Se instala con /plugin install security-guidance@claude-plugins-official y revisa el código mientras Claude lo escribe: una comprobación de patrones en cada edición (cosas como eval(, child_process.exec, .innerHTML =), una revisión de seguridad en segundo plano del diff de cada turno y una revisión más profunda cuando Claude hace commit. Puedes añadir reglas del proyecto en .claude/claude-security-guidance.md. La documentación deja claro que no bloquea escrituras y que se le pueden escapar problemas; es una capa más.
/review de Codex. El comando de revisión de Codex (y codex review --uncommitted o --base main desde la shell) es una revisión de código general. Pídele explícitamente que se centre en la seguridad si es lo que quieres.
Extensión de seguridad de Gemini CLI. Se instala con gemini extensions install https://github.com/gemini-cli-extensions/security y añade /security:analyze para los cambios de tu rama y /security:scan-deps, que revisa las dependencias con OSV-Scanner.
Para el código que ya tienes, y no para los cambios de una rama, usa los prompts por clase del paso 2. También puedes pasarle la salida de los escáneres:
Aquí tienes la salida de semgrep y npm audit en scan-results.txt.
Para cada hallazgo, comprueba si es alcanzable desde la entrada del usuario en
este código. Marca cada uno como confirmado, probable falso positivo o
necesita una persona, con una razón de una línea. No edites archivos.
Paso 4: separa los hallazgos reales de los falsos positivos
Las revisiones de seguridad con IA suenan seguras de sí mismas tanto si aciertan como si no. Pide pruebas, no veredictos:
- Origen: ¿por dónde entra el valor no confiable? ¿El cuerpo de una petición, una query string, una subida de archivo, un webhook?
- Camino: ¿por qué funciones pasa hasta llegar a la llamada peligrosa? Pide la cadena con file:line en cada salto.
- Protección: ¿qué validación, escapado o autorización hay en ese camino, y por qué no cubre este caso?
- Alcance: ¿la ruta está expuesta? Un hallazgo en un script de administración muerto no es lo mismo que uno en una API pública.
Después pide una segunda opinión. Una sesión nueva, o mejor un modelo distinto, debería comprobar los hallazgos de gravedad alta antes de que nadie escriba una corrección. Dale el hallazgo y el código, no el razonamiento del primer agente, para que no se limite a darle la razón. Revisión de código con IA explica cómo valorar los hallazgos y mantener ese ciclo acotado.
Falsos positivos habituales que puedes esperar: SQL construido solo con constantes, HTML que pasa por el escapado automático de un framework, fixtures de tests con claves falsas y peticiones del lado del servidor a una URL interna fija. Escribe los patrones seguros en CLAUDE.md o AGENTS.md para que las siguientes auditorías dejen de marcarlos.
Paso 5: corrige con un test de regresión
Una corrección de seguridad sin test tiende a volver. Pide primero el test:
Corrige la comprobación de propiedad que falta en GET /api/orders/:id (hallazgo n.º 2).
1. Primero escribe un test en el que el usuario A pide el pedido del usuario B y
espera un 404. Ejecútalo y muéstrame que falla.
2. Después añade la comprobación de la forma más pequeña que encaje con nuestro
middleware existente. No cambies código que no tenga relación.
3. Ejecuta la suite de tests completa y muéstrame el diff.
El test que primero falla y luego pasa demuestra que el bug existía y que la corrección lo cubre. Deja cada corrección en su propio commit con un mensaje claro, para que el historial explique qué estaba mal. Para el hábito general de corregir con el test primero, consulta depurar código con IA.
La misma disciplina vale para los hallazgos de dependencias: actualiza un paquete cada vez, ejecuta los tests y lee el changelog en busca de cambios incompatibles. Un npm audit fix --force masivo es la forma en que una auditoría acaba en una caída del servicio.
Si encuentras un secreto real en el repositorio
Este es el único caso en el que el orden de los pasos importa:
- Rota el secreto primero. Revoca la clave en el proveedor y emite una nueva. Una vez que se ha hecho push de un secreto, da por hecho que está comprometido; borrar el archivo no deshace la filtración.
- Lleva el nuevo secreto a tu gestor de secretos o a tu entorno, no de vuelta al código.
- Luego limpia: quítalo del código y decide con tu equipo si reescribir el historial. Reescribir el historial no sirve de nada si la clave no se rotó.
- Evita el siguiente con un hook de pre-commit. gitleaks documenta esta entrada de
.pre-commit-config.yaml:
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.24.2
hooks:
- id: gitleaks
Deja que el agente ayude con los pasos 2 a 4, pero nunca pegando el secreto en la conversación. “La clave de Stripe de src/config.ts tiene que pasar a una variable de entorno llamada STRIPE_SECRET_KEY” es todo lo que necesita.
Hazlo continuo
Una auditoría puntual pierde valor en cuanto llega código nuevo. Pon las comprobaciones deterministas en CI y reserva la revisión con IA para los pull requests:
# .github/workflows/security.yml (excerpt)
- run: npm audit --audit-level=high
- run: semgrep scan --config auto --error
Para una pasada con IA en cada pull request, la GitHub Action anthropics/claude-code-security-review de Anthropic comenta los hallazgos en el PR. Su input obligatorio es claude-api-key; entre los opcionales están comment-pr, exclude-directories y false-positive-filtering-instructions. Si ya ejecutas Claude en GitHub Actions, Claude Code GitHub Actions cubre la configuración y el manejo de secretos.
Cómo hacerlo con AgentVera
AgentVera es una app de escritorio para macOS, Windows y Linux que ejecuta Claude Code, Codex, Gemini CLI y otros agentes CLI uno al lado de otro en terminales reales. Para las auditorías de seguridad, eso facilita algunas configuraciones:
- Workspace: pon un auditor en solo lectura (con el permiso en Ask) junto a un agente que corrige en un worktree, y un tercer panel con otra CLI como segunda opinión. Cada agente mantiene su propio nivel de permisos.
- Revisión de código: activa la revisión al final de cada turno en los ajustes del proyecto y un modelo de Claude que tú eliges revisa los cambios del agente que corrige; los hallazgos llegan con gravedad y un enlace file:line y pueden volver al agente, como máximo dos rondas seguidas.
- Bandeja de revisión: el trabajo terminado espera en forma de tarjetas y se marcan los cambios de riesgo: código de autenticación y seguridad, archivos de dependencias, archivos de CI e infraestructura,
.envy cambios sin tests. - Verify (Pro y Team): un verificador independiente en solo lectura comprueba el resultado frente a los criterios de tu petición, como “existe un test de regresión y falla sin la corrección”.
- Agentes en Docker: ejecuta Claude Code o Codex en un contenedor que solo ve la carpeta del proyecto, de modo que los archivos y las claves SSH del resto de tu máquina quedan fuera de su alcance durante una auditoría.
- Checkpoints: cada turno se guarda como una instantánea, así que deshacer una corrección que sale mal está a un clic.
La cuadrícula, los worktrees, la revisión de código y los agentes en Docker están en el plan gratuito. Descarga AgentVera y haz tu primera auditoría en una rama.
Errores comunes
- Pedir “todos los problemas de seguridad” de una vez. Obtienes una checklist genérica. Audita una clase cada vez.
- Corregir antes de verificar. “Corregir” un falso positivo añade código que nadie entiende. Consigue pruebas primero.
- Pegar secretos para “comprobar si son válidos”. Nunca. Rótalos.
- Ejecutar
npm audit fix --forceen un bucle del agente. Las actualizaciones mayores rompen cosas de formas que parecen no tener relación. - Tomar una revisión con IA limpia como una garantía. Solo significa que el agente no encontró nada esta vez. Mantén los escáneres en CI.
- Dejar que el auditor edite. Mantén la auditoría en solo lectura y las correcciones en un paso aparte y revisado.
Conclusión
Empieza con gitleaks, tu auditor de dependencias y Semgrep. Luego audita una clase de OWASP cada vez con un agente en solo lectura, pidiendo pruebas con file:line y un camino alcanzable. Ejecuta /security-review (o el equivalente de tu agente) antes de cada pull request, haz que una segunda sesión compruebe los hallazgos graves y corrige cada uno con un test de regresión que falle primero. Si se filtra un secreto, rótalo antes que nada. Cuando quieras poner a los agentes a trabajar en las correcciones, programación en pareja con IA muestra cómo seguir en el asiento del navegante. Si todo esto es nuevo para ti, aprende a programar con IA es un punto de partida más suave.