====== 15. Herramientas deterministas ====== El código que escribe la IA es **estocástico**: el mismo prompt da cada vez un código distinto, y si le pedimos a otra IA que lo revise, la revisión también lo es. Un día detecta el //bug// y al siguiente no. Las herramientas de este tema son lo contrario: **analizadores deterministas**. Sobre el mismo código dan siempre el mismo informe, con reglas conocidas, y terminan con un código de salida que dice si pasa o no. Por eso se meten en el bucle del agente como un **sensor**: el agente escribe, lanza la herramienta, lee el informe, corrige y vuelve a lanzarla hasta que pasa. La IA revisa lo que no se puede escribir como regla; lo que sí se puede, lo comprueba la herramienta. ^ Herramienta ^ Qué comprueba ^ Dónde se usa en el curso ^ | [[#sonarqubecalidad_del_codigo|SonarQube]] | Calidad: //bugs//, //code smells//, duplicación, cobertura, complejidad | Servidor local en Docker y ''./mvnw sonar:sonar'' | | [[#snykvulnerabilidades_en_el_codigo_y_en_las_dependencias|Snyk]] | Seguridad: vulnerabilidades en el código propio y en las dependencias | CLI ''snyk'' | | [[#aikido_safe_chainque_el_agente_no_instale_malware|Aikido Safe Chain]] | Que no se instale un paquete con //malware// | Envuelve ''npm'', ''npx'', ''pip'', ''uv''... | Aikido también analiza el código y las dependencias, igual que Snyk. Para eso en el curso se usa Snyk, que se lanza desde la terminal; de Aikido se usa Safe Chain, que no tiene equivalente. ---- ===== 1. SonarQube: calidad del código ===== [[https://www.sonarsource.com/products/sonarqube/|SonarQube]] analiza el proyecto con miles de reglas por lenguaje y lo compara con una **//quality gate//**: un conjunto de condiciones que el código nuevo tiene que cumplir. La que trae por defecto, //Sonar way//, pide sobre el código nuevo: * **0 incidencias nuevas**. * **Cobertura** de tests de al menos el 80 %. * **Duplicación** de como mucho el 3 %. * Todos los **//security hotspots//** revisados. Es justo lo que se le escapa a la IA: el método copiado y pegado con un cambio, la clase de 600 líneas, el código nuevo sin test. ==== Arrancar el servidor ==== La //Community Build// es gratuita y se arranca en local con Docker: docker run -d --name sonarqube -p 9000:9000 sonarqube:community * En ''http://localhost:9000'' se entra con ''admin''/''admin'' y obliga a cambiar la contraseña. * El //token// para analizar se crea en //My Account → Security → Generate Tokens//, de tipo //Global Analysis Token//. Se guarda en la variable ''SONAR_TOKEN''. ==== Analizar el proyecto ==== * Spring Boot (Maven): ./mvnw verify sonar:sonar -Dsonar.host.url=http://localhost:9000 -Dsonar.token=$SONAR_TOKEN -Dsonar.qualitygate.wait=true * Angular: npx @sonar/scan -Dsonar.host.url=http://localhost:9000 -Dsonar.token=$SONAR_TOKEN -Dsonar.projectKey=pedidos-web -Dsonar.qualitygate.wait=true Las piezas: * **''verify''**: compila y pasa los tests antes de analizar. Sin él, Sonar no tiene los resultados de los tests. * **''-Dsonar.qualitygate.wait=true''**: espera a que el servidor evalúe la //quality gate// y, si no pasa, **la orden falla**. Es lo que la convierte en una puerta para el agente: no tiene que interpretar nada, mira el código de salida. * **''-Dsonar.projectKey''**: el nombre del proyecto en el servidor. En Maven no hace falta: usa el ''groupId:artifactId'' del ''pom.xml''. **Sin JaCoCo la cobertura sale al 0 %** y la //quality gate// falla en cuanto hay código nuevo. Sonar no ejecuta los tests: lee el informe XML que deja JaCoCo. El proyecto tiene que tener el ''jacoco-maven-plugin'' con el objetivo ''report'' en la fase ''verify''. ==== Que el agente lea las incidencias ==== Cuando la puerta falla, el agente necesita saber **qué** ha fallado. No hace falta un MCP: la API web lo da con ''curl''. curl -s -H "Authorization: Bearer $SONAR_TOKEN" "http://localhost:9000/api/issues/search?components=es.fpmislata:pedidos&resolved=false&ps=100" Y se le dice en ''AGENTS.md'' cuándo usarlo: - Antes de dar una tarea por terminada, ejecuta `./mvnw verify sonar:sonar -Dsonar.host.url=http://localhost:9000 -Dsonar.token=$SONAR_TOKEN -Dsonar.qualitygate.wait=true`. - Si falla, consulta las incidencias con `curl -s -H "Authorization: Bearer $SONAR_TOKEN" "http://localhost:9000/api/issues/search?components=es.fpmislata:pedidos&resolved=false&ps=100"`, corrígelas y vuelve a lanzarlo. No marques una incidencia como falso positivo: dímelo. **No dejes que el agente cambie la //quality gate// ni marque incidencias como aceptadas o falsos positivos.** Es la forma más rápida de que «pase»: bajar el listón en vez de arreglar el código. Su //token// es de análisis, no de administrador. ---- ===== 2. Snyk: vulnerabilidades en el código y en las dependencias ===== [[https://snyk.io|Snyk]] busca **vulnerabilidades de seguridad** en dos sitios distintos, cada uno con su orden: * **''snyk code test''** (SAST): el código que hemos escrito. Inyección SQL, //XSS//, //path traversal//, secretos escritos en el código... * **''snyk test''** (SCA): las dependencias del ''pom.xml'' o el ''package.json'', y las que arrastran. La librería que la IA ha puesto en una versión con un CVE conocido porque es la que recordaba. Se instala y se autentica una vez (el plan gratuito vale, con un límite de análisis al mes): npm install -g snyk snyk auth Y se lanza desde la raíz del proyecto: snyk code test --severity-threshold=medium snyk test --severity-threshold=medium * **''--severity-threshold=medium''**: solo informa, y solo falla, por lo de severidad media o más. Las de severidad baja son sobre todo ruido. * **Código de salida**: ''0'' sin vulnerabilidades, ''1'' con vulnerabilidades, ''2'' o ''3'' si el análisis no ha podido hacerse. Igual que con Sonar, el agente no interpreta: mira si ha salido ''0''. **''snyk test'' necesita el proyecto compilado**: en Maven, que las dependencias estén resueltas (''./mvnw install'' al menos una vez); en Angular, el ''package-lock.json''. Si no, termina con ''2'' o ''3'' y el agente puede tomarlo por «no hay nada». La regla en ''AGENTS.md'' es la que recomienda la propia Snyk, adaptada a la terminal: - Después de escribir o modificar código, ejecuta `snyk code test --severity-threshold=medium`. - Después de añadir o cambiar una dependencia, ejecuta `snyk test --severity-threshold=medium`. - Si encuentra vulnerabilidades en lo que has escrito o añadido, corrígelas y repite hasta que no haya ninguna nueva. Si termina con código 2 o 3, el análisis no se ha hecho: dímelo. ---- ===== 3. Aikido Safe Chain: que el agente no instale malware ===== Los modelos se inventan nombres de paquetes que suenan bien, y hay quien registra esos nombres en npm o PyPI con //malware// dentro esperando a que un agente los instale (//slopsquatting//). Un agente con permiso para ejecutar ''npm install'' lo instala sin que nadie lo vea. [[https://github.com/AikidoSec/safe-chain|Aikido Safe Chain]] se pone delante de ''npm'', ''npx'', ''yarn'', ''pnpm'', ''bun'', ''pip'', ''uv'' y ''poetry'' y **bloquea la descarga** de cualquier paquete marcado como //malware//. También rechaza las versiones publicadas hace menos de 48 horas, que es cuando se cuelan las versiones comprometidas de paquetes legítimos. Es gratuito y no necesita cuenta. curl -fsSL https://github.com/AikidoSec/safe-chain/releases/download/1.5.26/install-safe-chain.sh -o /tmp/install-safe-chain.sh \ && echo "9e4af7107f06d9c0d758cb08fb36804c2af88e24972f3a9d3f8c2bd0ca002adf /tmp/install-safe-chain.sh" | sha256sum -c - \ && sh /tmp/install-safe-chain.sh \ && rm /tmp/install-safe-chain.sh Para comprobar que funciona, este paquete de prueba tiene que quedar bloqueado: npm install safe-chain-test **Compruébalo desde el agente, no solo desde tu terminal.** Safe Chain se engancha con alias en el ''.bashrc'' o el ''.zshrc'', y la //shell// en la que el agente ejecuta órdenes no siempre los carga. Pídele que ejecute ''npm safe-chain-verify'': tiene que responder ''OK: Safe-chain works!''. Si no, el agente instala sin protección aunque en tu terminal funcione. ---- ===== Más información ===== * [[https://docs.sonarsource.com/sonarqube-server/|SonarQube Server]]: instalación, //quality gates// y la API web (''/api/issues/search''). * [[https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/scanners/sonarscanner-for-maven|SonarScanner for Maven]]: todos los parámetros ''-Dsonar.*''. * [[https://docs.snyk.io/developer-tools/snyk-cli|Snyk CLI]]: ''snyk code test'', ''snyk test'' y sus opciones. * [[https://docs.snyk.io/agent-security/agentic-security-with-snyk-studio/directives|Snyk Studio: directives]]: las reglas que recomienda Snyk para los agentes. * [[https://github.com/AikidoSec/safe-chain|Aikido Safe Chain]]: gestores de paquetes soportados, modo CI y configuración de la antigüedad mínima. * [[https://www.aikido.dev|Aikido]]: la plataforma completa (SAST, SCA, secretos, contenedores) conectada al repositorio. ---- ===== Ejercicios ===== ==== Ejercicio 1 ==== Arranca SonarQube en Docker y analiza un proyecto Spring Boot que hayas hecho con el agente. Rellena la tabla con lo que da el primer análisis: ^ Métrica ^ Valor ^ | //Bugs// | | | //Code smells// | | | Vulnerabilidades | | | //Security hotspots// | | | Cobertura | | | Duplicación | | ==== Ejercicio 2 ==== Añade al ''AGENTS.md'' la regla de Sonar y pide al agente una funcionalidad nueva. Comprueba que lanza el análisis antes de terminar y que, si la //quality gate// falla, corrige hasta que pasa. Anota cuántas vueltas ha dado y qué incidencias ha corregido. ==== Ejercicio 3 ==== Lanza ''snyk test'' y ''snyk code test'' sobre el mismo proyecto. Para cada vulnerabilidad de severidad media o más, anota si está en el código o en una dependencia y cómo se corrige. ==== Ejercicio 4 ==== Instala Safe Chain y comprueba con ''npm safe-chain-verify'' que funciona **desde el agente**. Después pídele que instale ''safe-chain-test'' y copia lo que responde.