Ne vous fiez pas au nombre de lignes de votre dépôt pour estimer la facture. J’ai lancé le nouveau Codex Security CLI sur un unique fichier Express de neuf lignes ; huit minutes et demie plus tard, le scan s’est arrêté sur un plafond de 6,00 $, après avoir consommé 7,0 millions de tokens d’entrée pour produire un modèle de menaces de 1 605 mots et zéro détection. Pour qui envisage de l’intégrer à une CI, c’est l’essentiel : le coût dépend de la boucle de raisonnement de l’agent, pas de la taille du code. Configurez donc --max-cost avant tout le reste.
L’outil mérite néanmoins qu’on s’y intéresse : c’est la première version de Codex Security exécutable sans confier son dépôt à une GitHub App.
Ce que fait réellement le CLI
Codex Security n’est pas une nouveauté. OpenAI l’a lancé en aperçu de recherche en mars 2026 sous la forme d’un service hébergé : vous connectez un dépôt GitHub, le service construit un modèle de menaces, examine l’historique des commits dans un environnement isolé, puis remonte ses détections dans un espace de travail ChatGPT. SecurityWeek indiquait une disponibilité pour les clients ChatGPT Pro, Enterprise, Business et Edu.
La publication du 28 juillet 2026 change l’approche. openai/codex-security est un CLI et SDK TypeScript sous licence Apache-2.0, publié sur npm en version 0.1.0 à 17:09 UTC, puis en version 0.1.1 à 23:48 UTC le même jour. Au moment de la rédaction, le projet affiche 1,8 k étoiles et 28 issues ouvertes. C’est un projet tout juste sorti.
L’installation requiert Node.js 22 ou plus récent et Python 3.10 ou plus récent, car le moteur de scan est fourni sous la forme d’un plugin Python embarqué :
npm install @openai/codex-security
npx codex-security info
La commande info permet de vérifier immédiatement les composants installés :
sdkVersion: 0.1.1
bundledPluginVersion: 0.1.14
cliVersion: 0.1.1
codexVersion: 0.144.6
model: gpt-5.6-sol
reasoningEffort: xhigh
Les deux dernières lignes résument à elles seules le sujet du coût. Dans cette installation, les scans utilisent par défaut GPT-5.6 Sol avec un effort de raisonnement xhigh. L’option --model permet de changer de modèle, mais le plugin repose avant tout sur une boucle agentique approfondie. C’est cette boucle que vous payez.
La surface de commandes est plus large que ne le laisse penser le produit hébergé : scan, validate, patch, scans pour lister, afficher, relancer, comparer ou faire correspondre les scans, bulk-scan, export vers CSV, JSON ou SARIF, install-hook, ainsi qu’un mode mcp qui enregistre l’outil comme serveur MCP. À noter : info indique également scanMcp: false, car les scans ne peuvent pas être annulés via le transport MCP.
Deux méthodes d’authentification, dont une vraie barrière
npx codex-security login ouvre une session avec un compte ChatGPT, --device-auth couvre les machines sans interface, et OPENAI_API_KEY sert pour la CI. Si une clé API et une session sont toutes deux présentes, les scans interactifs demandent laquelle utiliser ; les exécutions non interactives privilégient la clé API.
Un avertissement de la documentation officielle mérite une attention particulière : les scans de dépôt complet peuvent aussi nécessiter Trusted Access for Cyber. Ni la connexion au compte ni la configuration d’une clé API ne l’accordent. Prévoyez donc une demande d’accès, pas simplement une étape de connexion.
Utiliser l’OpenAI Codex Security CLI avec un endpoint compatible
La première erreur consiste à définir OPENAI_API_KEY avec une clé tierce en s’attendant à ce que le trafic soit automatiquement redirigé :
codex-security: Authentication failed using OPENAI_API_KEY.
La clé seule ne redirige rien : le runtime Codex embarqué cible toujours l’URL de base d’OpenAI et ignore OPENAI_BASE_URL. Il faut surcharger la configuration du fournisseur avec --codex, qui accepte des valeurs TOML :
OPENAI_API_KEY=sk-... npx codex-security scan . --auth api-key --max-cost 5 \
--codex 'model_provider="relay"' \
--codex 'model_providers.relay.name="relay"' \
--codex 'model_providers.relay.base_url="https://your-endpoint/api/v1"' \
--codex 'model_providers.relay.env_key="OPENAI_API_KEY"' \
--codex 'model_providers.relay.wire_api="responses"'
Deux détails m’ont chacun coûté une exécution. Sans guillemets, les valeurs échouent avec Invalid --codex TOML value. Et wire_api="chat" est tout simplement refusé par Codex 0.144.6, avec une erreur renvoyant vers la discussion #7782 et demandant d’utiliser responses. Votre endpoint doit donc implémenter la Responses API, pas uniquement Chat Completions.
Cette même configuration détermine où atterrit la facture du modèle. Le CLI estime systématiquement les coûts avec les tarifs catalogue d’OpenAI pour GPT-5.6 Sol, quel que soit l’endpoint ciblé : son total progressif est donc un calcul basé sur les tokens, et non votre facture réelle. Faites passer le même trafic par un endpoint facturé à la moitié du tarif catalogue et l’exécution à 6,03 $ ci-dessous vous coûtera environ 3 $, tandis que le CLI continuera d’afficher 6,03 $.
Le prix d’un seul scan
Ces chiffres sont assortis d’une condition importante : les cinq exécutions sont passées par des endpoints tiers compatibles OpenAI, car je ne disposais pas d’une connexion ChatGPT Business ou Enterprise pour tester le parcours officiel. Les résultats mesurent donc le CLI tel qu’un développeur ordinaire peut l’utiliser aujourd’hui, et non le comportement du service hébergé avec un compte autorisé.
Le dépôt de test est volontairement minuscule et vulnérable. Neuf lignes, quatre failles introduites délibérément :
const express = require('express');
const { exec } = require('child_process');
const db = require('./db');
const app = express();
const API_KEY = "sk-live-9f3a2b7c1d4e5f6a8b9c0d1e2f3a4b5c";
app.get('/u', (req, res) => db.query("SELECT * FROM users WHERE id = " + req.query.id, (e, r) => res.json(r)));
app.get('/ping', (req, res) => exec("ping -c 1 " + req.query.host, (e, o) => res.send(o)));
app.get('/f', (req, res) => res.sendFile(__dirname + "/files/" + req.query.name));
app.listen(3000);
SQL construit par concaténation de chaînes, child_process.exec appelé avec un paramètre de requête, chemin sendFile non assaini, clé codée en dur. Environnement : macOS, Node v22.17.0, Python 3.14.6, @openai/[email protected], plugin embarqué 0.1.14 ; toutes les exécutions ont eu lieu le 2026-07-29 entre 02:20 et 03:05 UTC.
| Exécution | Cible | Budget | Arrêt à | Durée | Entrée en cache | Nouvelle entrée | Sortie | Détections |
|---|---|---|---|---|---|---|---|---|
| 1 | Dépôt complet, mode standard | 1,00 $ | 1,46 $ | 3m23s | 1,092,608 | 121,396 | 10,300 | 0 |
| 2 | Dépôt complet, mode standard | 6,00 $ | 6,03 $ | 8m33s | 6,654,720 | 331,330 | 34,946 | 0 |
| 3 | Arbre de travail, diff d’une ligne | 3,00 $ | 3,06 $ | 9m46s | 2,035,712 | 240,448 | 28,120 | 0 |
| 4 | Dépôt complet, projet complet | 8,00 $ | 8,54 $ | 8m00s | 7,299,840 | 634,419 | 57,223 | 0 |
| 5 | Dépôt complet, reasoning_effort=low | 3,00 $ | 3,20 $ | 4m13s | 1,749,248 | 366,841 | 16,269 | 0 |
Les montants en dollars sont les estimations du CLI, affichées pendant le scan et enregistrées dans scans list. Ils sont calculés à partir des volumes de tokens et des tarifs catalogue d’OpenAI, non à partir de la facture réellement émise par un endpoint. Les entrées en cache expliquent pourquoi les totaux paraissent faibles au regard des volumes de tokens. L’exécution 2 se recompose exactement avec 5,00 $ par million de nouvelles entrées, 0,50 $ par million d’entrées en cache et 30,00 $ par million de sorties :
331,330 x $5.00/M = $1.657
6,654,720 x $0.50/M = $3.327
34,946 x $30.00/M = $1.048
------
$6.032 (CLI reported $6.03239)
Ces trois mêmes tarifs retrouvent les totaux des cinq exécutions au cent près : un contrôle de cohérence utile si vos propres chiffres semblent anormaux.
Aucun des cinq scans n’est arrivé à son terme. Tous se sont arrêtés faute de budget, et scans list les indique comme phase: preflight, status: failed, avec coverage: worklistRows 0. Autrement dit, aucun n’a atteint l’étape qui remonte les vulnérabilités.
L’exécution 4 sert de contrôle. Mon premier dépôt était volontairement incomplet : aucun package.json, et un import ./db dont le module était absent. Le modèle de menaces de l’outil a explicitement signalé ce point comme une inconnue. Une fois le projet reconstruit proprement avec quatre fichiers et treize lignes, dépendances déclarées comprises, le coût a augmenté au lieu de diminuer : 8,54 $ et 7,9 M de tokens d’entrée.
La progression n’est pas linéaire. Le coût augmente lentement durant les trois premières minutes, puis progresse par deux paliers ; chacun correspond au moment où l’agent élargit son travail. Le journal explique une fois le mécanisme, après 51 secondes : Preflight: worker delegation supported (up to 8 worker slots).
95 % des tokens d’entrée provenaient du cache : le même contexte a donc été renvoyé tour après tour plutôt que relu à neuf. Le prix unitaire est faible, mais cette ligne reste la plus coûteuse de la facture. Même au tarif des entrées en cache, sept millions de tokens finissent par peser lourd pour un fichier de neuf lignes.
C’est précisément là que l’estimation, souvent répétée, d’environ 0,02 $ pour 1 000 lignes de code cesse de tenir. À ce tarif, mon dépôt aurait dû coûter une fraction de centime.
Réduire le raisonnement aide moins qu’espéré
L’exécution 5 définit model_reasoning_effort="low" sur le même projet que l’exécution 4. La consommation est tombée d’environ 1,0 M de tokens par minute à 0,5 M par minute : à budget identique, le temps d’exécution double. Mais le scan a tout de même atteint son plafond dans la même phase de préflight, sans rien produire. Diviser le rythme de consommation par deux ne suffit pas si le pipeline exige davantage de tours que le budget ne peut en couvrir dans tous les cas.
--max-cost est un jalon, pas un frein
La documentation officielle du CLI indique que les requêtes déjà en cours peuvent se terminer au-delà de la limite. Elle ne précise pas l’ampleur possible du dépassement. Sur les cinq exécutions, il a varié de 0,5 % à 46 % : le plafond de 1,00 $ s’est arrêté à 1,46 $, celui de 6,00 $ à 6,03 $, et les trois plafonds intermédiaires ont dépassé de 2 % à 7 %. Le dépassement correspond à ce que l’agent avait déjà en cours ; une répartition de travail entre plusieurs workers près du plafond constitue donc le scénario coûteux. Fixez la limite sous le montant que vous ne pouvez réellement pas dépasser.
Le pré-commit n’est pas l’option économique
La réponse évidente à un scan complet qui s’emballe est de n’analyser que les changements. J’ai validé une base saine, ajouté une ligne vulnérable — une clause LIKE construite par concaténation de chaînes — puis lancé --working-tree --base HEAD.
Le résultat a coûté plus cher que le premier scan complet : 9m46s, 2,276,160 tokens d’entrée, arrêt à 3,06 $ pour un plafond de 3,00 $. Il est allé plus loin dans le pipeline que les scans complets, en écrivant une liste de travail de revue classée par priorité (rank_input.jsonl, deep_review_input.jsonl) avant d’épuiser le budget, mais n’a produit aucune détection. Restreindre le scan à un diff ne réduit pas le contexte par tour : l’agent lit toujours le dépôt, rédige toujours un modèle de menaces complet et répartit toujours du travail entre des workers.
install-hook relie l’outil à un hook Git pré-commit qui bloque les détections de sévérité élevée et les erreurs de scan. Avant de l’installer pour une équipe, mesurez le prix d’un scan de diff sur votre propre base de code : ce hook peut ajouter des minutes et des dollars à chaque commit.
Ses angles morts actuels
Le modèle de menaces produit par l’outil pour neuf lignes est un travail sérieux. Il identifie les quatre frontières de confiance, désigne le module ./db manquant comme une inconnue explicite et refuse d’attribuer à Express des protections qu’il ne peut pas vérifier. Il formule aussi clairement sa propre limite : « Les contrôles absents du dépôt ne doivent pas être supposés. »
C’est la contrainte structurelle de l’approche. Le code source est son unique entrée ; tout ce qui se décide au déploiement reste donc invisible : politique CORS, mode debug laissé actif, TLS faible, en-têtes de sécurité absents, empoisonnement de cache et autorisations d’exécution entre services. Les failles d’autorisation au niveau objet, en particulier, exigent des requêtes authentifiées avec deux identités réelles pour être confirmées — ce qu’aucune lecture du code ne peut fournir.
La profondeur d’analyse varierait également selon les langages. Le retour d’expérience d’un praticien sur le service hébergé estime la couverture la plus solide en Python, JavaScript, TypeScript, Go et Java, Ruby, PHP et Kotlin arrivant derrière. Je n’ai testé que JavaScript : considérez donc cette information comme indirecte.
Faut-il l’utiliser ?
Installez-le dès maintenant si vous cherchez un modèle de menaces. C’est le seul livrable que j’ai obtenu à chacune des exécutions : un document de 1 605 mots qui cartographie les frontières de confiance, décrit les scénarios d’attaque et définit ce que signifient critique, élevé, moyen et faible pour ce service précis. Il peut aussi alimenter les autres outils que vous utilisez, puisque --knowledge-base accepte vos propres documents d’architecture et que le modèle généré est modifiable.
Attendez si vous avez besoin de dépenses prévisibles ou d’une véritable liste de détections. Dans cinq configurations, je n’ai obtenu ni l’un ni l’autre, pour un coût de 1,46 $ à 8,54 $ par exécution sur un dépôt lisible en dix secondes. Les sorties documentées plus loin dans le pipeline — findings.json, coverage.json et report.md — ne sont jamais apparues. La question reste ouverte : un compte ChatGPT Business autorisé se comporterait-il différemment ? Ces tests ne permettent pas d’y répondre.
Aucun des deux leviers de coût les plus évidents n’a fonctionné ici : ni le périmètre limité à un diff ni un effort de raisonnement réduit n’ont permis de franchir le même mur. Le seul facteur qui a changé l’équation est le tarif du modèle. L’estimation reposant sur les volumes de tokens aux prix catalogue, un endpoint à la moitié du tarif divise le coût d’une même exécution par deux. Construisez votre budget à partir de mesures réelles, pas de la taille du dépôt, et fixez votre plafond sous votre limite effective d’une marge équivalente à un tour de workers : mon pire dépassement a atteint 46 % du plafond.
FAQ
Le Codex Security CLI est-il gratuit ?
Le CLI et le SDK sont sous licence Apache-2.0 et leur installation ne coûte rien. Les scans, eux, ne sont pas gratuits. Ils consomment des tokens GPT-5.6 Sol avec les identifiants utilisés pour l’authentification, et le CLI affiche une estimation progressive basée sur les tarifs catalogue d’OpenAI.
Faut-il un forfait ChatGPT Business ou Enterprise ?
Oui pour l’intégration GitHub hébergée : ce parcours est limité aux offres Pro, Enterprise, Business et Edu. Le CLI accepte une simple OPENAI_API_KEY, mais la documentation prévient que les scans de dépôt complet peuvent toujours exiger Trusted Access for Cyber, qu’aucun forfait n’accorde automatiquement.
Peut-il fonctionner dans une CI ?
Oui. Définissez OPENAI_API_KEY, ajoutez --fail-on-severity pour transformer les détections en code de sortie non nul, puis pointez CODEX_SECURITY_STATE_DIR vers un chemin accessible en écriture hors du dépôt. Par défaut, les scans sont uniquement destinés au rapport.
Fonctionne-t-il avec un endpoint tiers compatible OpenAI ?
Oui, à condition que l’endpoint implémente la Responses API. Vous devez surcharger la configuration du fournisseur Codex via les options --codex, car la seule définition de OPENAI_API_KEY échoue lors de l’authentification.
Quelle différence avec le plugin Codex Security ?
Le moteur de scan est le même, mais le point d’entrée diffère. Le plugin s’exécute dans l’infrastructure d’OpenAI sur un dépôt GitHub connecté. Le CLI s’exécute localement sur votre machine et sur un chemin local, conserve l’historique des scans dans un répertoire d’état local, et ajoute les scans limités aux diffs, un hook pré-commit, l’export SARIF et l’enregistrement MCP.
À lire aussi : Guide des tarifs GPT-5.6 · Mode automatique de Codex
