← PHPStan et ingénierie logicielle sécurisée

Module 7 / 8 · 90 min

07. Règles personnalisées et limites de sécurité

Automatiser une politique locale sans promettre un audit complet.

Votre progression apparaîtra ici lorsque JavaScript est actif.

La progression et le meilleur score sont enregistrés uniquement dans ce navigateur. Aucun compte n’est nécessaire ; effacer les données du navigateur les supprime. Les durées de modules sont indicatives et incluent les exercices.

Comprendre le mécanisme

Une règle PHPStan personnalisée peut examiner des nœuds et des types pour signaler un motif interdit dans un contexte. Elle doit formuler une propriété précise et être testée avec cas acceptés et refusés. Interdire un appel direct à une fonction legacy peut être utile ; cela ne démontre pas à soi seul l’absence d’injection, de fuite de secrets ou de défaut d’autorisation dans tous les chemins.

Raisonner et vérifier

PHPStan standard n’est pas un analyseur complet de flux de données sensibles pour toutes les vulnérabilités. Des outils spécialisés, des extensions, la revue et les tests de sécurité ont des périmètres complémentaires. Évaluez faux positifs, faux négatifs et coût de maintenance avant de rendre une règle bloquante. Une règle ignorant un wrapper ou un appel dynamique doit l’indiquer dans ses limites.

Propriété contrôlée

Une règle doit exprimer une propriété précise. Une règle locale a un périmètre limité. Définissez précisément si une règle interdit une API, un argument ou un flux dangereux. Un diagnostic doit annoncer ce qu’il établit, sans promettre une sécurité générale à partir d’un motif syntaxique étroit.

Erreur fréquente à comprendre

Interdire une fonction prouve toute sécurité applicative.

Une règle locale a un périmètre limité.

Cas admis

Les fixtures doivent inclure du code accepté. Elle doit discriminer selon la politique. Une règle qui bloque tout semble détecter chaque défaut mais empêche aussi le code correct. Ajoutez des fixtures positives et négatives afin de mesurer les deux côtés de sa frontière de décision.

Erreur fréquente à comprendre

Une règle refusant tout est toujours correcte.

Elle doit discriminer selon la politique.

Angles morts

Les faux négatifs doivent être documentés. Les chemins non suivis peuvent conserver un risque. Documentez les formes que la règle ne reconnaît pas : appel dynamique, alias ou wrapper. Cette information permet aux réviseurs de compléter l’analyse au lieu de considérer le rapport vert comme une preuve exhaustive.

Erreur fréquente à comprendre

Une absence de diagnostic prouve toute absence de vulnérabilité.

Les chemins non suivis peuvent conserver un risque.

Wrappers et indirection

Un wrapper peut échapper à une règle syntaxique naïve. Les capacités de la règle doivent être vérifiées. Un helper peut appeler hash avec un nom d’algorithme reçu par paramètre. Une recherche de md5 comme nom de fonction ne voit pas forcément ce chemin ; réduisez le cas dans une fixture.

Erreur fréquente à comprendre

Tout appel indirect est automatiquement compris par toute règle.

Les capacités de la règle doivent être vérifiées.

Flux de données

PHPStan standard n’est pas un audit complet de taint. Le typage ne couvre pas toutes les vulnérabilités. Le typage standard ne suit pas automatiquement toute provenance d’une entrée jusqu’à SQL ou HTML. Utilisez requêtes paramétrées, encodage adapté et, lorsque pertinent, des outils spécialisés avec hypothèses connues.

Erreur fréquente à comprendre

Le niveau max suit automatiquement toutes les données sensibles.

Le typage ne couvre pas toutes les vulnérabilités.

Autorisation métier

La revue d’autorisation complète les règles de types. La politique métier demande une vérification dédiée. Une règle syntaxique peut vérifier qu’un appel de contrôle existe sans prouver que son sujet est correct. Testez aussi que l’acteur Bob ne peut modifier l’objet d’Alice avec une référence valide.

Erreur fréquente à comprendre

Des types cohérents prouvent tout droit d’objet.

La politique métier demande une vérification dédiée.

Maintenance

Le coût de maintenance d’une règle compte. Les API et hypothèses peuvent évoluer. L’AST et les contrats des bibliothèques peuvent évoluer. Versionnez la règle avec ses fixtures et vérifiez son comportement lors des mises à jour de PHPStan afin d’éviter des exceptions devenues trompeuses.

Erreur fréquente à comprendre

Une règle personnalisée reste correcte pour toute version future.

Les API et hypothèses peuvent évoluer.

Diagnostic utile

Un diagnostic doit être exploitable. La localisation et la propriété facilitent une action correcte. Indiquez l’emplacement, le risque précis et une correction possible. Un message vague comme code dangereux encourage les suppressions ; une explication testable aide à corriger la cause.

Erreur fréquente à comprendre

Un message sans contexte suffit à toute correction.

La localisation et la propriété facilitent une action correcte.

Stockage de mots de passe

Interdire MD5 ne valide pas tout stockage de mot de passe. D’autres mauvais choix restent possibles. Interdire MD5 laisse possibles un hash rapide différent, un coût inadapté ou des logs contenant le secret. Vérifiez algorithme adaptatif, vérification, rehash et cycle de stockage séparément.

Erreur fréquente à comprendre

L’absence de md5 prouve un coût adaptatif approprié.

D’autres mauvais choix restent possibles.

Outils complémentaires

Les outils spécialisés peuvent compléter l’analyse. Les contrôles ont des périmètres complémentaires. Analyse des dépendances, revue de secrets, tests d’injection et contrôle d’exploitation répondent à des risques distincts. Définissez la preuve attendue pour chacun plutôt qu’additionner des logos d’outils sans critère d’acceptation.

Erreur fréquente à comprendre

Installer PHPStan rend tous les autres contrôles inutiles.

Les contrôles ont des périmètres complémentaires.

Atelier guidé : lire, expliquer et vérifier le code

<?php
declare(strict_types=1);
$algorithm = 'md5';
$fingerprint = hash($algorithm, 'lab-data');
echo strlen($fingerprint);

L’extrait calcule un condensat MD5 via hash et une variable. Une règle limitée aux appels directs à md5 peut ne rien signaler. Écrivez une fixture pour ce cas, puis précisez le périmètre revendiqué par la règle. Même une détection améliorée ne valide pas tout le cycle des mots de passe.

Ce calcul reste un hash rapide. Le périmètre annoncé ne comprend pas ce motif. Interdire un seul nom de fonction ne couvre pas tous les usages. hash peut calculer cet algorithme.

Travail pratique : Écrivez la spécification d’une règle interdisant un appel legacy dans un module donné. Préparez un wrapper et un appel hors périmètre.

Critères de correction : Définissez les résultats attendus pour chaque fixture et vérifiez les diagnostics. Documentez ce que la règle ne suit pas, puis complétez avec une revue d’usage et des tests de migration.

Exemple commenté

Politique locale : interdire md5 dans le stockage de nouveaux mots de passe
Règle → fixtures positives/négatives → diagnostic → revue des limites

Le contrôle syntaxique local ne remplace pas l’inventaire des usages cryptographiques.

Exercice de mise en pratique

Écrivez la spécification d’une règle interdisant un appel legacy dans un module donné. Préparez un wrapper et un appel hors périmètre.

Voir une proposition de correction

Définissez les résultats attendus pour chaque fixture et vérifiez les diagnostics. Documentez ce que la règle ne suit pas, puis complétez avec une revue d’usage et des tests de migration.

Points de vérification

  • Propriété précise.
  • Fixtures acceptées et refusées.
  • Angles morts documentés.

Contrôle de connaissances

Cours associé : 07. Règles personnalisées et limites de sécurité ↗
Une règle interdisant md5 prouve-t-elle la sécurité de tous les mots de passe ?

Documentation de référence ↗

Validation du module

101 questions, objectif pédagogique de 75 %. Durée conseillée de 150 minutes, sans limite imposée. Les questions et les choix sont mélangés ; le corrigé apparaît après validation. Le contrôle rapide de la leçon et l’examen final du cours restent des exercices distincts.

Commencer ou reprendre les 101 questions →