Inicio / Artículos / Siete herramientas de código abierto para auditar código generado por IA antes de producción

Siete herramientas de código abierto para auditar código generado por IA antes de producción

Siete proyectos de GitHub, de las pruebas de mutación a las de carga, que revisan la calidad de los tests, los secretos filtrados, las dependencias, la accesibilidad y la velocidad de las apps hechas con IA.

941 palabras

Tu asistente de programación te dice que el trabajo está terminado, los tests están en verde y la app funciona en la vista previa. Parece que ya está. Normalmente no lo está.

Una ejecución de tests en verde solo demuestra que los tests pasaron. Si esos tests fallarían ante una implementación rota es otra cuestión. Igual que otras cuantas: ¿se coló alguna credencial en un commit?, ¿los paquetes que has añadido están libres de fallos conocidos?, ¿qué pasa cuando cincuenta personas abren la app a la vez? Un asistente rara vez responde a esto por iniciativa propia.

Siete herramientas de código abierto cubren esos huecos, cada una desde un ángulo distinto: la solidez de los tests, los secretos filtrados, las dependencias vulnerables, los patrones de código, el código muerto, la accesibilidad y la carga. Varias apuntan a JavaScript y TypeScript, así que encajan especialmente bien con las apps web hechas con IA. Pásalas antes de que nada llegue a producción.

StrykerJS: ¿tus tests muerden de verdad?

StrykerJS es un framework de pruebas de mutación para JavaScript y TypeScript. Hace pequeños cambios deliberados en tu código fuente, como invertir una comparación o borrar una sentencia, y vuelve a ejecutar la batería de tests cada vez. Si después del cambio todos los tests siguen pasando, esa batería tiene un punto ciego. Los porcentajes de cobertura no pueden mostrarlo, porque una línea puede ejecutarse sin que nada la compruebe nunca.

En un proyecto pequeño puedes probarlo enseguida:

pnpm add --save-dev @stryker-mutator/core
# Only for small projects:
npx stryker run

Sin configuración, recurre a valores por defecto razonables. Ejecuta npm test como comando de tests y busca código que mutar en lib y src.

Gitleaks: caza los secretos a tiempo

Gitleaks analiza archivos y el historial de Git en busca de credenciales como claves de API y tokens. Puedes ejecutarlo a mano o integrarlo en una pipeline automatizada, que frena una clave filtrada antes de que se extienda por clones y forks. El código generado es una fuente habitual de este problema, ya que un modelo pega sin reparos una clave de ejemplo que resulta ser real.

Para descargarlo y compilarlo:

git clone https://github.com/gitleaks/gitleaks.git
cd gitleaks
make build

OSV-Scanner: sabe de qué dependes

OSV-Scanner compara los paquetes de tus lockfiles con la base de datos de vulnerabilidades OSV. Indica cuáles de tus versiones exactas tienen avisos publicados y te da una imagen concreta del riesgo que introducen las dependencias. Los asistentes suelen añadir librerías sin pensarlo dos veces, así que esta comprobación se amortiza rápido.

Puedes compilarlo con Go:

go install github.com/google/osv-scanner/v2/cmd/osv-scanner@latest

Semgrep: análisis estático con reglas

Semgrep es un analizador estático de código abierto y rápido. Busca patrones en el código para encontrar bugs, señalar construcciones inseguras y hacer cumplir las convenciones de tu equipo. Entiende más de treinta lenguajes y funciona en el editor, como hook de pre-commit o dentro de un job de CI/CD.

Se instala con pip:

 python3 -m pip install semgrep

Knip: borra lo que nadie usa

Knip encuentra en proyectos de JavaScript y TypeScript archivos, dependencias y exports a los que nada hace referencia. El código generado acumula restos enseguida: helpers abandonados, paquetes que se añadieron y nunca se importaron. Limpiarlos reduce la carga de mantenimiento y hace que el repositorio se lea mejor a medida que crece.

axe-core: comprobaciones de accesibilidad

axe-core es un motor de pruebas de accesibilidad para páginas web y otras interfaces basadas en HTML. Es rápido y ligero, y se conecta a cualquier configuración de tests que ya tengas, de modo que las aserciones de accesibilidad pueden convivir con las funcionales de siempre. Los asistentes tienden a generar marcado que parece correcto pero al que le faltan etiquetas, roles y contraste, y así es como te das cuenta.

k6: ¿cómo se comporta bajo carga?

k6 es una herramienta de pruebas de carga. Describes escenarios en código, mides tiempos de respuesta y tasas de error, y fijas umbrales que hacen fallar una ejecución automáticamente cuando el rendimiento empeora. Un ejemplo pequeño:

import http from "k6/http";
import { check, sleep } from "k6";

// Test configuration
export const options = {
  thresholds: {
    // Assert that 99% of requests finish within 3000ms.
    http_req_duration: ["p(99) < 3000"],
  },
  // Ramp the number of virtual users up and down
  stages: [
    { duration: "30s", target: 15 },
    { duration: "1m", target: 15 },
    { duration: "20s", target: 0 },
  ],
};

// Simulated user behavior
export default function () {
  let res = http.get("https://quickpizza.grafana.com");
  // Validate response status
  check(res, { "status was 200": (r) => r.status == 200 });
  sleep(1);
}

El script simula diez usuarios virtuales durante treinta segundos, y cada uno hace una pausa de un segundo entre peticiones. Sus umbrales exigen que el percentil 95 del tiempo de respuesta se mantenga por debajo de 500 ms y que fallen menos del 1% de las peticiones.

Guarda el archivo como test.js, instala k6 y lánzalo con k6 run test.js.

Juntándolo todo

Ninguna de estas herramientas demuestra que tu app sea correcta, ni lo pretende. Juntas cubren las preguntas que una demo exitosa se salta. Empieza con Gitleaks y OSV-Scanner, que llevan minutos y detectan los errores más caros. Después añade Stryker y Semgrep para revisar el propio código, Knip para podarlo, axe-core para la accesibilidad y k6 para el tráfico. Si otra herramienta de código abierto merece estar en tu lista, añádela. El objetivo es siempre el mismo: confía en el resultado solo después de que algo haya intentado romperlo.