OpenAI liberó su CLI de seguridad: así lo pones a escanear tu repo y a cortar tu CI

OpenAI liberó su CLI de seguridad: así lo pones a escanear tu repo y a cortar tu CI

Durante un mes, el issue #29878 en openai/codex estuvo abierto con una observación incómoda adjunta. Codex CLI es Apache-2.0, todo el proyecto, auditable. Pero el plugin codex-security que instalaba en las máquinas de los developers era otra cosa: "license": "Proprietary", directo del manifest, distribuido a través del marketplace curado de OpenAI y apuntando a un repositorio que nadie fuera podía abrir. El reclamo no era filosófico. Era que un binario cerrado se estaba instalando en tu sistema, mediante una herramienta abierta, para leer tu código fuente.

Ese issue sigue abierto. Pero desde esta semana existe lo que pedía: github.com/openai/codex-security, público, Apache-2.0, 98 commits en main, con un CLI, un SDK de TypeScript, un Dockerfile y un compose.yaml para escaneos masivos. OpenAI no lo anunció primero — lo dijeron ellos mismos en X: “we quietly released the open-source Codex Security CLI, but Hacker News found it before we had a chance to share it here.”

El release se mueve rápido. npm pasó de 0.1.0 a 0.1.4 en unas 55 horas: 0.1.0 y 0.1.1 el 28 de julio, 0.1.2 y 0.1.3 el 29, 0.1.4 en la madrugada del 30. Si estás leyendo un tutorial escrito hace un día, revisa la versión.

Antes de instalar: dos requisitos y una restricción

El README es explícito: Node.js 22 o superior, Python 3.10 o superior. La parte de Python sorprende — es un paquete de npm, nadie espera necesitar un intérprete, pero tanto el escaneo como la exportación de findings pasan por ahí. Si tu primer npx se muere, normalmente es por eso.

El tercer requisito es el que decide si esto es para ti. La autenticación funciona de dos formas: --auth chatgpt, facturando contra tu plan de ChatGPT, o --auth api-key, facturando contra la API. Y según el propio help center de OpenAI, Codex Security todavía es un research preview disponible para ChatGPT Enterprise, Edu, Business y Pro — así que la ruta de ChatGPT está limitada por tier de plan. Si tienes una cuenta Plus personal, el camino práctico es una API key.

Vale decirlo sin rodeos, porque condiciona todo lo que sigue: el código es abierto, el scanner no es gratis. Cada scan es inferencia de modelo, y alguien la paga.

El primer scan

npm install @openai/codex-security
npx codex-security login
npx codex-security scan .

login te lleva por credenciales de ChatGPT o una API key. scan . corre contra el repositorio actual y escribe los resultados en un directorio de scan; el historial vive en el state directory del workbench de Codex Security, y si esa ubicación no es escribible en tu entorno — contenedores, runners de CI, laptops con permisos restringidos — configura CODEX_SECURITY_STATE_DIR apuntando a una que sí lo sea.

Lo que recibes de vuelta no es un grep de patrones sospechosos. La propuesta del repo es “finding, validating, and fixing” — y la parte de validating es la interesante, porque el modo de fallo histórico del tooling de seguridad automatizado no es que se le escapen bugs, es que te ahoga en findings que no son reales.

Cómo hacer que bloquee tus commits

npx @openai/codex-security install-hook

Esto instala un hook de pre-commit que escanea los cambios staged y unstaged antes de cada commit, y bloquea ante findings de severidad alta o ante un scan que falló directamente. Dos detalles que importan si alguna vez te quemaste con un instalador de hooks: respeta core.hooksPath y no reemplaza un hook existente.

Sé honesto contigo mismo respecto a la latencia. Un hook que llama a un modelo en cada commit no cuesta lo mismo que uno que corre eslint. Pruébalo un día antes de imponérselo al equipo.

Seguirle el rastro a los findings entre corridas

Esta es la parte que lo separa de un scanner de una sola pasada. Cada scan queda guardado, y puedes razonar sobre los deltas entre uno y otro:

npx @openai/codex-security scans list "$REPOSITORY"
npx @openai/codex-security scans match PREVIOUS_SCAN_ID CURRENT_SCAN_ID
npx @openai/codex-security scans compare PREVIOUS_SCAN_ID CURRENT_SCAN_ID

match vincula findings que comparten la misma root cause entre dos scans — el problema difícil, porque los números de línea se mueven y un refactor puede hacer que el mismo bug parezca completamente nuevo. compare lee esos matches guardados y clasifica cada finding como new, persisting, reopened, resolved o unknown.

La categoría que vale la pena mirar fijo es “reopened”. Significa que una vulnerabilidad que ya habías corregido volvió, que es exactamente el tipo de regresión que la revisión manual de seguridad nunca detecta y que un scanner sin estado reporta como si fuera novedad.

El bloque de CI

Aquí es donde el release se gana el lugar. Del propio CI guide de OpenAI, el paso de scan en GitHub Actions:

"$CODEX_SECURITY_BIN" scan . \
  --diff "$BASE_REVISION" \
  --head "$HEAD_SHA" \
  --auth api-key \
  --output-dir "$SCAN_DIR" \
  --json > "$RUNNER_TEMP/codex-security.json"

Fíjate en --diff y --head: en CI escaneas los cambios del pull request, no el repositorio completo. Eso es lo que mantiene el costo soportable.

Después, la política de severidad:

--fail-on-severity high

Los valores aceptados son critical, high, medium, low, y un umbral incluye esa severidad y las superiores. Con eso, un scan completado que contenga un finding calificado sale con exit 1 y tu pipeline se pone en rojo.

Y la exportación a SARIF, que es la forma en que los findings llegan a GitHub code scanning o a cualquier cosa que hable ese formato:

"$CODEX_SECURITY_BIN" export "$SCAN_DIR" \
  --export-format sarif \
  --source-root "$GITHUB_WORKSPACE" \
  --output "$SARIF_FILE"

El workflow instala una versión pineada con --ignore-scripts --no-audit --no-fund dentro de $RUNNER_TEMP, y mapea OPENAI_API_KEY desde un secret del repositorio — una credencial acotada para CI en lugar de tu login personal. Pinea la versión. Este proyecto sacó cinco releases en tres días.

Escanear muchos repositorios de una vez

Si eres la persona responsable de más de un codebase, existe el camino de Docker:

docker compose run --rm codex-security \
  bulk-scan /input/repositories.csv \
  --output-dir /output \
  --workers 4

Le pasas un CSV de repositorios y los recorre de forma no interactiva, dentro de un sandbox endurecido para el comando de Codex. Este es el caso de uso de inventario a nivel organización, y es donde la pregunta sin responder que viene abajo deja de ser curiosidad y se convierte en una línea de presupuesto.

El número que nadie está publicando

Ni el README ni el help center dicen cuánto cuesta un scan. Ni precio por repositorio, ni estimación de tokens, ni un orden de magnitud aproximado. Y con --workers 4 masticando un CSV de repositorios, eso no es un detalle — es toda la pregunta de si puedes correr esto semanalmente o una vez por trimestre.

Así que mídelo antes de comprometerte. Corre un scan completo contra un repositorio cuyo tamaño conozcas, revisa tu dashboard de uso de la API inmediatamente antes y después, y anota el número. Después corre la variante con --diff sobre un pull request normal y anota ese también. Esos dos números son los que realmente determinan tu política de CI, y hoy solo puedes obtenerlos generándolos tú mismo.

Esa es además la cosa más útil que puedes publicar sobre este release. Todo el mundo puede reportar que cambió la licencia. Casi nadie está reportando cuánto cuesta un scan.


¿Ya corriste un scanner de seguridad contra tus propios repositorios en CI — y qué te hizo apagarlo, los falsos positivos o la factura?