Security-audit: la skill de Cloudflare que audita tu código
Le pides a tu agente de IA que revise la seguridad de tu repositorio y te devuelve catorce hallazgos en dos minutos.
Nueve son “falta rate limiting”. Tres son “considera añadir validación de entrada”. Uno es una cabecera que no has puesto. Y el último, el que sí era grave de verdad, ni lo menciona.
¿Te suena?
Cloudflare tenía el mismo problema, pero a otra escala: auditar su flota de repositorios sin ahogar al equipo de seguridad en ruido. Su respuesta fue una skill de unas 450 líneas que fue creciendo hasta convertirse en el harness de descubrimiento de vulnerabilidades que describen en su blog. Y en septiembre de 2026 publicaron esa semilla en GitHub con licencia MIT.
Se llama security-audit y no se parece nada a lo que tú y yo entendemos por “pídele a la IA que revise el código”.
Lo que cubre este artículo:
- Qué es la skill
security-audity de dónde sale - Cómo se instala y qué necesitas tener montado antes
- Por qué su disciplina de evidencia cambia la calidad de lo que recibes
- El catálogo completo: 162 clases de ataque repartidas en 11 ficheros
- Cómo está estructurada por dentro: seis fases, agentes aislados y dos validadores
- Tres casos de uso con la salida exacta que te devuelve en cada uno
Si vienes de las herramientas de revisión automática, echa un ojo antes a Warden, la propuesta de Sentry y al plugin security-guidance de Anthropic. Esta skill juega en otra liga: no revisa un diff, audita un repositorio entero.
¿Qué es exactamente la security-audit skill de Cloudflare? ¶
Es una Agent Skill: un paquete de instrucciones en Markdown que un agente de IA carga cuando detecta que la tarea encaja. Nada de binarios ni de servicios. Markdown, un esquema JSON y dos validadores en Node sin dependencias.
Lo que la hace distinta es su ambición. En lugar de decirle al modelo “busca vulnerabilidades”, le monta un procedimiento completo: reconocimiento del código, plan determinista de cobertura, cazadores aislados, verificadores adversariales que intentan tumbar cada hallazgo, salida en JSON validada contra esquema, y solo al final la prosa del informe.
El repositorio son 20 ficheros: 15 de Markdown con unas 24.700 palabras de instrucciones, un report-schema.json, dos validadores (1.645 líneas de JavaScript) y sus dos ficheros de tests (1.392 líneas más). Todo bajo licencia MIT.
Y tiene una característica que agradecerás: es agnóstica de plataforma. Habla de “parent” (el agente que coordina), “Task tool” (el mecanismo de delegación de tu agente) y de dos roles de subagente, research y general. No menciona a Claude Code ni a ningún otro por su nombre. Si tu agente sabe lanzar subagentes, la skill funciona.
Dos modos, y este detalle importa ¶
La skill arranca en modo guía por defecto. Cargarla no autoriza la auditoría completa ni la creación de ficheros.
- Guidance mode: para preguntas de seguridad, revisiones puntuales, metodología o triaje de un hallazgo concreto. Usa las partes relevantes del documento y no escribe nada en disco.
- Full audit mode: solo cuando pides de forma explícita auditar el repositorio, hacer un pen-test, una revisión completa de principio a fin, o cuando pides los artefactos del informe. Entonces se ejecutan las seis fases.
Si tu petición es ambigua, la skill te obliga a preguntar antes de crear un solo fichero. Es una decisión pequeña que evita que la skill te llene el disco de carpetas de auditoría sin que se lo hayas pedido.
¿Cómo se instala la security-audit skill? ¶
Con el CLI de skills.sh, en un comando:
npx skills add https://github.com/cloudflare/security-audit-skill \
--skill security-audit
Eso la deja instalada en el proyecto en el que estés. Si la quieres disponible en todos tus repositorios, añade --global:
npx skills add https://github.com/cloudflare/security-audit-skill \
--skill security-audit \
--global
Con npx skills --help tienes las opciones de selección de agente y el modo no interactivo, útil si la vas a instalar desde un script de aprovisionamiento.
Cómo se activa ¶
No hay comando que ejecutar. Abres tu agente apuntando al código que quieres auditar y se lo pides en lenguaje natural:
security audit this codebase
find security vulnerabilities in ./src
do a security review, output to ~/audits/mi-proyecto
La skill se activa sola cuando la petición encaja con su descripción. Si no indicas directorio de salida, escribe en ~/security-audit-skill/<nombre-repo>/run-<N>, donde <N> es el siguiente entero libre. Y nunca escribe dentro del repositorio auditado salvo que elijas de forma explícita un directorio que el control de versiones ignore, cosa que el propio agente verifica antes de aceptar.
Los tres requisitos que no puedes saltarte ¶
Aquí es donde mucha gente se va a estrellar, así que vamos con calma.
- Un agente con modelo que soporte tool use y subagentes en paralelo. Sin delegación no hay validación adversarial, y sin validación adversarial esto es otra cosa distinta.
- Node.js, para los dos validadores. No tienen dependencias, así que no hay
npm installque valga. - Un sandbox reforzado por el sistema operativo para cualquier ejecución de código del objetivo: builds, tests, procesos, navegadores, emuladores, fuzzers y procesado de ficheros de prueba.
Ese sandbox tiene una lista de condiciones concreta: sin red externa (solo un espacio de nombres loopback aislado si la comprobación necesita tráfico local), entorno vacío poblado desde una lista blanca explícita con HOME, temporales y cachés dentro del scratch, objetivo y toolchain montados en solo lectura, escritura permitida únicamente en el scratch/ asignado, y límites explícitos y bajos de CPU, memoria, procesos, tamaño de fichero, disco y tiempo de reloj.
⚠️ Si no puedes garantizar todos esos controles, la skill no ejecuta el código del objetivo. No lo hace igualmente “con cuidado”: marca la pista como
needs_validationindicando qué capacidad de sandbox falta y propone un plan de validación seguro. Esa negativa a improvisar es lo que evita informes que suenan sólidos y no lo son.
Una auditoría es una spec ejecutada con disciplina
Lo que hace esta skill con la seguridad es lo mismo que el Spec Driven Development hace con las funcionalidades: definir el criterio antes de trabajar, para que el resultado se pueda comprobar. En este curso recorres el ciclo completo de OpenSpec sobre un proyecto real, del proposal al archivado.
Entra en el curso gratis →¿Por qué usar esta skill en lugar de pedirle “búscame bugs” al agente? ¶
Por una razón que puedes medir: el porcentaje de lo que recibes que merece tu tiempo.
Un agente al que le sueltas “revisa la seguridad” produce lo que los modelos producen bien: una lista plausible. Falta cabecera X, falta validación Y, considera añadir Z. Te deja con el trabajo caro sin hacer, que es separar lo que rompe una frontera de confianza real de lo que es una buena práctica ausente.
La skill ataca ese problema con cinco principios de diseño que están escritos en el propio README y repetidos como restricciones dentro de cada prompt.
Solo se confirma lo que rompe una frontera establecida. Para cada candidato hay que nombrar seis cosas: el principal de menor confianza, la entrada o acción aceptada, el control que debería haberlo rechazado, la frontera cruzada, el principal o recurso afectado y el resultado observado. Si falta una, no es un hallazgo confirmado. Si la pista está fundamentada en código pero bloqueada por un hecho que no se ve desde el repositorio, se queda en needs_validation con el hecho exacto que falta.
Validación adversarial. El agente que comprueba un hallazgo nunca es el que lo encontró. Y en el perfil estándar hay dos pasadas de verificación, con agentes frescos distintos, sobre el mismo registro.
La severidad exige impacto. Probabilidad por impacto, no desviación respecto a un checklist. La severidad general no puede superar al impacto demostrado. Y hay un discriminador escrito para la frontera alta/media: ¿el resultado demostrado derrota por completo un control explícito con consecuencias reales, o solo lo debilita? Si no puedes enunciar el daño concreto, la severidad es más baja de lo que te parece.
Los huecos de defensa en profundidad no son vulnerabilidades. Si la capa A evita el ataque, la ausencia de la capa B es una nota de endurecimiento. Va a una sección separada del informe y no contamina la tabla de hallazgos.
Varias pasadas mejoran la cobertura. Este es el dato honesto que casi nadie publica: en las pruebas de Cloudflare, una sola pasada encontró aproximadamente la mitad de las vulnerabilidades que las pasadas repetidas encontraron en total. Y las que aparecían en la primera pasada tendían a ser las más simples.
🔑 Una auditoría con IA que te promete cobertura completa en una ejecución te está mintiendo. Esta skill escribe explícitamente que ninguna pasada es completa y te obliga a declararlo en el informe.
Tres veredictos que no se mezclan ¶
Todo hallazgo acaba en uno de tres estados, y sus contratos son excluyentes:
| Veredicto | Qué significa | Campos que usa | Lleva severidad |
|---|---|---|---|
confirmed |
Traza de código completa y resultado observado acotado | root_cause, intended_behavior, conditions, execution, remediation, severity, confidence |
Sí |
needs_validation |
Hipótesis fundamentada en código con un hecho exacto sin resolver | claimed_root_cause, blockers, validation_plan |
No |
rejected |
Candidato refutado durante la validación | claimed_root_cause, reason |
No |
Ese rejected no es basura que se tira. Se guarda en findings.json para que futuras ejecuciones no vuelvan a repetir la misma afirmación sin evidencia nueva. La auditoría tiene memoria.
¿Qué revisa la skill? El catálogo completo de clases de ataque ¶
Aquí está el músculo. El catálogo son 162 clases de ataque nombradas, repartidas entre un fichero de clases ordinarias y diez ficheros de dominio que se seleccionan según lo que el reconocimiento encuentre.
Las 9 clases ordinarias ¶
Viven en ATTACK-CLASSES.md y aplican a casi cualquier objetivo:
| Clase | Qué persigue |
|---|---|
| Injection | Entrada no confiable hasta un sink peligroso, incluida la indirecta: dato guardado sano y recuperado en contexto peligroso, inyección por nombres de campo, claves, cabeceras y metadatos |
| Access control | No si existe la comprobación de permisos, sino si es el permiso correcto sobre el recurso correcto por el mecanismo correcto |
| Resource and file handling | Path traversal (con symlinks, secuencias codificadas, bytes nulos), SSRF, deserialización insegura, zip slip, TOCTOU en ficheros |
| Cryptography and secrets | Aleatoriedad débil, secretos en logs y URLs, HMAC sin verificar, reutilización de nonce, canales laterales de tiempo, y qué pasa cuando la operación criptográfica falla |
| Business logic | Violaciones de máquina de estados, carreras con impacto de negocio, manipulación numérica, lógica temporal, comportamiento por defecto cuando falta configuración |
| Feature abuse and data leakage | El export como exfiltración, el import como inyección, la búsqueda como oráculo, la enumeración por efectos secundarios, el webhook como SSRF |
| Chained vulnerabilities | Comportamientos contenidos por separado que se convierten en vulnerabilidad cuando otro componente asume una garantía más fuerte |
| Wildcard | Sin categoría asignada. “¿Cuál es el código más raro del repositorio? ¿Por qué existe?” Y una joya: mira los tests, ¿qué no están probando? |
| Obvious things | Lo básico que todos asumen que ya miró otro: secretos en el código, TODOs sobre seguridad, modo debug activable por cabecera, endpoints /debug y /metrics sin proteger, CORS con comodín, cookies sin HttpOnly |
Esa última merece un comentario. La skill le dice al agente: “no necesitas ser creativo, necesitas ser exhaustivo y literal”. Y a continuación le exige que trace el impacto antes de reportar: una cookie sin HttpOnly no es un hallazgo si no contiene nada sensible. Una bandera no es un hallazgo.
Los 10 ficheros de dominio ¶
Cada uno se selecciona no porque aparezca el nombre de un lenguaje o una dependencia, sino porque el reconocimiento encontró la frontera de confianza que ese fichero describe.
| Fichero de dominio | Clases | Cuándo se activa |
|---|---|---|
MEMORY-SAFETY-AND-BINARY.md |
20 | C/C++/Rust unsafe, kernel, parsers, FFI, JIT, cargadores binarios |
WEB-PROTOCOL-AND-AUTH.md |
20 | HTTP, proxies, CDN, sesiones, JWT, OAuth/OIDC, SAML, MFA, passkeys, mTLS |
DESKTOP-MOBILE-AND-LOCAL-IPC.md |
16 | Apps nativas, deep links, webviews, helpers privilegiados, XPC/Binder/D-Bus |
CLOUD-AND-DEPLOYMENT.md |
15 | IAM, IaC, contenedores, serverless, ingress, ciclo de vida de secretos |
DATA-ISOLATION-AND-LIFECYCLE.md |
15 | Multi-tenant, cachés, búsqueda, export/backup, migración, borrado, restore |
AI-AND-LLM.md |
14 | Chatbots, RAG, memoria persistente, tool calling, servidores y clientes MCP |
CLIENT-SIDE.md |
14 | SPAs, extensiones, service workers, postMessage, CORS, prototype pollution |
PROTOCOLS-RPC-AND-MESSAGING.md |
14 | gRPC, GraphQL, Protobuf, colas, brokers, webhooks, streaming |
RESOURCE-EXHAUSTION-AND-AVAILABILITY.md |
13 | CPU, memoria, disco, conexiones, workers, cuotas y gasto del operador |
SUPPLY-CHAIN-AND-RELEASE.md |
12 | Dependencias, CI, releases, firma, actualizaciones, plugins |
Si trabajas con agentes, el fichero de IA merece una lectura aparte. Su disciplina nuclear empieza con una frase que conviene tener a mano: “la inyección de prompt por sí sola no es un hallazgo”. Exige un fallo de frontera a nivel de código: que el contenido llegue al contexto de otro principal, que invoque autoridad que el solicitante no tiene, que revele datos que no puede leer o que alcance un sink al que no llega de otro modo. Y remata: “un prompt de guardarraíl no es una frontera de seguridad”.
De ahí salen clases como action-confirmation and approval binding (apruebas una acción descrita y la ejecución usa argumentos cambiados, otro recurso u otro turno del modelo), MCP server and tool identity confusion (dos servidores reclamando la misma identidad de herramienta) o MCP metadata and schema as policy (descripciones de herramientas tratadas como autorización).
El catálogo de ataques de una skill cambia según lo que el sector descubre cada semana. Cada domingo seleccionamos 12 recursos sobre IA y desarrollo entre +7.200 developers. Gratis desde 2018.
Quiero esa dinamita 🧨¿Cómo está estructurada la skill por dentro? ¶
En seis fases que el agente coordinador ejecuta en orden, sin saltarse ninguna.
Fase 1 · Reconocimiento. Cuatro agentes research en paralelo, cada uno con su prompt escrito. El 1a mapea producto, stack y operación local. El 1b mapea principales, autoridad y controles. El 1c inventaría superficies de entrada, copias derivadas y sinks. El 1d evalúa qué se puede ejecutar en local y qué controles de sandbox soporta tu máquina. De ahí sale architecture.md, con un tope duro de unas 1.000 palabras, y el coverage-ledger.json.
Fase 2 · Oleadas de caza guiadas por cobertura. El coordinador asigna unidades del libro de cobertura a cazadores aislados. Cada prompt de cazador lleva nueve partes en orden fijo, incluidas las clases de ataque copiadas literalmente (nunca por su nombre) y la lista de bloques excluidos con el motivo de cada exclusión. Al terminar cada oleada entra un crítico de cobertura fresco que solo propone cobertura, nunca hallazgos.
Fase 3 · Validación de candidatos. Cada candidato único va a un verificador fresco que no lo cazó, con un prompt que empieza así: “tú no escribiste este candidato; intenta refutarlo”. Puede promover, degradar o rechazar.
Fase 4 · Salida estructurada. Todo se escribe en findings.json ordenado por fingerprint y se valida con validate-findings.cjs contra el esquema, que usa additionalProperties: false. El libro de cobertura pasa por validate-coverage-ledger.cjs.
Fase 5 · Verificación independiente de los registros. Un verificador fresco por cada registro final, en paralelo. Y una regla que me encanta: si un verificador propone una sustitución material (promoción a un veredicto más fuerte, o cambio de causa raíz, traza, resultado observado o severidad), esa sustitución no se aplica hasta que un tercer verificador independiente la valide.
Fase 6 · Informe neutral respecto al objetivo. Solo entonces se escribe prosa, derivada de los registros ya verificados. La prosa nunca puede cambiar un veredicto, una severidad o un impacto.
El libro de cobertura es la pieza clave ¶
coverage-ledger.json es lo que convierte “he revisado la autenticación” en algo comprobable. Cada unidad es una combinación de superficie de entrada, frontera de confianza, subsistema y clase de ataque, con referencias canónicas derivadas del código:
{
"coverage_id": "...",
"canonical_refs": {
"surface": "src/router.ts#POST /users/:id",
"boundary": "src/authz.ts#requireOwner",
"subsystem": "packages/api",
"attack_class": "ATTACK-CLASSES.md#Access control"
},
"starting_paths": ["src/router.ts"],
"status": "planned",
"agent_id": null,
"reviewed_paths": [],
"local_checks": [],
"result_fingerprints": [],
"unresolved": []
}
El coverage_id se deriva con percent-encoding RFC 3986 de las cuatro referencias unidas por ::, sin slugs con pérdida. Y hay una tabla de estados que el validador aplica sin piedad: una unidad covered necesita dueño, rutas revisadas y comprobaciones, sin hechos sin resolver y sin candidatos. Una unidad deferred necesita motivo. El libro es la afirmación de cobertura; un resumen de arquitectura o un recuento de agentes no lo es.
Tres perfiles y un presupuesto ¶
| Perfil | Oleadas | Verificación | Para qué |
|---|---|---|---|
quick |
Una sola, con un crítico final | Un verificador fresco por candidato (fases 3 y 5 fusionadas) | Objetivos pequeños, re-ejecuciones, primer vistazo |
standard |
Hasta pasada limpia | Dos pasadas separadas | El flujo tal y como está escrito |
deep |
Hasta pasada limpia, unidades por subsistema y modo de ciclo de vida | Dos pasadas, más segunda pasada independiente en unidades ya cubiertas | Objetivos grandes o de alto riesgo |
Los perfiles cambian amplitud y redundancia, nunca el listón de evidencia. No se puede recortar la validación de candidatos, la frontera de ejecución, la disciplina de needs_validation, la validación de esquema ni la verificación independiente.
Y si le pones presupuesto (número máximo de invocaciones de agente), la skill lo gasta en un orden concreto: reserva primero los críticos y la validación, y solo después asigna cazadores. Si el presupuesto no da para el mínimo, no lanza ni un agente: te pide más presupuesto, menos alcance u otro perfil. Prefiere no auditar a auditar mal.
💡 Si solo te llevas una idea de toda la arquitectura: la separación entre quien encuentra y quien verifica es lo que convierte una lista de sospechas en un informe.
Tres casos de uso y qué esperas recibir de vuelta ¶
Vamos a lo práctico. Tres escenarios distintos, con la forma exacta de lo que sale por el otro lado. Los ejemplos de registros son ilustrativos, pero respetan campo por campo el esquema real del repositorio.
Caso 1: API multi-tenant antes de abrir el registro público ¶
El contexto. SaaS en Node con Postgres, autenticación por sesión, endpoints de exportación y un panel de administración. Vas a abrir el registro y quieres saber si el aislamiento entre inquilinos aguanta.
Lo que pides. “Security audit this codebase, deep profile, output to ~/audits/saas-api”.
Lo que hace por dentro. El reconocimiento detecta almacén multi-inquilino, HTTP y sesiones de navegador, así que selecciona DATA-ISOLATION-AND-LIFECYCLE.md y WEB-PROTOCOL-AND-AUTH.md como dominios. El libro de cobertura se llena con unidades por cada ruta y frontera. Los cazadores trabajan en paralelo, cada uno con su directorio de trabajo aislado.
Lo que recibes. Si encuentra un fallo de aislamiento en una ruta de exportación, un registro así en findings.json:
{
"verdict": "confirmed",
"fingerprint": "export/tenant-scope/bulk-report",
"title": "Bulk export ignores tenant scope on report_id lookup",
"root_cause": "The bulk export handler resolves report_id before applying the tenant filter applied by the single-item route.",
"intended_behavior": "Every report read must be scoped to the session tenant.",
"trace": [
{ "kind": "entrypoint", "file": "src/routes/export.ts", "line": 42,
"scope": "POST /export/bulk", "description": "Accepts report_ids from the request body" },
{ "kind": "propagation", "file": "src/services/report.ts", "line": 118,
"scope": "loadReports()", "description": "Queries by id without tenant_id predicate" },
{ "kind": "sink", "file": "src/services/export.ts", "line": 77,
"scope": "buildCsv()", "description": "Serializes rows into the response stream" }
],
"conditions": [
{ "kind": "authentication_level", "description": "Any authenticated user of any tenant" }
],
"execution": {
"attacker_perspective": "Authenticated dummy user of tenant A",
"payloads": "{ \"report_ids\": [\"<id owned by dummy tenant B>\"] }",
"instructions": "Run the existing integration test fixture with two dummy tenants and call the bulk export route.",
"observed_result": "CSV response contains the row owned by dummy tenant B."
},
"remediation": {
"strategy": "Apply the tenant predicate inside loadReports() so every caller inherits the scope."
},
"severity": {
"likelihood": { "score": "high", "reason": "Reachable by any authenticated account with a known id" },
"impact": { "score": "high", "reason": "Cross-tenant read of report content" },
"overall_severity": "high"
},
"confidence": "high"
}
Fíjate en lo que no hay: ni “considera añadir”, ni severidad inventada, ni una instrucción para probarlo contra producción. Hay fichero, línea, ámbito, entrada exacta, resultado observado con datos ficticios y el cambio mínimo que impone el invariante.
Además de findings.json recibes REPORT.md (resumen ejecutivo con tabla de confirmados), FINDINGS-DETAIL.md (reproducción completa de cada confirmado medio, alto o crítico), NEEDS-VALIDATION.md, architecture.md, coverage-ledger.json y run-metadata.json.
Caso 2: un agente con herramientas y servidores MCP ¶
El contexto. Has montado un asistente interno que lee tickets, consulta una base de conocimiento y ejecuta acciones vía MCP. Todo el mundo te dice que “hay riesgo de prompt injection” y nadie te dice dónde.
Lo que pides. “Do a security review of the agent runtime, focus on tool dispatch and MCP”.
Lo que hace por dentro. Selecciona AI-AND-LLM.md. Sus cazadores no buscan prompts persuasivos: buscan dónde el código concede autoridad, confía en la salida del modelo, escribe estado duradero o alimenta un sink. Trazan el flujo contenido no confiable → modelo o memoria → capacidad, autoridad o sink.
Lo que recibes. Aquí aparece mucho el segundo veredicto, porque el comportamiento del proveedor o del renderizador no se ve desde el repositorio:
{
"verdict": "needs_validation",
"fingerprint": "mcp/tool-identity/reconnect-binding",
"title": "Tool calls routed by model-selected alias instead of authenticated connection",
"claimed_root_cause": "The dispatcher resolves tool names against a merged registry, so two servers can claim the same tool identity after a reconnect.",
"trace": [
{ "kind": "entrypoint", "file": "src/mcp/registry.ts", "line": 64,
"scope": "mergeServerTools()", "description": "Merges tool descriptors keyed by name" },
{ "kind": "sink", "file": "src/mcp/dispatch.ts", "line": 131,
"scope": "callTool()", "description": "Selects the transport by name, not by connection id" }
],
"blockers": [
"Whether the deployed MCP server set allows a second server to register an overlapping tool name is not observable from source."
],
"validation_plan": {
"local": "Start two isolated loopback stub servers declaring the same tool name and record which transport receives the call.",
"deployment": "Ask the operator to list the configured MCP servers and their declared tool names for one production workspace."
}
}
Sin severidad. Con el hecho exacto que falta y dos maneras seguras de resolverlo: una local acotada y una que le pides al responsable del despliegue. Nunca “lanza tráfico contra el entorno real a ver qué pasa”.
Este es el registro que más tiempo te ahorra, porque convierte una preocupación difusa en una pregunta que se responde en veinte minutos.
Verificar antes que confiar
El agente que audita también puede equivocarse: aprende a verificarlo
La skill separa a quien encuentra de quien verifica porque un modelo solo no basta. En esta masterclass grabada en directo montamos el método para comprobar lo que un agente afirma, con casos reales donde la IA sonaba convincente y estaba equivocada.
Entrar a la masterclass →Masterclass en directo · validada por la comunidad de Web Reactiva Premium
Caso 3: una librería open source antes de publicar la release ¶
El contexto. Mantienes un paquete con un parser y un CLI. No hay servidor, no hay base de datos, no hay inquilinos. Y aun así quieres pasar un filtro antes de publicar.
Lo que pides. “Security audit ./src with the quick profile, budget 12 agents”.
Lo que hace por dentro. Aplica la puerta estricta de presupuesto antes de lanzar el primer agente de reconocimiento: reserva las cuatro llamadas de reconocimiento, un crítico final y al menos un verificador. Si con 12 no llega, no arranca. Como es una ejecución con alcance limitado, todas las superficies fuera de ./src se registran como out_of_scope, nunca como covered.
Lo que recibes. Probablemente pocos confirmados, algún rechazado y un resumen de cobertura que es tan valioso como los hallazgos:
## Coverage summary
Profile: quick · Scope: ./src · Budget: 12 agents (11 spent)
Source ref: 8f21c0d (worktree clean)
Execution policy: sandboxed-source-and-local-only
| Status | Units |
|---|---|
| covered | 9 |
| candidate | 2 |
| blocked | 1 |
| deferred | 4 |
| out_of_scope | 6 |
This is a partial pass. The `quick` profile ran one hunter wave followed by one
final critic. No prior coverage ledger was available for this repository.
Y un rejected guardado para la próxima:
{
"verdict": "rejected",
"fingerprint": "parser/depth/stack-overflow",
"title": "Recursive descent parser reaches stack exhaustion on nested input",
"claimed_root_cause": "Nested arrays recurse without a depth bound.",
"reason": "src/parser.ts:88 enforces MAX_DEPTH before recursion; the bounded local fixture at depth 10000 returns a handled error."
}
Esa línea te ahorra la discusión dentro de seis meses, cuando otro agente proponga lo mismo y el registro previo le diga que ya se miró y por qué no era.
Resumen de lo que sale por el otro lado ¶
| Artefacto | Qué contiene |
|---|---|
REPORT.md |
Perfil, alcance, presupuesto gastado, tabla de confirmados, tabla separada de needs_validation, notas de endurecimiento y resumen de cobertura |
FINDINGS-DETAIL.md |
Traza completa y reproducción acotada de cada confirmado medio, alto o crítico |
NEEDS-VALIDATION.md |
Pistas priorizadas sin severidad, con su bloqueador exacto y su plan |
findings.json |
Los tres veredictos en formato legible por máquina, validado contra esquema |
coverage-ledger.json |
La afirmación de cobertura, unidad por unidad |
architecture.md |
El mapa del sistema y sus fronteras, con tope de 1.000 palabras |
Si no encuentra nada, el informe lo dice y explica los límites de cobertura restantes. La skill lo escribe con todas las letras: una ejecución limpia puede tener cero confirmados; no te inventes hallazgos LOW para rellenar.
¿Qué no hace esta skill? ¶
Toca la parte incómoda.
No arregla tu código. Describe el cambio mínimo que impone el invariante y propone un caso de regresión, pero no toca el código del objetivo. La decisión y la implementación siguen siendo tuyas.
No prueba contra sistemas vivos. Nada de endpoints desplegados, servicios externos, infraestructura compartida, identidades de producción ni planos de control. Si el hecho decisivo está fuera del código y del fixture aislado, se reporta como pendiente de validación. Punto.
No sustituye a un SAST ni a un pen-test humano. Es una capa más, no la última palabra. Complementa bien a herramientas como Warden para el diff del pull request y al plugin security-guidance para el código que el agente escribe mientras trabaja.
Cuesta invocaciones de agente. Cada unidad de cobertura es aproximadamente un cazador, y cada candidato superviviente son uno o dos verificadores según el perfil. En un repositorio grande con perfil deep esto no es barato. De ahí que el presupuesto sea un campo de primera clase.
Tiene falsos negativos declarados. La mitad de los bugs en la primera pasada, recuerda. La skill te pide que ejecutes varias veces y que aproveches el libro de cobertura previo para atacar huecos, revalidar código cambiado y no dar por cubierto lo que quedó bloqueado.
Depende de que tu entorno soporte el sandbox. Sin esos controles no se ejecuta nada del objetivo y muchas pistas se quedan en needs_validation. Sigue siendo útil, pero recibes hipótesis en lugar de resultados observados.
¿Cómo encaja en tu flujo de trabajo real? ¶
Tal como está pensada, no es una herramienta de cada commit. Es una herramienta de hito: antes de abrir un producto al público, antes de una release importante, cuando heredas un repositorio que no conoces, o cuando quieres saber qué tan sólido es el aislamiento de datos antes de firmar un contrato que lo exige.
Un orden que funciona:
- Primera ejecución con perfil
quicksobre el subsistema que más te preocupa, para calibrar coste y ver la forma de la salida. - Lectura del
coverage-ledger.jsonantes que del informe. Ahí ves qué se miró de verdad y qué quedó aplazado. - Segunda ejecución con perfil
standardsobre el repositorio completo, aprovechando el libro anterior. - Triaje humano de
NEEDS-VALIDATION.md: esas son las preguntas que solo tú o quien opera el despliegue podéis responder. - Repetición periódica, porque el libro acumula y cada pasada ataca lo que la anterior dejó abierto.
Es más trabajo que pedirle a un modelo que te haga una lista. También es la diferencia entre una lista y una auditoría.
🛡️ Antes de lanzar la primera ejecución, comprueba que tu directorio de salida está fuera del repositorio. La skill lo verifica, pero es la clase de detalle que agradeces tener claro desde el minuto uno.
Auditar con agentes, verificar lo que afirman, medir la cobertura real... el oficio está cambiando rápido. En la newsletter de Web Reactiva compartimos cada domingo lo que vamos probando entre +7.200 developers.
Suscríbete gratis →Preguntas frecuentes sobre la security-audit skill de Cloudflare ¶
¿Qué es la security-audit skill de Cloudflare?
Es una Agent Skill open source con licencia MIT que convierte a un agente de codificación en auditor de seguridad. Orquesta agentes aislados a través de seis fases (reconocimiento, caza guiada por cobertura, validación de candidatos, salida estructurada, verificación independiente e informe) y produce hallazgos legibles por máquina validados contra un esquema JSON. Es la semilla del harness de descubrimiento de vulnerabilidades de Cloudflare.
¿Cómo se instala la skill security-audit?
Con el CLI de skills.sh: npx skills add https://github.com/cloudflare/security-audit-skill --skill security-audit. Añade --global para una instalación a nivel de usuario. No requiere configuración adicional más allá de tener Node.js disponible para los validadores.
¿Funciona con agentes distintos a Claude Code?
Sí. La skill está escrita de manera agnóstica: habla de “parent” para el agente coordinador, “Task tool” para el mecanismo de delegación y de dos roles de subagente (research y general). Cualquier agente cuyo modelo soporte tool use y subagentes en paralelo puede ejecutarla usando sus capacidades equivalentes.
¿Necesito un sandbox obligatoriamente?
Para inspección de código, no: eso es solo lectura. Para ejecutar builds, tests, procesos, navegadores o fuzzers del objetivo, sí, y con condiciones estrictas: sin red externa, entorno vacío desde lista blanca, objetivo en solo lectura, escritura solo en el scratch asignado y límites explícitos de CPU, memoria, procesos y tiempo. Si falta cualquier control, la skill no ejecuta y marca la pista como pendiente de validación.
¿Qué diferencia hay entre confirmed y needs_validation?
Un registro confirmed tiene traza de código completa, resultado observado acotado y severidad asignada. Un needs_validation es una hipótesis fundamentada en código bloqueada por un hecho exacto que no se puede observar desde el repositorio, y no lleva severidad. No es una vulnerabilidad de baja confianza: es una pregunta concreta pendiente de respuesta.
¿Cuántas clases de ataque cubre?
162 clases nombradas: 9 clases ordinarias en ATTACK-CLASSES.md que aplican a casi cualquier objetivo, más 153 repartidas en diez ficheros de dominio que se seleccionan según las fronteras de confianza que encuentre el reconocimiento (memoria y binario, HTTP y autenticación, cliente, IA y LLM, nube, cadena de suministro, protocolos, agotamiento de recursos, aislamiento de datos, y escritorio/móvil/IPC local).
¿Una sola ejecución basta para auditar un repositorio?
No, y la propia skill lo declara. En las pruebas de Cloudflare, una sola pasada encontró aproximadamente la mitad de las vulnerabilidades que las pasadas repetidas encontraron en total, y las de la primera pasada tendían a ser las más simples. Las ejecuciones son acumulativas: la skill lee libros de cobertura y hallazgos previos para atacar huecos y revalidar código cambiado.
¿Modifica mi código o abre pull requests?
No. La auditoría describe la corrección mínima que impone el invariante y sugiere un caso de regresión, pero no toca el código del objetivo. Tampoco escribe dentro del repositorio auditado salvo que elijas de forma explícita un directorio que el control de versiones ignore.
¿Sirve para auditar aplicaciones con LLM y servidores MCP?
Sí, y es uno de sus puntos fuertes. El fichero AI-AND-LLM.md cubre inyección indirecta por contenido recuperado, envenenamiento de memoria persistente, inyección de argumentos de herramientas hacia sinks, agencia excesiva, confusión de identidad entre servidores MCP y metadatos tratados como política. Su regla de partida es que la inyección de prompt por sí sola no es un hallazgo sin un fallo de frontera a nivel de código.
¿Cuánto cuesta ejecutar una auditoría completa?
Depende del tamaño del repositorio y del perfil. Como regla, una unidad de cobertura equivale a un cazador y cada candidato superviviente a uno o dos verificadores. La skill acepta un presupuesto máximo de invocaciones de agente y lo reparte reservando primero críticos y validación; si el presupuesto no cubre el mínimo, no lanza ningún agente y te pide reducir el alcance o cambiar de perfil.
Fuentes y enlaces ¶
- cloudflare/security-audit-skill en GitHub — El repositorio completo con los 20 ficheros, el esquema y los validadores
- Build your own vulnerability harness — El artículo del blog de Cloudflare donde cuentan cómo la skill inicial creció hasta convertirse en un sistema multifase para toda su flota
- skills.sh — El CLI con el que se instala la skill en cualquier agente compatible
La pregunta que deja esta skill sobre la mesa no es si la IA puede encontrar vulnerabilidades. Ya sabemos que puede, a ratos y con suerte.
La pregunta es si estás dispuesto a montarle alrededor la disciplina que hace que sus hallazgos se puedan defender delante de alguien: una frontera nombrada, una traza con fichero y línea, un resultado observado y un verificador que no sea el mismo que lo encontró.
Ahí es donde deja de ser un juguete.
🧨 Cada domingo, una dosis de dinamita sobre programación con IA en tu correo. Suscríbete gratis a Web Reactiva en https://webreactiva.com/newsletter
12 recursos para developers cada domingo en tu bandeja de entrada
Además de una skill práctica bien explicada, trucos para mejorar tu futuro profesional y una pizquita de humor útil para el resto de la semana. Gratis.