La CI est verte. composer update a écrit des milliers de lignes dans vendor/. Personne n’a ouvert le diff. Dans ce scénario illustratif, fréquent en reprise Laravel, l’équipe fait confiance à Packagist et au lockfile : la build passe, donc le code est « bon ». Or chaque mise à jour apporte du code que personne sur le projet n’a lu — jusqu’à ce qu’un paquet compromis, ou simplement surprenant, s’exécute au prochain déploiement.
Le problème n’est pas Composer en soi. C’est l’absence de revue du code qui entre dans vendor/ avant l’écriture : on valide une résolution de versions, pas le contenu des fichiers. Tant que la chaîne s’arrête à « update OK », la supply chain PHP reste un acte de foi — alors qu’un outil 1er party, encore en beta, existe pour montrer ce diff et enregistrer ce qu’on fait confiance.
Symptômes : update passé, dette invisible
Au moment où le ticket de reprise arrive, les signes se contredisent. Le composer.lock a bougé. Les tests unitaires passent. Aucune CVE criante dans le scanner du jour. Pourtant personne ne peut dire quels fichiers ont changé dans les paquets montés de version, ni qui a décidé que ce contenu était acceptable. Le métier voit une maintenance « à jour ». La surface technique voit du code tiers non relu, exécuté avec les droits de l’application.
Cette classe de risque n’est pas théorique en 2026 : politiques Composer, malware sur l’écosystème npm, pression croissante sur les dépendances. Côté maintenance, c’est le genre de dette qu’un devis d’audit deps doit nommer : pas seulement « monter les versions », mais « qui lit ce qui entre dans vendor ».
Hypothèses : pourquoi personne n’a lu
Plusieurs causes plausibles produisent le même symptôme. Il faut les départager, parce que le correctif n’est pas le même.
Hypothèse 1 — le process s’arrête au lockfile. L’équipe traite composer update + tests verts comme une validation complète. Le diff de composer.lock est relu ; le contenu des archives Packagist ne l’est pas. Cas le plus fréquent en petite équipe sous pression.
Hypothèse 2 — pas d’outil de revue avant écriture. Sans plugin qui bloque l’écriture de vendor/ tant qu’un paquet n’est pas marqué de confiance, la revue manuelle des diffs Packagist est trop coûteuse pour tenir. On abandonne, puis on normalise l’abandon.
Hypothèse 3 — confiance transitive non tracée. On connaît les paquets directs ; les transitives bougent aussi. Sans enregistrement de confiance par version et empreinte, un bump mineur d’une dépendance profonde passe inaperçu.
Hypothèse 4 — PHP / toolchain trop vieux pour le garde-fou. Laravel Vet exige PHP ≥ 8.4. Sur une base encore en 8.2 ou 8.3, l’outil n’est pas installable tel quel : la dette n’est pas seulement process, c’est runtime.
Ces hypothèses coexistent souvent. Les confondre produit des demi-mesures : on ajoute un scanner CVE et l’on continue d’écrire vendor/ sans lire le diff.
Laravel Vet en une phrase (outil, beta)
Depuis mi-septembre 2026, l’équipe Laravel publie Laravel Vet — plugin Composer 1er party (annoncé notamment via Laravel News) : il montre le code qu’un composer update s’apprête à écrire dans vendor/, et enregistre les paquets de confiance dans un fichier vet.json. Inspiration proche de cargo vet côté Rust. Encore en beta : le comportement peut changer avant une version stable. Prérequis : PHP 8.4 ou plus. Ce texte ne dump pas le changelog ; il décrit le mécanisme utile en reprise.
Le flux illustratif : installer en dev (composer require laravel/vet --dev, autoriser le plugin), initialiser la confiance sur l’existant (./vendor/bin/vet --init → écrit vet.json), puis laisser Vet intercepter les updates non de confiance. Un paquet non relu fait échouer la commande (statut non zéro) — utile en CI. La revue peut être humaine ou assistée par un agent de coding local (PASS / FAIL / WARN) ; seuls les choix humains enregistrés mettent à jour vet.json. L’empreinte couvre les fichiers du paquet : si le contenu change sans nouveau numéro de version, Vet redemande une revue.
Tests discriminants : départager avant de brancher Vet
Avant d’imposer Vet partout, on vérifie où en est le projet.
Test A — le dernier update a-t-il un diff vendor relu ? Geste : prendre le dernier bump de lockfile et demander qui a ouvert le diff des fichiers du paquet (pas seulement le lock). Résultat attendu si la dette tient : personne / « on a regardé le changelog ». Conclusion : process lockfile-only confirmé.
Test B — PHP runtime ≥ 8.4 ? Geste : lire la contrainte plateforme et la version CI/prod. Résultat attendu si bloqueur : < 8.4. Conclusion : planifier le bump PHP avant Vet, ou documenter l’écart.
Test C — un paquet non trusté bloque-t-il la CI aujourd’hui ? Geste : simuler un bump mineur ; observer si quoi que ce soit refuse l’écriture vendor. Résultat attendu si absente : update écrit sans friction. Conclusion : aucun cran d’écriture ; Vet (ou équivalent) comble ce trou.
Test D — vet.json (ou équivalent) est-il versionné ? Geste : chercher un registre de confiance commité à côté de composer.json. Résultat attendu si absent : silence. Conclusion : même avec revue ad hoc, la confiance n’est pas rejouable en équipe.
Ces quatre tests collent à des artefacts — historique git, version PHP, sortie CI, présence de vet.json — plutôt qu’à un débat d’intention (« on fait attention »).
composer.lock bump → diff vendor relu par qui ?
PHP plateforme → ≥ 8.4 pour laravel/vet ?
CI update → échoue si paquet non trusté ?
vet.json (ou équiv.)→ versionné à côté de composer.json ?
Correction maintenant, non-régression ensuite
La correction sur une reprise traite l’existant. On inventorie les paquets à risque (directs + transitives sensibles : HTTP, auth, filesystems, process). On lit — ou on fait lire par un agent, puis on valide soi-même les FAIL/WARN — le diff des bumps récents non audités. On tourne les secrets si un paquet suspect a pu s’exécuter. On ne se contente pas d’un scanner CVE vert : une CVE absente ne dit pas qu’on a lu le code. Si PHP < 8.4, on planifie le runtime avant d’imposer Vet ; en attendant, une revue manuelle documentée des bumps critiques.
La prévention / non-régression se pose sur le process. Installer Vet en dev quand le runtime le permet ; committer vet.json ; faire échouer la CI sur paquet non trusté. Règle écrite : aucun composer update de prod sans entrée de confiance à jour. Les résultats d’agent (PASS/FAIL) aident ; ils ne remplacent pas la sélection humaine dans vet.json. Couche optionnelle citée par l’écosystème : politique d’âge minimum des releases (ex. Heimdall) — complémentaire, pas substitut à la revue de contenu.
Séparer correction et prévention évite un piège classique : activer Vet, lancer --init, et croire que l’historique est audité. --init enregistre la confiance sur les fichiers déjà présents sans les avoir relus. Utile pour démarrer ; insuffisant comme preuve d’audit rétroactif.
Limites et ce que ce texte n’est pas
Ce texte décrit une classe fréquente — update Composer sans revue du contenu vendor — et pointe Laravel Vet comme mécanisme 1er party encore beta (PHP ≥ 8.4), pas un audit nominatif ni un dump de changelog. Vet peut évoluer ; la doc du dépôt et l’annonce Laravel News font foi le jour J. Un agent de revue peut rater un fichier trop gros (WARN) : l’humain garde le dernier mot sur le trust. D’autres stacks avec un composer.json peuvent utiliser le même plugin ; le raisonnement supply-chain reste le même.
Quand une maintenance se vend comme « deps à jour » sans cran avant écriture de vendor/, on a modernisé les versions et laissé la supply chain en acte de foi. Ce n’est plus un détail d’outil : c’est une dette de revue.
Si vous héritez d’un Laravel dont les bumps Composer n’ont jamais été lus fichier par fichier, le cadre opérationnel — audit deps, reprise, non-régression — est décrit sur la page expertise.
Commentaires 0
Soyez le premier à commenter cet article.
Laisser un commentaire