Le test terrain présenté ici porte sur une tâche proche d'un domaine déjà présent en production, avec un livrable précis, des contraintes de sécurité et une exigence de preuve d'exécution.
Claude Code, l'orchestrateur du studio Synapx, a donc testé Codex gpt-5.6-terra en effort « max ». L'objectif n'était pas de refaire un benchmark. Il était plus concret : observer le travail livré, relire le code, refaire les tests, puis lui opposer des attaques que le modèle n'avait jamais vues.
Le résultat est très convaincant sur ce point précis. Il ne permet pas de généraliser : l'échantillon ne contient qu'une seule tâche. C'est justement cette limite qui rend le retour utile. Voici ce que le test montre, et ce qu'il ne montre pas.
flowchart TD
A[Consigne PHP cadrée] --> B[Exploration du dépôt]
B --> C[Code SignedUrl]
C --> D[Tests]
D --> E[README]
E --> F[Exécution de php tests.php]
F --> G[Relecture indépendante]
G --> H[12 attaques adverses inédites]
H --> I[Verdict terrain nuancé]
Le protocole : une tâche autonome et vérifiable
Le modèle testé est Codex gpt-5.6-terra, avec l'effort « max », via le CLI codex 0.144.4. Le test s'est déroulé avec une sandbox danger-full-access, dans un bac à sable Git isolé, hors du dépôt de production.
La consigne demandait d'implémenter, en PHP 8.1 pur et sans Composer, un utilitaire SignedUrl avec sign() et verify(). Cet utilitaire devait produire et vérifier des URL signées en HMAC-SHA256, utiliser une comparaison à temps constant, traiter les cas limites, livrer des tests exécutables avec php tests.php et fournir un README. Codex devait aussi lancer lui-même ses tests.
Le sujet est proche du lot 5 « pièces jointes » de Synapx, où des URL signées HMAC existent déjà côté Synapx.
| Indicateur | Valeur |
|---|---|
| Durée de bout en bout | ~4 min |
| Tokens consommés | 42 450 |
| Actions terrain (shell) | 3 (explorer → écrire → exécuter les tests) |
| Fichiers livrés | SignedUrl.php (281 lignes), tests.php (187 lignes), README.md |
| Tests écrits par Codex | 12/12 (ré-exécutés par l'orchestrateur : 12/12) |
| Attaques adverses (écrites par l'orchestrateur après coup) | 12/12 |
| php -l (lint) | aucune erreur |
La vérification ne s'est pas arrêtée à la sortie du modèle. L'orchestrateur a relu le code, ré-exécuté les tests écrits par Codex, puis écrit lui-même douze attaques adverses. Ces attaques n'avaient pas été fournies au modèle durant la tâche. Le protocole ne repose donc pas sur une simple déclaration de réussite : il sépare la production, la relecture et l'épreuve supplémentaire.
🗒️ Note de Claude — Le point important n'est pas seulement que les tests passent. Le modèle a réellement exécuté
php tests.phpet montré la sortie demandée, au lieu d'affirmer que le code était testé.
La méthode observée : le terrain avant le code
Le déroulé a été particulièrement lisible. Avant d'écrire une ligne de code, Codex a utilisé find et rg pour cartographier le dépôt. Cette exploration initiale correspond à une règle simple : terrain avant code.
La suite s'est faite en une passe unique et cohérente : code, tests, README, puis exécution. Aucun tâtonnement ni aller-retour brouillon n'a été observé. Cela ne dit pas que tout problème de développement se résout en un passage ; cela décrit ce qui s'est produit ici, sur cette demande précise.
Le périmètre a aussi été tenu strictement. Le livrable contient exactement ce qui était demandé : SignedUrl.php, tests.php et README.md. Aucun fichier parasite, aucune dépendance introduite, aucun ajout hors sujet.
Ce qui va au-delà de la consigne côté sécurité
La consigne demandait une signature HMAC-SHA256, une comparaison à temps constant et la gestion des cas limites. À la relecture, plusieurs protections supplémentaires ont été observées. Elles n'étaient pas explicitement demandées dans la tâche.
La première concerne le décodage. La méthode strictRawUrlDecode rejette tout encodage non canonique. Une même donnée ne peut donc avoir qu'une seule forme d'URL valide, ce qui évite une collision de canonicalisation.
La seconde concerne sig. La signature est validée avec une expression régulière stricte avant l'appel à hash_equals. La casse compte : une signature en majuscules est refusée. Le contrôle observé est explicite :
if ($expiration === null || !preg_match('/^[a-f0-9]{64}$/D', $providedSignature)) { return false; }
Le paramètre exp est, lui aussi, traité de façon stricte. Il est parsé à la main, les zéros en tête sont refusés, une borne explicite est appliquée face à PHP_INT_MAX et une garde protège le calcul du TTL contre le dépassement.
Le code adopte par ailleurs un comportement fail-closed : tout throwable est intercepté et devient false. Toute entrée malformée échoue donc du côté sécurisé. Les noms de paramètres réservés, exp et sig, sont protégés dès la signature afin qu'un appelant ne puisse pas les écraser.
Enfin, plusieurs ambiguïtés de requête sont rejetées : un espace encodé en + est considéré comme ambigu et refusé, seul %20 est accepté ; le fragment # est refusé ; les paramètres dupliqués le sont également. Ces choix ne sont pas une promesse générale sur toutes les implémentations d'URL signées. Ce sont les protections effectivement observées dans ce livrable.
Douze attaques inédites, douze résultats tenus
Après la relecture et la ré-exécution des tests du modèle, l'orchestrateur a rédigé douze attaques adverses. Elles ont été écrites après coup et n'ont jamais été fournies à Codex. Le contrôle portait sur les cas suivants :
- Signature d'un autre secret
- Confusion path→query
expavec zéro en têteexpen dépassement (overflow)- Signature en majuscules
- Path
%2Fnon canonique - Aller-retour unicode + caractères réservés
- Paramètre vide
- Fragment
# - Espace encodé en
+ - Déterminisme de la signature
- Paramètre réservé refusé
Le bilan global est de 12/12, sans contournement trouvé. Il faut lire ce résultat à sa juste portée. Il ne certifie pas un modèle pour tous les cas de sécurité possibles. Aucune faiblesse n'a été détectée sur cette implémentation et sur ces scénarios.
Benchmark générique et constat terrain : deux mesures différentes
Les benchmarks génériques placent terra légèrement au-dessus de Fable. Le présent test ne mesure pas ce pourcentage annoncé. Il ne permet donc ni de le confirmer ni de l'infirmer.
La différence est importante. Ici, le protocole observe une tâche PHP autonome, un périmètre donné, une exécution effective des tests, une relecture indépendante et des attaques rédigées après livraison.
Ce que ce test montre concrètement est une discipline de preuve : Codex a exécuté ses tests et montré leur sortie au lieu d'affirmer le résultat sur parole. Il montre aussi une anticipation sécurité au-delà de la consigne fournie, notamment sur le décodage, le format de la signature, l'expiration et les ambiguïtés de requête.
Le verdict terrain, à ce stade et sur un seul point de mesure, est donc très convaincant. Le mot important reste « terrain » : il décrit ce qui a été observé ici, pas une supériorité générale déduite d'un seul exercice.
Les réserves à garder visibles
Premier constat : aucun bug fonctionnel ni faille de sécurité n'a été détecté sur cette tâche précise. C'est un résultat du protocole réalisé, pas une absence de risque garantie au-delà de ce périmètre.
Une réserve mineure concerne exp. Le paramètre d'expiration est stocké en clair dans la query par conception. Il est toutefois couvert par la signature, donc non altérable. Le comportement est correct, mais il doit être documenté du côté de l'appelant.
La réserve principale est méthodologique : l'échantillon est une seule tâche. Un test unique ne suffit pas pour tirer une règle générale sur un modèle. Le constat doit être rejoué sur d'autres registres, notamment le refactoring de code legacy, la chasse aux bugs et le front-end, avant toute généralisation.
Verdict : GO, avec un plan de confirmation
Le verdict de l'orchestrateur est GO : sur une tâche cadrée, Codex gpt-5.6-terra est jugé apte à produire du code de sécurité PHP autonome de qualité production, avec preuve d'exécution à l'appui.
La recommandation est d'intégrer terra max au pool d'agents Codex pour les tâches sensibles, notamment l'authentification, les signatures et la validation. Cette intégration ne clôt pas l'évaluation. Elle doit être accompagnée de deux à trois tests complémentaires, dont du code legacy Delphi et de la chasse aux bugs, afin d'asseoir le constat avant de le généraliser.
Le point à retenir n'est donc pas qu'un modèle aurait remplacé la vérification humaine. Le test raconte l'inverse : le résultat devient solide parce que le modèle livre, exécute et montre ses tests, puis parce qu'un orchestrateur relit et cherche activement à casser ce qui vient d'être produit.
Conclusion : une preuve locale, pas une promesse générale
Le benchmark générique et le retour terrain ne se confondent pas. Le premier peut situer terra face à Fable ; le second montre qu'ici, sur un utilitaire PHP d'URL signées HMAC-SHA256, le modèle a tenu une consigne cadrée, fourni les artefacts attendus, exécuté ses tests et résisté à douze attaques adverses inédites.
Ce sont des éléments concrets et vérifiables. Ils justifient un verdict très convaincant sur cette tâche, ainsi qu'un GO opérationnel pour les tâches sensibles décrites par l'orchestrateur. Ils ne justifient pas une conclusion générale sur toutes les formes de développement.
La bonne suite est déjà connue : élargir le terrain de mesure, conserver la même exigence de preuve et comparer les résultats sans transformer une réussite locale en promesse universelle. L'échantillon reste une seule tâche ; c'est la limite à ne pas oublier.