composer audit doit devenir un contrôle automatique de chaque projet PHP : il lit les dépendances réellement installées, les compare aux avis de sécurité connus et retourne un code d’erreur exploitable en CI. En 2026, la bonne stratégie n’est ni de figer éternellement les versions, ni de lancer aveuglément composer update : conservez un composer.lock, auditez à chaque pipeline, planifiez des mises à jour ciblées et testées, puis traitez les vulnérabilités selon leur exposition réelle. Cette discipline s’applique aussi bien à Symfony qu’à Laravel.
Comprendre ce que contrôle réellement composer audit
La commande composer audit interroge les avis de sécurité disponibles pour les packages présents dans votre projet. Elle s’appuie notamment sur la base d’avis Packagist et sur le mécanisme d’advisories consommé par Composer. Son intérêt est simple : détecter une bibliothèque vulnérable avant qu’elle ne reste des mois dans un environnement de production.
Exécutez-la depuis la racine du projet :
composer audit
Dans un dépôt avec un lockfile, utilisez plutôt :
composer audit --locked
L’option --locked indique explicitement à Composer d’évaluer les versions déclarées dans composer.lock. C’est généralement le comportement attendu en CI : vous voulez analyser l’artefact de dépendances déployable, pas une résolution théorique qui pourrait varier selon le moment où la commande est lancée.
Composer peut aussi signaler des packages abandonnés. Ce signal ne correspond pas nécessairement à une faille exploitable, mais il mérite une décision documentée : remplacer la dépendance, la maintenir temporairement dans un fork interne, ou accepter consciemment le risque.
Voici une lecture pratique des sorties possibles.
| Élément du rapport | Ce qu’il indique | Action recommandée |
|---|---|---|
| Package concerné | La dépendance directe ou transitive affectée | Identifier qui l’installe avec composer why |
| Version installée | La version présente dans le lockfile | Vérifier qu’elle correspond à la production |
| Versions affectées | La plage vulnérable décrite par l’avis | Chercher la première version corrigée |
| CVE ou identifiant d’avis | Référence publique de la vulnérabilité | Lire le détail et l’impact réel |
| Sévérité | Niveau de criticité lorsqu’il est disponible | Prioriser, sans remplacer l’analyse technique |
| URL de référence | Lien vers l’avis ou le correctif | Vérifier les conditions d’exploitation |
Un audit n’est pas un scanner magique de votre code métier. Il ne détecte pas une injection SQL écrite dans un contrôleur, une configuration CORS trop permissive ou une clé API envoyée dans un dépôt Git. Il répond à une question plus précise : « Une version de package déclarée dans ce projet est-elle connue pour être vulnérable ? »
Cette distinction est essentielle dans un projet Symfony. Une alerte sur symfony/http-foundation, par exemple, exige de savoir si la fonctionnalité vulnérable est utilisée, mais elle ne justifie pas l’inaction : un framework est un composant transversal, souvent exposé par plusieurs chemins d’exécution. Pour approfondir les sujets d’exposition applicative, consultez aussi ce guide sur la sécurité des API Symfony.
Lire un rapport de vulnérabilité sans réduire l’analyse à une CVE
Une CVE, ou Common Vulnerabilities and Exposures, est un identifiant public permettant de référencer une vulnérabilité. Elle facilite le suivi entre un outil, un fournisseur, une pull request et une équipe sécurité. Mais une CVE ne dit pas automatiquement si votre application est compromise.
Un rapport Composer peut contenir une ligne proche de celle-ci :
Package: vendor/package
Affected versions: <2.4.7
Reported at: 2026-02-10
CVE: CVE-2026-XXXXX
Advisory: https://...
La première étape est de retrouver l’origine de la dépendance :
composer why vendor/package
Vous saurez alors si elle est requise directement dans votre composer.json ou installée indirectement par un bundle, un SDK de paiement, un client HTTP ou un framework.
Ensuite, qualifiez l’alerte avec une grille simple :
-
L’application exécute-t-elle le code vulnérable ? Une faille dans un composant de génération d’archives ne produit pas le même risque si votre application n’accepte aucun fichier téléversé.
-
Un attaquant contrôle-t-il l’entrée nécessaire ? Une vulnérabilité exploitable uniquement par un administrateur authentifié n’a pas le même niveau d’urgence qu’une exécution de code distante sur une route publique.
-
La version corrigée est-elle compatible ? Regardez les notes de version, les changements de contrat public et les contraintes des packages voisins.
-
Existe-t-il une mitigation temporaire ? Désactiver une fonctionnalité, filtrer une entrée ou restreindre une route peut réduire le risque pendant la préparation de la mise à jour. Ce n’est pas un substitut permanent au correctif.
-
Quelle est l’exposition de production ? Une application interne, un back-office public, une API multi-tenant et une plateforme e-commerce ne se priorisent pas de la même manière.
La sévérité affichée est utile pour trier, pas pour penser à votre place. Un score élevé peut concerner un chemin inutilisé ; une faille évaluée comme modérée peut devenir grave si votre application traite des données particulièrement sensibles. Le standard CVSS, maintenu par le Forum of Incident Response and Security Teams (FIRST), décrit une méthode de notation pertinente, mais votre contexte d’exécution reste décisif.
Documentez chaque exception. Si vous décidez de ne pas corriger immédiatement, créez un ticket contenant l’identifiant de l’avis, le package, la justification, la mesure compensatoire et une date de révision. Cette trace évite qu’un « faux positif temporaire » devienne une dette de sécurité oubliée.
Intégrer l’audit Composer dans GitHub Actions ou GitLab CI
Un audit manuel réalisé une fois par trimestre est utile, mais insuffisant. Le contrôle doit s’exécuter quand une dépendance change et avant le déploiement. L’intégration CI est particulièrement naturelle pour les équipes qui ont déjà industrialisé tests, analyse statique et migrations, comme dans un pipeline décrit par notre guide CI/CD Symfony avec GitLab et GitHub Actions.
Dans GitHub Actions, un job minimal peut ressembler à ceci :
name: Security audit
on:
pull_request:
push:
branches: [main]
jobs:
composer-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
- run: composer install --no-interaction --prefer-dist --no-progress
- run: composer audit --locked
L’objectif n’est pas de remplacer vos tests PHPUnit, Pest ou fonctionnels Symfony. Il s’ajoute à eux. Une mise à jour de sécurité peut modifier un comportement : le pipeline doit donc enchaîner installation reproductible, audit, tests et analyse statique.
Pour GitLab CI, la logique est identique :
composer_audit:
image: composer:2
stage: test
script:
- composer install --no-interaction --prefer-dist --no-progress
- composer audit --locked
only:
- merge_requests
- main
Quelques règles rendent ce contrôle fiable :
- lancez l’audit sur les merge requests et sur la branche de déploiement ;
- utilisez une image ou une version de Composer maintenue ;
- échouez le pipeline lorsqu’une vulnérabilité doit bloquer la livraison ;
- évitez de masquer globalement les erreurs avec
|| true; - produisez un ticket ou une alerte lorsque le correctif ne peut pas être appliqué immédiatement ;
- exécutez aussi l’audit sur une tâche planifiée, car de nouveaux avis peuvent viser un lockfile inchangé.
Cette dernière règle est souvent oubliée. Votre composer.lock peut être identique aujourd’hui et devenir problématique demain parce qu’un avis de sécurité vient d’être publié. Un pipeline planifié hebdomadaire détecte ce cas sans demander une surveillance humaine permanente.
Versions figées, mises à jour régulières : choisir le compromis utile
Le fichier composer.json exprime les contraintes acceptables ; composer.lock fixe les versions précises résolues. En production, vous devez déployer le lockfile, pas demander au serveur de résoudre à nouveau les dépendances.
La commande recommandée lors d’un déploiement est :
composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction
Évitez composer update sur le serveur de production. Cette commande recalculerait les dépendances selon l’état courant des repositories et pourrait produire un ensemble différent de celui testé en CI.
Le faux débat oppose souvent deux extrêmes : verrouiller toutes les versions pour toujours, ou mettre à jour toutes les semaines sans contrôle. Le premier scénario accumule des correctifs manquants ; le second augmente le risque de régression. Une politique réaliste combine stabilité et cadence.
Pour une mise à jour ciblée :
composer update symfony/http-foundation --with-all-dependencies
L’option --with-all-dependencies est fréquemment nécessaire dans l’écosystème Symfony et Laravel, car un composant corrigé peut exiger l’alignement de packages associés. Avant de fusionner, examinez le diff de composer.lock, les changelogs et les tests concernés.
Une cadence saine peut être organisée ainsi :
- À chaque pull request de dépendances : exécuter tests, analyse statique et
composer audit. - Chaque semaine : lancer un audit planifié sur les branches maintenues.
- Chaque mois : consacrer un créneau à des mises à jour mineures et patches.
- À chaque CVE critique applicable : créer une branche corrective, tester puis déployer selon votre procédure d’urgence.
- À chaque montée majeure de framework : préparer une migration dédiée, jamais noyée dans une vague de petites mises à jour.
Laravel et Symfony donnent tous deux de bonnes raisons d’adopter cette discipline : leur écosystème est riche, et une application moderne dépend vite de dizaines de composants directs ou transitifs. Si vous hésitez entre les approches de maintenance des deux frameworks, l’article Laravel vs Symfony en 2026 apporte des repères complémentaires.
Roave Security Advisories, Symfony Security Checker et les outils complémentaires
composer audit est aujourd’hui le point d’entrée standard pour un projet PHP utilisant Composer. Il remplace avantageusement l’ancien outil Symfony Security Checker dans la plupart des workflows. Le projet historique symfony/security-checker a été déprécié ; Symfony recommande désormais d’utiliser composer audit. Cette évolution est cohérente avec la documentation officielle de Symfony et le fait que Composer dispose nativement de cette capacité.
Roave Security Advisories reste néanmoins utile dans certains contextes. Ce package ne corrige rien et ne scanne pas votre production : il agit comme une contrainte Composer qui empêche l’installation de versions connues comme vulnérables.
Ajoutez-le en développement :
composer require --dev roave/security-advisories:dev-latest
Son intérêt apparaît lors d’un composer update : Composer évite les versions couvertes par les avis intégrés au package. C’est une barrière préventive appréciable, mais elle peut rendre certaines résolutions difficiles lorsqu’un projet ancien dépend de contraintes trop serrées.
Ne le considérez pas comme un remplacement de l’audit :
- Roave Security Advisories bloque des versions vulnérables lors de la résolution ;
composer auditvérifie les dépendances résolues et peut être exécuté sur un lockfile existant ;- les tests applicatifs valident que le correctif n’a pas cassé vos cas métier ;
- l’analyse de code cible vos défauts propres, absents des bases d’advisories.
Les documentations officielles de Composer et de Symfony sont les premières références à consulter pour ces mécanismes. Pour les bibliothèques critiques, lisez aussi les notes de version de l’éditeur concerné. Côté PHP, les bulletins et recommandations de la documentation officielle PHP restent indispensables dès que la vulnérabilité implique l’environnement d’exécution plutôt qu’un package Composer.
L’outillage IA peut aider à résumer un changelog ou à préparer une checklist de régression, mais ne lui déléguez pas la décision de sécurité. Un assistant peut confondre une version transitive, ignorer une contrainte de compatibilité ou inventer une mitigation. Le bon usage consiste à lui fournir le rapport, le diff du lockfile et vos conventions, puis à valider sa proposition. Cette approche rejoint les pratiques détaillées dans notre guide de prompt engineering pour PHP et Symfony.
Vérifier l’intégrité : lockfile, provenance et installation reproductible
La sécurité des dépendances ne se limite pas aux CVE. Vous devez aussi savoir exactement ce qui a été installé, depuis quelle source, et si le serveur de production reçoit les mêmes versions que la CI.
Le fichier composer.lock est central. Il contient les versions résolues, les références de distribution et les métadonnées nécessaires à une installation reproductible. Il doit être versionné dans Git pour une application, revu dans les pull requests et déployé avec le code.
Les pratiques suivantes réduisent les surprises :
- ne modifiez pas manuellement
composer.lock; - refusez une pull request qui change un package sans expliquer la raison ;
- utilisez
composer validate --strictdans la CI ; - installez avec
composer install, jamais avec une résolution libre en production ; - archivez les artefacts de build ou construisez une image immuable ;
- limitez les tokens Composer à leurs permissions nécessaires ;
- supprimez les repositories Packagist alternatifs non justifiés.
Ajoutez la validation à votre pipeline :
composer validate --strict
composer install --no-interaction --prefer-dist --no-progress
composer audit --locked
Composer fournit des mécanismes de vérification autour des archives distribuées et des références consignées dans le lockfile. Toutefois, l’écosystème PHP ne repose pas uniformément sur un modèle de signatures cryptographiques de package comparable à certains registres centralisés. Il faut donc raisonner en couches : intégrité fournie par Composer, contrôle du dépôt Git, protection de la CI, revue des changements de lockfile et provenance des repositories.
Pour les sources VCS privées, épinglez les références lorsque c’est possible et évitez les branches mouvantes comme dev-main en production. Une dépendance installée depuis une branche peut changer sans que votre contrainte semver ne change, ce qui complique l’audit et la reproductibilité.
Une routine d’audit légère pour les projets PHP en production
Une méthode durable doit être assez simple pour survivre aux semaines chargées. L’objectif n’est pas de créer un comité sécurité pour chaque dépendance, mais de transformer les contrôles importants en réflexes automatisés.
Commencez par une routine de trente minutes par semaine pour les applications exposées :
- Consultez le résultat du pipeline planifié
composer audit --locked. - Vérifiez les changements de
composer.lockfusionnés depuis la dernière revue. - Classez les alertes selon l’exposition de l’application.
- Ouvrez un correctif ciblé pour les alertes applicables.
- Lancez les tests, puis préparez le déploiement.
- Consignez les exceptions avec une échéance.
Cette routine d’audit rejoint des pratiques plus larges de veille en cybersécurité applicative : le magazine industrie-du-futur.tv couvre régulièrement les enjeux numériques et technologiques des équipes de développement, utile pour situer l’audit de dépendances dans une hygiène de sécurité plus globale.
Sur une application Symfony mature, ajoutez quelques contrôles ciblés : exécutez les tests end-to-end pour les flux touchés, vérifiez les logs après déploiement et surveillez les erreurs sur les endpoints exposés. Le lien entre sécurité des dépendances et observabilité est concret : un patch de framework peut corriger une faille tout en révélant une incompatibilité de configuration. À ce sujet, l’entretien consacré à l’observabilité Symfony donne des pistes opérationnelles.
Pour un portefeuille de plusieurs applications, centralisez le résultat plutôt que les commandes. Chaque dépôt garde son composer audit, mais une tâche planifiée peut envoyer un résumé dans votre outil d’alerting ou créer automatiquement un ticket. Évitez toutefois de générer du bruit : une alerte sans propriétaire, sans échéance et sans contexte finit ignorée.
Enfin, ne retardez pas les migrations de runtime. Un composer.lock impeccable ne protège pas une application exécutée sur une version de PHP non maintenue. Vérifiez régulièrement la compatibilité entre votre version de PHP, votre framework et vos dépendances. Les évolutions expliquées dans notre guide PHP 8 montrent pourquoi cette maintenance fait partie intégrante de la sécurité applicative.
La formule efficace tient en peu de mots : lockfile versionné, installation reproductible, audit à chaque changement, audit planifié, mises à jour petites et testées, exceptions temporaires documentées. C’est moins spectaculaire qu’un grand audit annuel, mais beaucoup plus utile quand une vulnérabilité réelle apparaît.