Aller au contenu
FUTUR BTS FuturBTS
B3SLAM · chapitre 1 Chapitre offert

Sécuriser dès la conception

Ce que tu sauras faire : Intégrer la sécurité dans un projet de développement dès l'expression du besoin : écrire des exigences de sécurité vérifiables, modéliser les menaces d'une application avec STRIDE, appliquer les principes de conception sûre, protéger les données dès la conception, sécuriser la chaîne de développement et vérifier la conformité d'une application à un référentiel (OWASP Top 10, OWASP ASVS).

2 h de cours 10 exercices corrigés 10 questions de quiz

1. La sécurité dans le projet

Une application se protège mieux quand la sécurité est pensée avant la première ligne de code. Ce chapitre ouvre la partie SLAM du bloc 3 : il montre comment le développeur fait entrer la sécurité dans le besoin, dans la conception, dans le code et dans la chaîne qui livre l’application. Les failles elles-mêmes, l’authentification et les tests seront vus dans les trois chapitres suivants.

AUne demande d’Anaïs

Lundi 19 octobre 2026. Les spécifications du module de maintenance préventive de KerMaint ont été validées le 16 octobre par Franck Guillou, responsable technique des bâtiments de Kervanet (SLAM-01, ticket VEL-2026-4203). Le devis du 19 octobre attend la signature de Kervanet.

Anaïs Lecoq, responsable du pôle développement de Vellacor, réunit Sarah Cherif, alternante SLAM, et Romain Daguet, développeur :

« Les spécifications disent ce que le module doit faire, très peu ce qu’il ne doit pas permettre. Avant de coder, je veux les exigences de sécurité, une analyse des menaces et la liste de ce que nous vérifierons à la recette. Sarah s’en charge, Romain relira. »

BPourquoi dès la conception

Une faille découverte en production coûte cher : comprendre, corriger, tester, redéployer, parfois informer la CNIL. Et si personne n’a prévu de contrôler qui peut modifier un plan, personne ne le codera. L’OWASP le résume (Top 10:2025) : une implémentation parfaite ne répare pas une conception non sûre, car les contrôles nécessaires n’ont jamais été prévus.

Définition

Sécurité dès la conception

La sécurité dès la conception (security by design) consiste à traiter la sécurité comme une exigence du projet, au même titre que les fonctions attendues, depuis l’expression du besoin jusqu’à l’exploitation : on identifie les menaces, on fixe des exigences vérifiables, on choisit une architecture et des principes qui les satisfont, puis on vérifie à chaque étape qu’elles sont respectées.

On distingue deux types de défauts :

  • un défaut de conception : le contrôle nécessaire n’existe pas dans le modèle (aucune règle ne limite la modification des plans au responsable) ;
  • un défaut d’implémentation : le contrôle est prévu, mais mal codé (la règle existe, mais le code oublie de la vérifier sur une des pages).

Ce chapitre traite surtout des premiers ; les seconds sont l’objet de B3SLAM-02 et B3SLAM-03.

CLa sécurité à chaque étape

La sécurité n’est pas une phase à part : chaque étape du développement reçoit ses propres activités.

Le cycle de développement sécurisé
Besoin exigences de sécurité, cas d'abus B3SLAM-01 Conception menaces (STRIDE), principes de conception B3SLAM-01 Développement codage sûr, revue de code, dépendances B3SLAM-01 à 03 Tests tests de sécurité, audit de code B3SLAM-04 Déploiement configuration sûre, secrets, environnements B3SLAM-01, 04 Exploitation journaux, veille, correctifs, incidents B3SLAM-04 chaque étape du développement reçoit ses activités de sécurité retour d'expérience : un incident ou une faille nourrit les exigences du projet suivant
Les six étapes du développement (vues en SLAM-01 et B1-10) reçoivent chacune des activités de sécurité ; le chapitre qui les traite est indiqué sous chaque étape. Le retour d'expérience de l'exploitation (incidents, failles découvertes) nourrit les exigences des projets suivants.

En Scrum, ces activités se répètent à chaque sprint (B1-10).

À retenir

Ce que le référentiel attend de toi

  • Participer à la vérification des éléments qui font la qualité d’un développement (C3B.5-a).
  • Prendre en compte la sécurité dans un projet de développement (C3B.5-b).
  • Mettre en œuvre et vérifier la conformité d’une application et de son développement à un référentiel, une norme ou un standard de sécurité (C3B.5-c).

Tu participes : tu proposes, appliques, vérifies et documentes ; l’architecture et l’acceptation des risques reviennent au responsable du pôle et au client.

2. Écrire les exigences de sécurité

Une exigence de sécurité dit ce que l’application doit garantir, et comment on vérifiera qu’elle le garantit. Elle s’écrit dans le cahier des charges et dans les récits utilisateur, comme les exigences fonctionnelles. Sans elle, la sécurité reste une intention que personne ne peut contrôler.

AD’où viennent les exigences

Les exigences de sécurité d’un projet ne s’inventent pas : elles se déduisent de cinq sources.

Les sources des exigences de sécurité du module préventif
Source Ce qu’elle apporte Exemple pour le module
Analyse des risques (B3-01) les besoins DICP des données et les risques prioritaires KerMaint : disponibilité 3, intégrité 3 ; un contrôle de sécurité oublié engage la responsabilité de Kervanet
Règles de gestion du client les limites métier à faire respecter RG8 : seul le profil Responsable crée ou modifie un plan
Réglementation (B3-02, CEJMA-08) données personnelles, conservation, traçabilité le nom du technicien qui valide un contrôle est une donnée personnelle
Contrat (CEJMA-03, CEJMA-04) engagements du prestataire accord de sous-traitance : journalisation, aucune donnée réelle en test
Référentiels (partie 7) exigences types déjà rédigées et éprouvées OWASP ASVS : contrôle des droits côté serveur, messages d’erreur génériques

S’y ajoute la modélisation des menaces de la partie 3 : elle fait apparaître des exigences que personne n’avait formulées.

BUne exigence vérifiable

Une exigence floue (« le module doit être sécurisé ») ne sert à rien : on ne peut ni la coder ni la tester. Une bonne exigence de sécurité a les mêmes qualités qu’une exigence non fonctionnelle de SLAM-01 : elle est précise, vérifiable, justifiée et identifiée.

Définition

Exigence de sécurité

Une exigence de sécurité est une condition que l’application doit respecter pour protéger la disponibilité, l’intégrité, la confidentialité ou la traçabilité de ses données et de ses fonctions. Elle porte un identifiant, une formulation testable, sa justification (risque, règle, texte) et le moyen de la vérifier.

Des exigences floues aux exigences vérifiables
Formulation floue Exigence vérifiable Vérification
« Les plans sont protégés. » EXS-01 — Seul un utilisateur du profil Responsable peut créer, modifier ou désactiver un plan ; le contrôle est fait par le serveur à chaque requête ; tout autre profil reçoit un refus. test avec un compte Technicien qui appelle directement l’action (doit être refusé)
« Les saisies sont contrôlées. » EXS-02 — Chaque champ reçu est vérifié par le serveur selon une liste de valeurs ou de formats autorisés (périodicité 1, 3, 6 ou 12 ; date AAAA-MM-JJ existante) ; tout champ non prévu fait rejeter la requête. jeu d’essai de valeurs invalides et d’un champ ajouté
« On garde une trace. » EXS-03 — Chaque validation de contrôle est enregistrée avec le compte, la date et l’heure en temps universel, l’intervention et le résultat ; le journal ne contient ni mot de passe ni donnée inutile. lecture du journal après un scénario de recette
« Pas d’erreur visible. » EXS-04 — En cas d’erreur inattendue, l’utilisateur voit un message générique et une référence ; le détail technique n’apparaît que dans le journal. provoquer une erreur de base en recette
« Le code est propre. » EXS-05 — Aucun secret (mot de passe, clé, jeton) n’est présent dans le dépôt ; les secrets de production sont distincts de ceux de la recette. contrôle automatique du dépôt, revue
« Les bibliothèques sont à jour. » EXS-06 — Aucun composant livré ne porte une vulnérabilité publiée au-delà du délai fixé par la politique de Vellacor (7 jours si critique, 30 jours si élevée). contrôle des dépendances dans le pipeline
Astuce

Pour vérifier qu’une exigence est bien écrite, demande-toi : « Quel test me dira qu’elle n’est pas respectée ? » Si tu ne trouves pas de test, l’exigence est encore trop floue.

CLes exigences dans les récits utilisateur

En agilité, les besoins s’écrivent en récits utilisateur avec des critères d’acceptation (SLAM-01). La sécurité s’y intègre de deux façons.

1. Des critères d’acceptation négatifs. À chaque récit, on ajoute au moins un scénario qui doit échouer : droit insuffisant, valeur hors limite, donnée d’un autre établissement.

Exemple

US1 complété par Sarah

US1 — En tant que responsable technique, je veux créer un plan préventif pour un équipement afin de ne plus dépendre du tableur.

Scénario de sécurité 1 — Étant donné Mathis Le Goff connecté avec le profil Technicien, quand il envoie au serveur une demande de création de plan (même sans passer par l’écran), alors la demande est refusée, aucun plan n’est créé et le refus est journalisé.

Scénario de sécurité 2 — Étant donné Franck Guillou connecté avec le profil Responsable, quand il saisit une périodicité de 2 mois, alors la création est refusée avec le message « Périodicité : 1, 3, 6 ou 12 mois ».

2. Des récits d’attaquant. Un cas d’abus (misuse case, ou récit d’attaquant) décrit ce qu’une personne malveillante, ou simplement maladroite, voudrait faire avec l’application : « En tant que technicien pressé, je veux marquer « conforme » un contrôle sans l’avoir fait, afin de finir ma tournée plus vite. » On ne réalise pas ce récit : on écrit les exigences qui l’empêchent ou qui le rendent visible (traçabilité EXS-03, durée minimale saisie, relecture par le responsable).

Piège

« Les scénarios négatifs, on verra en recette. » C’est trop tard : si le récit ne prévoit pas le refus, le développeur ne le code pas, et la recette découvre une absence de contrôle, c’est-à-dire un défaut de conception. Un récit n’est « prêt » (definition of ready) que s’il a ses critères de sécurité.

DLes exigences dans le cahier des charges

Dans un projet plus classique, le cahier des charges comporte une section « Exigences de sécurité », numérotée comme les autres. Elle sert de base au contrat (obligation de conseil du prestataire, CEJMA-03) et à la recette : une exigence non satisfaite est une réserve au procès-verbal.

Méthode

Rédiger les exigences de sécurité d'un projet

  1. Partir des données et de leurs besoins DICP (B3-01) ; repérer les données personnelles (B3-02).
  2. Lister les acteurs et leurs droits (matrice des droits).
  3. Modéliser les menaces (partie 3) et en tirer les exigences qui manquent.
  4. Compléter avec un référentiel (OWASP ASVS, partie 7) au niveau choisi.
  5. Rédiger chaque exigence : identifiant, formulation testable, justification, vérification.
  6. Rattacher chaque exigence aux récits et au cahier de recette, puis faire valider et versionner.

3. Modéliser les menaces

Modéliser les menaces, c’est se demander méthodiquement ce qui peut mal tourner dans l’application qu’on va construire. On dessine ses flux de données, on repère les frontières où la confiance change, puis on passe chaque élément au crible de six familles de menaces : STRIDE.

AQuatre questions

La modélisation des menaces (threat modeling) se fait sur la conception, avant le code, et se refait à chaque évolution importante. Elle répond à quatre questions simples :

  1. Que construit-on ? On représente l’application : ses utilisateurs, ses traitements, ses données, ses échanges.
  2. Que peut-il mal se passer ? On cherche les menaces, élément par élément.
  3. Que fait-on contre chaque menace ? On choisit une mesure, qui devient une exigence (partie 2).
  4. A-t-on bien travaillé ? On vérifie que chaque menace retenue a une mesure, un responsable et un test.
À retenir

La modélisation des menaces est l’analyse de risques du développeur : EBIOS RM (B3-01) part des missions et des attaquants, elle part du schéma de l’application. Elle alimente les scénarios opérationnels de l’atelier 4 d’EBIOS RM et utilise les mêmes échelles (gravité × vraisemblance).

BLe diagramme de flux de données

Pour répondre à la première question, on dessine un diagramme de flux de données (data flow diagram, DFD). Il n’utilise que quatre symboles :

  • les entités externes (rectangles) : personnes ou systèmes hors de l’application (le technicien, la messagerie) ;
  • les traitements (formes arrondies) : les parties de l’application qui transforment les données ;
  • les stockages (deux traits) : bases, fichiers, journaux ;
  • les flux (flèches) : les données qui circulent.

S’y ajoutent les frontières de confiance, en pointillés.

Définition

Frontière de confiance

Une frontière de confiance (trust boundary) sépare deux zones qui n’ont pas le même niveau de confiance : la tablette d’un utilisateur et le serveur, l’application et sa base, le réseau interne et Internet. Toute donnée qui franchit une frontière en entrant doit être contrôlée ; toute donnée qui la franchit en sortant doit être limitée à ce qui est nécessaire.

Les flux de données du module de maintenance préventive
Technicien tablette Responsable technique, poste Administrateur Vellacor Application KerMaint Apache, PHP KV-KERMAINT Tâche nocturne 5 h (RG4) Base MariaDB kermaint Journal de KerMaint Serveur de messagerie saisies plans SSH par clé SQL courriel frontière 1 frontière 2 compte kermaint_app qui, quoi, quand les flèches qui traversent une frontière de confiance sont celles à examiner en premier avec STRIDE
Les utilisateurs envoient leurs saisies à l'application à travers la frontière 1 (réseau des sites vers le serveur KV-KERMAINT). L'application écrit dans la base et le journal ; la tâche nocturne écrit dans la base et envoie les courriels, à travers la frontière 2. Chaque flèche qui franchit une frontière est un point d'entrée possible pour une attaque.

CLes six familles STRIDE

STRIDE est une grille proposée par Microsoft pour ne rien oublier : chaque lettre désigne une famille de menaces, et chaque famille s’attaque à une propriété de sécurité.

Les six familles de menaces STRIDE
Lettre Menace Propriété atteinte (lien avec DICP, B3-01) Famille de mesures
S Spoofing : usurpation d’identité (se faire passer pour un autre utilisateur ou système) authenticité authentification (B3SLAM-03, B3-05)
T Tampering : falsification (modifier une donnée, une requête, un fichier) intégrité (I) validation, contrôle des droits, signature (B3-06)
R Repudiation : répudiation (nier une action, faute de trace fiable) preuve (P) journalisation protégée, comptes nominatifs
I Information disclosure : divulgation confidentialité (C) contrôle d’accès, minimisation, chiffrement, erreurs génériques
D Denial of service : déni de service disponibilité (D) limites, quotas, contrôles de volume
E Elevation of privilege : élévation de privilèges (obtenir des droits non accordés) autorisation refus par défaut, contrôle côté serveur, moindre privilège
Astuce

Pour ne rien oublier, applique STRIDE élément par élément du schéma. Les entités externes subissent surtout S et R ; les flux, T, I et D ; les stockages, T, I et D (et R pour les journaux) ; les traitements, les six familles.

DSTRIDE appliqué au module

Sarah et Romain passent une heure sur le schéma. Ils retiennent huit menaces et les évaluent avec les échelles de Vellacor (B3-01 : gravité et vraisemblance de 1 à 4, criticité = gravité × vraisemblance).

Les menaces retenues pour le module préventif (séance du 19/10/2026), classées par criticité puis par gravité
Code Menace Élément du schéma G V Criticité Mesure (exigence)
E1 Un technicien appelle directement l’adresse de l’action « modifier un plan » application 3 3 9 élevé contrôle des droits côté serveur, refus par défaut (EXS-01)
T1 La requête de validation d’un contrôle est modifiée (autre intervention, point marqué conforme) flux saisies 3 2 6 modéré validation serveur, vérification que l’intervention appartient au technicien (EXS-02, B3SLAM-03)
R1 Un technicien conteste avoir validé un contrôle journal 3 2 6 modéré journal nominatif, horodaté, protégé (EXS-03)
S1 Une session reste ouverte sur une tablette partagée et quelqu’un d’autre valide entité technicien 3 2 6 modéré verrouillage de la tablette, durée de session (B3SLAM-03)
T2 La bibliothèque d’export PDF livrée est vulnérable ou piégée traitement 3 2 6 modéré inventaire et contrôle des dépendances (EXS-06)
I1 Une erreur affiche la requête SQL, des chemins ou des identifiants réponses de l’application 2 3 6 modéré erreurs génériques, détail au journal (EXS-04)
I2 Le registre PDF d’un établissement est lisible en devinant son adresse réponses de l’application 2 2 4 modéré contrôle d’accès sur chaque export (EXS-01)
D1 La génération nocturne tourne en boucle et crée des milliers d’interventions tâche nocturne 2 2 4 modéré contrôle d’unicité (RG4) et plafond par nuit avec alerte

E1 reçoit la vraisemblance 3 parce qu’un oubli de contrôle sur une seule page suffit ; I1, parce qu’un journal de débogage resté actif a déjà fait tomber KerMaint le 7 octobre (B1-06). Toutes les menaces sont au moins modérées : aucune n’est acceptée sans mesure.

Méthode

Modéliser les menaces d'une application

  1. Dessiner le diagramme de flux de données : entités, traitements, stockages, flux.
  2. Tracer les frontières de confiance et repérer les flux qui les franchissent.
  3. Appliquer STRIDE à chaque élément, en commençant par les flux qui franchissent une frontière.
  4. Décrire chaque menace retenue en une phrase (qui, comment, quel élément, quel effet).
  5. Évaluer gravité et vraisemblance avec les échelles de l’organisation ; classer.
  6. Associer à chaque menace une mesure, traduite en exigence testable, et un responsable.
  7. Conserver le modèle avec le projet et le mettre à jour à chaque évolution importante.
Piège

Une modélisation des menaces n’est pas une liste d’attaques célèbres : elle porte sur cette application et ces flux. « Injection SQL » n’est utile que si l’on dit où, et ce qu’elle permettrait ici.

4. Concevoir de façon sûre

Quelques principes de conception, connus depuis longtemps, évitent la plupart des défauts de conception : donner le moins de droits possible, empiler les contrôles, refuser par défaut, contrôler ce qui entre, ne rien laisser fuir dans les erreurs, garder les secrets hors du code. Cette partie les applique au code PHP de KerMaint.

ALe moindre privilège dans l’application

Le moindre privilège (B3-05) s’applique aussi aux comptes que l’application utilise elle-même : le compte de base kermaint_app lit, ajoute et modifie, sans pouvoir supprimer de table ni gérer les droits ; la tâche nocturne ne fait que lire les plans et créer des interventions ; le jeton d’une plateforme partenaire de KerResa ne donne accès qu’aux opérations de son contrat (B3SLAM-03) ; le serveur web n’écrit que dans les dossiers prévus, jamais dans le code.

Question à poser pour chaque composant : « S’il était compromis, que ferait l’attaquant avec ses droits ? »

BLa défense en profondeur

La défense en profondeur (définie en B3-04 pour les postes) s’applique aussi à l’intérieur d’une application : une requête traverse plusieurs contrôles indépendants, et aucun ne suppose que le précédent a fonctionné.

Les couches de contrôle d'une requête
requête Valider normaliser, liste blanche Authentifier qui appelle ? (B3SLAM-03) Autoriser refus par défaut Traiter règles de gestion Accéder requête préparée, compte limité données Échec à une étape : refus, message générique avec une référence, détail dans le journal Secrets lus dans l'environnement Journal sans mot de passe ni donnée inutile chaque couche peut arrêter la requête ; aucune ne compte sur la précédente
Une requête est validée, l'appelant authentifié, ses droits vérifiés avec refus par défaut, puis elle est traitée et accède aux données par une requête préparée avec un compte limité. Un échec à n'importe quelle étape conduit au même résultat : refus, message générique, détail dans le journal.

Exemple : même si la validation laissait passer une valeur étrange, la requête préparée (B1-08) l’empêcherait d’être interprétée comme du SQL ; même si une requête SQL était détournée, le compte limité empêcherait de supprimer une table.

CLa sécurité par défaut et l’échec sûr

Définition

Sécurité par défaut et échec sûr

  • La sécurité par défaut (secure by default) : le réglage livré, sans action de l’utilisateur, est le plus sûr raisonnable. Une fonction dangereuse est désactivée tant qu’on ne l’active pas ; un droit n’existe que s’il a été accordé.
  • L’échec sûr (fail safe, ou fail closed) : quand un contrôle ne peut pas aboutir (erreur, donnée manquante, service injoignable), l’application refuse au lieu de laisser passer.

Sarah code la matrice des droits du module en liste blanche : ce qui n’est pas écrit est interdit. La règle RG8 de SLAM-01 devient une ligne de la matrice.

<?php
declare(strict_types=1);

// Matrice des droits du module (liste blanche) : ce qui n'est pas écrit est interdit
const DROITS = [
    'Technicien'  => ['voir_echeances', 'saisir_controle'],
    'Responsable' => ['voir_echeances', 'saisir_controle', 'gerer_plan', 'exporter_registre'],
];

function peutFaire(?string $profil, string $action): bool
{
    // Refus par défaut : profil absent, inconnu ou action non listée
    return in_array($action, DROITS[$profil] ?? [], true);
}

function autoriser(callable $lireProfil, string $action): bool
{
    try {
        return peutFaire($lireProfil(), $action);
    } catch (Throwable $e) {
        error_log('contrôle des droits impossible : ' . $e->getMessage());
        return false;                 // en cas d'erreur, on refuse (échec sûr)
    }
}

Résultats relevés le 20/10/2026 sur la machine de laboratoire LAB-UBU01 (Ubuntu 24.04 LTS, PHP 8.3) :

Responsable  gerer_plan        autorisé
Technicien   gerer_plan        refusé
Technicien   saisir_controle   autorisé
Consultation voir_echeances    refusé
(aucun)      voir_echeances    refusé
Responsable  supprimer_plan    refusé
annuaire en panne, gerer_plan : refusé

Le profil Consultation, qui n’apparaît pas dans la matrice du module, est refusé sans qu’on ait eu à l’écrire ; une action oubliée (supprimer_plan) aussi ; et quand la lecture du profil échoue, la réponse est « non ».

Piège

Écrire return $profil != 'Technicien'; (« tout le monde sauf le technicien ») est une liste noire : le jour où un profil est ajouté (Consultation, Prestataire), il obtient automatiquement le droit. La liste blanche se trompe dans le sens sûr : un oubli bloque un utilisateur légitime, qui le signale, au lieu d’ouvrir un droit en silence.

La gestion complète des habilitations dans le code (profils rattachés à la session, contrôle de l’objet consulté) est traitée en B3SLAM-03.

DValider les entrées

B1-08 t’a appris à contrôler un formulaire côté serveur avec filter_var. Du point de vue de la conception, trois idées s’ajoutent.

1. Valider à la frontière, au même endroit. Toute donnée qui franchit une frontière de confiance (formulaire, paramètre d’adresse, appel d’API, fichier importé) passe par une couche de validation commune ; le reste du code ne manipule que des valeurs validées.

2. Normaliser avant de valider. Une même information peut s’écrire de plusieurs façons (espaces superflus, caractère accentué codé de deux manières en Unicode) : on la ramène d’abord à une forme canonique unique, puis on la contrôle.

3. Valider par liste blanche. On décrit ce qui est autorisé (valeurs d’une liste, format, intervalle, longueur), plutôt que d’essayer d’énumérer ce qui est interdit, et l’on refuse les champs non prévus. Ce dernier point empêche l’affectation de masse (mass assignment) : un utilisateur qui ajoute à sa requête un champ actif=0 ne doit pas pouvoir désactiver un plan par ce biais.

Définition

Validation par liste blanche

La validation par liste blanche (ou validation positive) n’accepte une donnée que si elle correspond à ce qui est explicitement attendu : une valeur d’une liste fermée, un format précis, un intervalle. Tout le reste est refusé. Elle s’oppose à la liste noire, qui refuse seulement des valeurs connues comme dangereuses et laisse passer tout ce qu’on n’a pas prévu.

La fonction de Sarah pour la création d’un plan (extrait : les contrôles 2 et 3 ne sont pas reproduits) :

<?php
declare(strict_types=1);

const CHAMPS_PLAN = ['id_equip', 'libelle', 'periodicite', 'premiere_echeance'];
const PERIODICITES = [1, 3, 6, 12];          // RG2 : périodicité en mois

function normaliserTexte(string $texte): string
{
    $texte = Normalizer::normalize($texte, Normalizer::FORM_C);   // forme Unicode unique
    return trim(preg_replace('/\s+/u', ' ', $texte));            // espaces uniformisés
}

function validerPlan(array $entree): array
{
    $erreurs = [];
    // 1. Refuser tout champ non prévu (pas d'affectation de masse)
    $inconnus = array_diff(array_keys($entree), CHAMPS_PLAN);
    if ($inconnus !== []) {
        $erreurs['_'] = 'Champ non prévu : ' . implode(', ', $inconnus);
    }
    // 2 et 3. Identifiant d'équipement (entier >= 1) et libellé normalisé (3 à 60 caractères,
    //        sans caractère de contrôle) : contrôles sur le même modèle, non reproduits ici
    // 4. Périodicité : valeur de la liste blanche seulement
    $per = filter_var($entree['periodicite'] ?? null, FILTER_VALIDATE_INT);
    if ($per === false || !in_array($per, PERIODICITES, true)) {
        $erreurs['periodicite'] = 'Périodicité : 1, 3, 6 ou 12 mois.';
    }
    // 5. Date au format ISO 8601 (AAAA-MM-JJ), qui existe vraiment
    $d = DateTimeImmutable::createFromFormat('!Y-m-d', (string) ($entree['premiere_echeance'] ?? ''));
    if ($d === false || $d->format('Y-m-d') !== ($entree['premiere_echeance'] ?? '')) {
        $erreurs['premiere_echeance'] = 'Date au format AAAA-MM-JJ.';
    }
    if ($erreurs !== []) {
        return [null, $erreurs];
    }
    return [['id_equip' => $id, 'libelle' => $libelle, 'periodicite' => $per,
             'premiere_echeance' => $d->format('Y-m-d')], []];   // valeurs propres et typées
}

Le jeu d’essai, relevé sur LAB-UBU01 le 20/10/2026 :

A correct         : accepté {"id_equip":12,"libelle":"Entretien annuel chaudière","periodicite":12,"premiere_echeance":"2026-11-16"}
B periodicite 2   : refusé {"periodicite":"Périodicité : 1, 3, 6 ou 12 mois."}
C date 31/11      : refusé {"premiere_echeance":"Date au format AAAA-MM-JJ."}
D champ en trop   : refusé {"_":"Champ non prévu : actif"}
E id negatif      : refusé {"id_equip":"Équipement invalide."}
avant : false (10 et 11 octets)
après : true

Le cas A montre la normalisation (espaces retirés, identifiant converti en entier) ; le cas C, qu’une date doit exister ; le cas D, le refus d’un champ non prévu. Les deux dernières lignes montrent pourquoi normaliser : « chaudière » peut s’écrire avec un « è » en un seul caractère (10 octets) ou avec un « e » suivi d’un accent combinant (11 octets) ; sans forme canonique, deux libellés identiques à l’écran seraient différents pour le programme (doublons, contrôles d’unicité contournés).

Piège

Valider ne remplace ni la requête préparée ni htmlspecialchars (B1-08) : une donnée validée peut contenir une apostrophe (« Contrôle de l’ascenseur »). La validation vérifie le métier ; l’encodage en sortie protège les interpréteurs (B3SLAM-02).

EGérer les erreurs sans fuite

Une erreur mal gérée fait deux dégâts : elle renseigne l’attaquant (nom de la base, requête, chemins des fichiers, versions) et elle peut laisser l’application dans un état incohérent (une opération à moitié faite). L’OWASP a créé en 2025 une catégorie dédiée à ce problème (partie 7).

Voici ce qu’il ne faut pas faire (extrait d’un prototype, à ne pas reproduire) :

// À NE PAS FAIRE : erreurs affichées et message technique renvoyé à l'utilisateur
ini_set('display_errors', '1');
try { /* ... */ } catch (PDOException $e) { echo 'Erreur : ' . $e->getMessage(); }

Le message d’une exception de base de données révèle souvent le compte, le serveur ou la requête. Sarah écrit un gestionnaire de dernier recours, chargé par chaque page :

<?php
declare(strict_types=1);

// Réglages de production : rien d'interne n'est affiché, tout est journalisé
ini_set('display_errors', '0');
ini_set('log_errors', '1');

const JOURNAL = __DIR__ . '/kermaint_erreurs.log';   // en production : /var/log/kermaint/

function journaliser(string $reference, Throwable $e): void
{
    $ligne = sprintf("%s ref=%s %s: %s (%s:%d)\n",
        gmdate('Y-m-d\TH:i:s\Z'), $reference, get_class($e),
        str_replace(["\r", "\n"], ' ', $e->getMessage()),   // une ligne par erreur
        basename($e->getFile()), $e->getLine());
    file_put_contents(JOURNAL, $ligne, FILE_APPEND | LOCK_EX);
}

// Gestionnaire de dernier recours : toute exception non traitée arrive ici
set_exception_handler(function (Throwable $e): void {
    $reference = bin2hex(random_bytes(4));          // relie l'écran au journal
    journaliser($reference, $e);
    if (PHP_SAPI !== 'cli') {
        http_response_code(500);
    }
    echo "Une erreur est survenue. Merci de réessayer plus tard.\n";
    echo "Si le problème persiste, communique au support la référence $reference.\n";
});

On simule un refus de connexion de la base (LAB-UBU01, 20/10/2026). Ce que voit l’utilisateur :

Une erreur est survenue. Merci de réessayer plus tard.
Si le problème persiste, communique au support la référence 5b1235b6.

Ce qu’enregistre le journal, lisible par les seuls administrateurs :

2026-10-20T21:03:45Z ref=5b1235b6 RuntimeException: SQLSTATE[HY000] [1045] Access denied for user 'kermaint_app'@'localhost' (using password: YES) (test_erreurs.php:6)

La référence aléatoire relie l’appel de l’utilisateur à la ligne du journal, sans rien révéler. L’heure est en temps universel (Z), pour recouper plusieurs serveurs (B3-07). Les retours à la ligne sont remplacés : une donnée ne peut pas fabriquer une fausse ligne de journal.

Méthode

Concevoir la gestion des erreurs

  1. Désactiver l’affichage des erreurs en production (display_errors à 0) et tout mode de débogage ; le vérifier à chaque mise en production.
  2. Traiter les erreurs prévisibles là où elles se produisent (saisie invalide, élément introuvable), avec un message utile mais sans détail technique.
  3. Prévoir un gestionnaire de dernier recours pour toutes les autres : message générique, référence, détail au journal.
  4. Échouer de façon sûre : annuler l’opération entière (transaction) plutôt que de laisser des données à moitié écrites ; refuser l’accès si un contrôle échoue.
  5. Journaliser sans mot de passe, sans jeton, sans donnée personnelle inutile (B3-02).
  6. Tester à la recette : provoquer une erreur de base, une saisie invalide, un service injoignable.

FGarder les secrets hors du code

Un secret est une information qui donne un accès : mot de passe de base de données, clé d’API, jeton d’une plateforme partenaire, secret HMAC des notifications de KerResa (B3-06), clé de signature des livraisons. B1-08 a posé la première règle : les paramètres de connexion sont hors de la racine web, et le mot de passe n’est jamais dans le dépôt. La conception sûre va plus loin.

Les règles de gestion des secrets d’une application
Règle Pourquoi
Aucun secret dans le code ni dans le dépôt, même privé, même « pour tester » le dépôt est copié sur chaque poste de développeur, dans les sauvegardes, chez un futur prestataire ; et l’historique garde tout
Secrets rangés dans un gestionnaire de secrets et fournis au serveur au déploiement un seul endroit protégé, avec des droits et une traçabilité
Un secret différent par environnement (développement, recette, production) un secret de recette divulgué n’ouvre pas la production
Droits d’accès minimaux aux secrets seul le service qui l’utilise peut le lire
Rotation à échéance, au départ d’une personne qui le connaissait, et immédiatement en cas de fuite limiter la durée d’utilisation d’un secret volé
Démarrage refusé si un secret manque pas de valeur « temporaire » qui reste en production ; pas de page de diagnostic (phpinfo()) qui afficherait l’environnement

Chez Vellacor, le mot de passe du compte kermaint_app est rangé dans le gestionnaire de secrets et fourni au serveur sous forme de variable d’environnement, définie dans un fichier de configuration du service lisible par le seul administrateur. Le code se contente de la lire :

<?php
declare(strict_types=1);

// Les secrets ne sont jamais dans le code : ils viennent de l'environnement du serveur,
// alimenté depuis le gestionnaire de secrets (une valeur différente par environnement).
function secret(string $nom): string
{
    $valeur = getenv($nom);
    if ($valeur === false || $valeur === '') {
        // Sécurité par défaut : sans secret, l'application refuse de démarrer
        throw new RuntimeException("Configuration incomplète : variable $nom absente.");
    }
    return $valeur;
}

function parametresBase(): array
{
    return [
        'dsn'          => 'mysql:host=localhost;dbname=kermaint;charset=utf8mb4',
        'utilisateur'  => 'kermaint_app',
        'mot_de_passe' => secret('KERMAINT_DB_PASSWORD'),
    ];
}

Sur LAB-UBU01, sans puis avec la variable (valeur fictive Exemple-2026!) :

démarrage refusé : Configuration incomplète : variable KERMAINT_DB_PASSWORD absente.
configuration chargée pour kermaint_app (mot de passe de 13 caractères, non affiché)

GUn code modulaire et robuste

Un code organisé, lisible et prévisible est plus facile à vérifier, donc plus sûr.

Les bonnes pratiques de développement au service de la sécurité
Pratique Ce qu’elle apporte à la sécurité
Code modulaire : une fonction, une responsabilité ; les contrôles regroupés dans des modules communs (validation.php, droits.php, erreurs.php, config.php) un contrôle écrit, testé et corrigé à un seul endroit, appliqué partout
Normes de codage communes (chez Vellacor : PER Coding Style 3.1 du PHP-FIG, qui remplace PSR-12) le code se relit vite ; les écarts sautent aux yeux à la revue
Typage et comparaisons stricts (declare(strict_types=1), ===, in_array(…, true)) pas de conversion surprenante ("0", "", null) qui fausse un contrôle
Données normalisées : UTF-8 en forme NFC, dates AAAA-MM-JJ (ISO 8601), heures des journaux en temps universel, montants en centimes entiers pas d’ambiguïté entre deux écritures d’une même valeur
Robustesse : transactions, gestionnaire d’erreurs, valeurs par défaut sûres pas d’arrêt dans un état incohérent
Tests automatiques des règles et des refus (SLAM-10, B3SLAM-04) une régression de sécurité est détectée avant la livraison

5. Protéger les données dès la conception

Le RGPD fait de la protection des données une obligation de conception : les réglages par défaut d’une application doivent déjà être protecteurs. Les principes et les outils ont été vus en B3-02 et CEJMA-08 ; cette partie montre comment le développeur les transforme en choix de conception, et comment il prépare l’application à l’exercice des droits des personnes.

ACe que dit l’article 25

Tu connais le principe (art. 25 RGPD, à jour au 20/10/2026, CEJMA-08) : le responsable du traitement (Kervanet) protège les données dès la conception et par défaut (seules les données nécessaires, en quantité, étendue, durée et accessibilité). Vellacor, sous-traitant, l’y aide : son obligation de conseil lui interdit de livrer une application impossible à rendre conforme (CEJMA-08).

Pour le développeur, la question devient : quels réglages, quels champs, quels droits ma conception impose-t-elle par défaut ?

BDu principe aux choix de conception

La protection des données par défaut, traduite en choix de conception
Dimension (art. 25) Choix de conception par défaut (exemples dans KerMaint)
Quantité de données seulement les champs nécessaires : l’identifiant du technicien, pas son téléphone ; liste de motifs plutôt que texte libre (B3-02)
Étendue du traitement le journal des validations sert à la traçabilité des contrôles, pas à mesurer la productivité des techniciens
Durée de conservation la purge est livrée avec le produit, planifiée et testée (journaux : 12 mois glissants, B3-02)
Accessibilité droits minimaux par défaut ; tableau de bord de la direction sans nom (vue de B3-05)
Pseudonymisation, chiffrement prévus dans l’architecture : exports pseudonymisés, HTTPS (B3-02, B3-06)
Données de test aucune donnée réelle hors production : recette anonymisée sur KV-RECETTE, jeux d’essai fictifs
Exemple

Pour le module préventif, Sarah ajoute deux exigences à la liste de la partie 2 : EXS-07 — « Les écrans du module n’affichent ni le téléphone ni l’adresse des techniciens ; seul le nom de celui qui a validé un contrôle apparaît dans le registre » ; EXS-08 — « Les journaux de validation sont purgés après 12 mois ; la purge est journalisée et testée en recette ». Elle les rattache au registre des traitements de Kervanet, tenu par le DPO.

CLes droits des personnes dans l’application

Les personnes concernées (clients, salariés) peuvent accéder à leurs données, les faire rectifier, effacer, limiter, s’opposer à un traitement ou les récupérer (CEJM-14). Kervanet doit répondre dans un délai d’un mois, et Vellacor exécute la partie technique sous 5 jours ouvrés (B3-02). Ces délais ne peuvent être tenus que si l’application a été conçue pour les droits.

Concevoir l’application pour les droits des personnes
Droit Ce que la conception doit prévoir
Accès et portabilité une fonction qui rassemble toutes les données d’une personne, dans un format lisible par machine (JSON, CSV)
Rectification une modification tracée, propagée aux copies
Effacement une suppression ou anonymisation qui respecte les obligations de conservation (factures, fiches de police) et les clés étrangères
Limitation un état « gelé » qui empêche tout traitement sauf la conservation
Opposition à la prospection une case de consentement et une liste d’opposition consultée à chaque import

Chaque droit devient donc un récit (« En tant qu’administrateur fonctionnel, je veux exporter toutes les données d’un client… ») avec ses critères d’acceptation : une fonction à développer et à tester. L’exécution technique d’une demande est décrite en B3-02.

DLa sécurité par défaut dans les textes

Point juridique

Le règlement européen sur la cyberrésilience — à jour au 21/10/2026

Le principe. Le règlement (UE) 2024/2847 du 23 octobre 2024, dit règlement sur la cyberrésilience (Cyber Resilience Act), impose aux fabricants de produits comportant des éléments numériques mis à disposition sur le marché de l’Union, logiciels compris, des exigences essentielles de cybersécurité. Parmi elles (annexe I) : des produits conçus et développés pour garantir un niveau de cybersécurité adapté aux risques, mis sur le marché sans vulnérabilité exploitable connue, avec une configuration sécurisée par défaut, et qui ne traitent que les données nécessaires.

Les dates. Le règlement est en vigueur depuis le 10/12/2024 ; il s’applique à partir du 11/12/2027, sauf l’obligation de signaler les vulnérabilités activement exploitées et les incidents graves (art. 14), applicable depuis le 11/09/2026 (art. 71).

Ce que cela veut dire concrètement. « Mettre à disposition sur le marché », c’est fournir un produit dans le cadre d’une activité commerciale, à titre onéreux ou gratuit (art. 3). Un logiciel sur mesure fourni à un seul client n’est pas exclu pour cette seule raison : le considérant 64 admet même, pour un produit sur mesure destiné à un utilisateur professionnel particulier, des écarts convenus par contrat. Un service fourni à distance relève en principe d’autres textes (considérant 12). Le cas de KerMaint et de KerResa demande donc l’avis d’un juriste ; les principes du règlement sont déjà ceux de ce chapitre.

6. Sécuriser la chaîne de développement

Une application n’est pas seulement le code écrit par l’équipe : elle assemble des composants venus d’ailleurs, passe par un dépôt, un pipeline, des environnements de recette et de production. Chaque maillon peut introduire une faille. B3-07 a présenté l’attaque par la chaîne d’approvisionnement ; cette partie montre comment le pôle développement protège sa propre chaîne.

ALes maillons de la chaîne

La chaîne de développement de KerMaint
Poste du développeur crochet pre-commit Merge request revue par un autre développeur Pipeline GitLab tests, dépendances, détection de secrets Branche main protégée (pas de push direct) push Recette KV-RECETTE données fictives Production KV-KERMAINT livraison signée après recette Gestionnaire de secrets un secret différent par environnement Dépôt de composants versions figées dans composer.lock versions contrôlées par le pipeline chaque maillon de la chaîne peut introduire une faille : chacun a son contrôle
Le code part du poste du développeur (crochet de contrôle), passe par une merge request revue par un autre développeur, puis par le pipeline de contrôles, avant d'arriver sur la branche principale protégée. La livraison signée est installée en recette, avec des données fictives, puis en production. Les secrets viennent du gestionnaire de secrets ; les composants, de versions figées et contrôlées.

Chaque maillon a son risque : poste compromis, secret versionné, bibliothèque vulnérable ou piégée, code fusionné sans relecture, archive remplacée, recette nourrie de données réelles. L’ANSSI (« Les essentiels — DevSecOps », v1.0, février 2024) recommande notamment un gestionnaire de secrets par environnement et aucun secret en dur dans le code, les dépôts ou les journaux, des dépendances réduites, évaluées et corrigées avant déploiement, l’authentification multifacteur sur les dépôts, des environnements séparés et des livraisons signées.

BGérer les dépendances

KerMaint utilise des bibliothèques PHP installées par le gestionnaire de dépendances Composer. Deux fichiers comptent :

  • composer.json déclare les bibliothèques voulues et les versions acceptables (contraintes, par exemple « 6.4 ou plus, mais pas 7 ») ;
  • composer.lock enregistre les versions exactes installées. Il est versionné dans le dépôt : chaque environnement installe exactement les mêmes versions, celles qui ont été testées.
Définition

Nomenclature logicielle (SBOM)

La nomenclature logicielle (software bill of materials, SBOM) est l’inventaire de tous les composants d’une application, avec leur version, leur origine et leur licence, y compris les dépendances des dépendances. C’est la condition de la veille : on ne peut pas savoir qu’une faille nous concerne si l’on ignore qu’on utilise le composant.

La commande composer audit (Composer 2.8.12 du laboratoire) compare les versions aux avis de sécurité publiés (--locked : d’après composer.lock ; --no-dev : sans les outils de développement) et renvoie le code 1 en cas de problème, ce qui permet de bloquer un pipeline.

Le pôle développement complète ce contrôle par sa politique de délais : une fois un avis publié, le composant doit être mis à jour en 7 jours si la faille est critique, 30 jours si elle est élevée, 90 jours si elle est moyenne et 180 jours si elle est faible. Pour suivre aussi les avis de sa veille (bulletins des éditeurs, avis du CERT-FR, B3SISR-03), Sarah a écrit un court programme PHP qui lit composer.lock, compare chaque version installée à la version corrigée de chaque avis (fonction version_compare, qui sait que 6.4.10 est postérieure à 6.4.3, ce qu’une comparaison de textes ne garantit pas), calcule l’âge de l’avis et le compare au délai de la politique, puis renvoie le code 1 s’il reste un composant à corriger.

Résultat sur la branche du module le 20/10/2026 (LAB-UBU01 ; les noms de composants et les numéros d’avis sont ceux de l’inventaire et de la veille internes de Vellacor) :

AVIS-2026-0117  exemple/rapport-pdf    6.4.1   À METTRE À JOUR en 6.4.3 (élevée, avis de 15 j, délai 30 j : reste 15 j)
AVIS-2026-0098  exemple/planificateur  2.3.2   corrigé (>= 2.3.2)
AVIS-2026-0121  exemple/journal-psr    3.0.2   À METTRE À JOUR en 3.0.4 (critique, avis de 4 j, délai 7 j : reste 3 j)
code retour : 1

La bibliothèque de journalisation passe en priorité (3 jours restants) ; la bibliothèque d’export PDF, utilisée par un écran réservé aux responsables, sera mise à jour avec la livraison mensuelle, dans son délai (B3-07).

Le programme ne voit que les avis publiés, pas les composants plus maintenus : le framework de KerMaint, Symfony 7.3, ne reçoit plus aucun correctif depuis janvier 2026, d’où la migration vers Symfony 7.4, version à support long (SLAM-07). L’inventaire note donc aussi la date de fin de maintenance de chaque composant.

Méthode

Choisir et suivre un composant

  1. Avant d’ajouter un composant : en a-t-on vraiment besoin ? Est-il maintenu (dernières versions, réactivité aux failles) ? Sa licence est-elle autorisée (CEJMA-02) ? Vient-il du dépôt officiel ?
  2. Figer la version dans composer.lock et le versionner.
  3. Inscrire le composant dans l’inventaire (SBOM) avec sa raison d’être.
  4. Contrôler les avis à chaque merge request et chaque nuit (composer audit, veille).
  5. Mettre à jour dans les délais de la politique, après tests en recette.
  6. Retirer les composants devenus inutiles ou abandonnés.

CUtiliser la gestion de version en sécurité

L’outil de gestion de version (Git, avec la forge GitLab chez Vellacor) est un outil de sécurité s’il est bien réglé.

La branche principale est protégée. Dans GitLab, une branche protégée n’accepte pas d’envoi direct (push) : le code n’y arrive que par une merge request (demande de fusion), fusionnée par une personne habilitée. La branche par défaut est protégée automatiquement ; Vellacor a retiré à tous le droit d’y pousser directement.

Les secrets n’entrent pas dans le dépôt. Le fichier .gitignore liste ce qui ne doit jamais être versionné (fichiers .env, configuration locale). Mais .gitignore se contourne d’une simple option : Sarah a ajouté un crochet (hook) pre-commit, un script que Git exécute avant chaque commit sur le poste du développeur.

#!/bin/sh
# .git/hooks/pre-commit : refuse un commit qui ajoute un secret probable
motifs='(mot_de_passe|password|secret|api_key|token)[^=:]{0,20}[=:>]+ *["'"'"'][^"'"'"']{8,}["'"'"']|-----BEGIN [A-Z ]*PRIVATE KEY-----'
if git diff --cached -U0 --diff-filter=AM | grep '^+' | grep -v '^+++' | grep -Eiq "$motifs"; then
    echo "Commit refusé : secret probable dans les lignes ajoutées."
    echo "Range-le dans le gestionnaire de secrets et lis-le par une variable d'environnement."
    exit 1
fi
for f in $(git diff --cached --name-only --diff-filter=AM); do
    case "$f" in
        *.env|*.pem|*.key|config.local.php)
            echo "Commit refusé : le fichier $f ne doit jamais être versionné."
            exit 1 ;;
    esac
done
exit 0

Le motif cherche, dans les lignes ajoutées, un nom évocateur (mot_de_passe, token…) suivi d’une valeur d’au moins 8 caractères entre guillemets, ou un en-tête de clé privée. Essai dans un dépôt de test (LAB-UBU01, Git 2.43, 20/10/2026 ; sortie abrégée aux lignes utiles) :

== commit 1 (secret lu dans l'environnement)
accepté
== commit 2 (mot de passe écrit dans le code)
Commit refusé : secret probable dans les lignes ajoutées.
Range-le dans le gestionnaire de secrets et lis-le par une variable d'environnement.
== git check-ignore -v .env
.gitignore:1:.env   .env
== commit 3 (.env forcé)
Commit refusé : le fichier .env ne doit jamais être versionné.

Le crochet est local et peut être oublié : le contrôle est refait côté serveur, dans le pipeline, par le modèle GitLab de détection de secrets (Jobs/Secret-Detection.gitlab-ci.yml).

Piège

« J’ai supprimé le mot de passe dans le commit suivant. » Le secret reste dans l’historique : n’importe qui ayant une copie du dépôt le retrouve avec git log. Un secret qui a été versionné est un secret divulgué : on le change d’abord (rotation), on vérifie ensuite qu’il n’a pas été utilisé, et seulement après on nettoie l’historique si c’est utile. L’exercice 9 le montre.

DLa revue de code

La revue de code consiste à faire relire chaque modification par un autre développeur avant sa fusion. C’est l’application au développement de la séparation des tâches (B3-05) : celui qui écrit ne valide pas seul.

Dans l’édition gratuite de GitLab utilisée par Vellacor (B1-10), une approbation peut être donnée, mais elle n’est pas bloquante : la règle « une approbation d’un autre développeur avant fusion » est donc une règle d’équipe, contrôlée par Anaïs Lecoq, seule habilitée à fusionner sur la branche principale avec Romain Daguet.

La liste de contrôle de revue du pôle développement (extrait)
Point à vérifier Question
Droits Chaque action modifiant des données appelle-t-elle le contrôle des droits côté serveur ?
Entrées Toute donnée reçue passe-t-elle par la couche de validation ? Les champs non prévus sont-ils refusés ?
Base et affichage Requêtes préparées partout ? Toute donnée affichée protégée (htmlspecialchars) ?
Erreurs Aucun message technique n’est-il renvoyé à l’utilisateur ?
Secrets Aucun secret, aucune adresse de production n’est-il écrit dans le code ?
Journaux Les événements de sécurité sont-ils tracés, sans donnée sensible ?
Dépendances Un composant ajouté est-il justifié, autorisé, inscrit à l’inventaire ?
Tests Les scénarios négatifs du récit sont-ils couverts par des tests ?

ESéparer les environnements

Développement, recette et production sont des environnements séparés : machines différentes, secrets différents, données différentes. KerMaint est développé sur les postes Linux du pôle, recetté sur KV-RECETTE avec une base anonymisée, exploité sur KV-KERMAINT (B1-11). Les techniques d’isolation, la configuration de production et les tests de sécurité avant mise en production sont traités en B3SLAM-04.

7. Vérifier la conformité à un référentiel

Un référentiel de sécurité applicative fournit des exigences déjà rédigées, reconnues, et une base commune pour discuter avec un client ou un auditeur. Le référentiel demande de savoir mettre en œuvre une application conforme et de le vérifier. Deux références de l’OWASP dominent : le Top 10, pour connaître les risques, et l’ASVS, pour vérifier.

AL’OWASP

L’OWASP (Open Worldwide Application Security Project) est une fondation à but non lucratif qui publie librement des documents, des outils et des référentiels sur la sécurité des applications. Ses deux productions les plus utilisées sont présentées ici.

BLe Top 10 de l’OWASP

Le Top 10 classe les dix catégories de risques les plus importantes pour les applications web. L’édition en vigueur au 20/10/2026 est le Top 10:2025 (site top10.owasp.org, consulté le 20/10/2026).

L’OWASP Top 10:2025 et les chapitres qui le traitent
Code Catégorie (traduction) Où dans le bloc 3 SLAM
A01:2025 Contrôle d’accès défaillant conception : refus par défaut (ici) ; code : B3SLAM-02, B3SLAM-03
A02:2025 Mauvaise configuration de sécurité secrets, débogage, fonctions superflues (ici) ; B3SLAM-04
A03:2025 Défaillances de la chaîne d’approvisionnement logicielle dépendances, dépôt, pipeline (ici)
A04:2025 Défaillances cryptographiques B3-06, B3SLAM-03
A05:2025 Injection validation (ici) ; requêtes préparées et encodage : B1-08, B3SLAM-02
A06:2025 Conception non sûre exigences, modélisation des menaces, principes (ici)
A07:2025 Défaillances de l’authentification B3SLAM-03
A08:2025 Défaillances d’intégrité des logiciels ou des données livraisons signées (B3-06), chaîne (ici)
A09:2025 Défaillances de la journalisation et des alertes journal sans fuite (ici) ; analyse : B3SLAM-04
A10:2025 Mauvaise gestion des conditions exceptionnelles gestion des erreurs, échec sûr (ici)

A06 recommande la modélisation des menaces, des exigences de sécurité dans les récits et des tests de cas d’abus ; A10, nouvelle en 2025, regroupe les erreurs mal gérées, les messages trop bavards et les contrôles qui « échouent ouverts ».

Piège

Le Top 10 est un document de sensibilisation, pas une norme de vérification : une application peut n’avoir « aucun des 10 risques » et rester fragile. Pour vérifier une application point par point, on utilise l’ASVS.

CL’ASVS de l’OWASP

L’ASVS (Application Security Verification Standard) est une liste d’exigences de sécurité vérifiables pour les applications web et les API. La version stable au 20/10/2026 est la 5.0.0, publiée en mai 2025 : 345 exigences réparties en 17 chapitres (validation et logique métier, authentification, sessions, autorisation, cryptographie, configuration, protection des données, codage sûr et architecture, journalisation et gestion des erreurs, etc.).

Chaque exigence porte un niveau :

Les trois niveaux de l’ASVS 5.0.0
Niveau Rôle Exigences du niveau Exigences à satisfaire en tout
L1 le minimum, point de départ de toute application 70 (20,3 %) 70
L2 le niveau que la plupart des applications devraient atteindre 183 (53,0 %) 253 (73,3 %)
L3 les applications les plus sensibles 92 (26,7 %) 345 (100 %)

L’ASVS ne dit pas quel niveau viser : l’organisation le choisit d’après ses risques et la sensibilité de l’application. La charte de développement du pôle de Vellacor fixe : L1 pour toute application, L2 pour toute application exposée sur Internet ou traitant des données de clients (KerResa, « Kervanet & Moi »). KerMaint, interne, vise L1, complété d’exigences L2 choisies d’après la modélisation des menaces.

Une exigence se cite avec la version : v5.0.0-2.2.1 désigne l’exigence 1 de la section 2 (validation des entrées) du chapitre 2 ; la version évite les confusions d’une édition à l’autre.

Les exigences de l’ASVS 5.0.0 qui recouvrent les exigences du module (extrait)
Exigence du module Exigence ASVS Niveau Ce qu’elle demande (résumé)
EXS-01 v5.0.0-8.2.1 et 8.3.1 L1 accès aux fonctions réservé aux permissions explicites ; règles d’autorisation appliquées par le serveur
EXS-02 v5.0.0-2.2.1 et 2.2.2 L1 validation positive (liste blanche, structure attendue) faite côté serveur
EXS-02 v5.0.0-15.3.3 L2 protection contre l’affectation de masse (champs autorisés par action)
EXS-03 v5.0.0-16.2.1 et 16.2.5 L2 chaque entrée de journal dit quand, où, qui, quoi ; pas de donnée sensible interdite
EXS-04 v5.0.0-16.5.1 et 16.5.3 L2 message générique en cas d’erreur ; échec sûr, sans traitement poursuivi malgré l’erreur
EXS-05 v5.0.0-13.3.1 L2 secrets gérés par une solution dédiée (coffre de secrets)
EXS-05 v5.0.0-13.4.1 L1 aucun dossier de gestion de version (.git) accessible en production
EXS-06 v5.0.0-15.1.1 et 15.2.1 L1 délais de mise à jour des composants vulnérables documentés et respectés

DLes guides français

En France, l’ANSSI (« Les essentiels — DevSecOps », 2024) et la CNIL (guide RGPD de l’équipe de développement, B3-02) complètent l’OWASP. Cite toujours le titre, la version et la date du document utilisé.

EVérifier la conformité

Vérifier la conformité, c’est confronter l’application, exigence par exigence, au référentiel retenu, et conserver la preuve de chaque réponse.

Méthode

Vérifier la conformité d'une application à l'ASVS

  1. Fixer le périmètre (application, version, environnement) et le niveau visé, avec sa justification.
  2. Extraire les exigences du niveau ; marquer « non applicable », avec la raison, celles qui ne concernent pas l’application (une application sans téléversement de fichiers n’a pas à respecter le chapitre sur les fichiers).
  3. Pour chaque exigence, vérifier par le moyen adapté : lecture de la documentation, revue du code, test (positif et négatif), lecture de la configuration.
  4. Noter le statut (conforme, non conforme, partiellement conforme, non applicable) et la preuve (extrait de code, sortie de test, capture, date).
  5. Traiter les écarts : correction avec un responsable et une échéance, ou acceptation écrite du risque par le responsable.
  6. Restituer une synthèse (taux de conformité par chapitre, écarts prioritaires) et recommencer à chaque version majeure.
Exemple chiffré

La grille du module préventif avant le premier sprint

Sarah applique la grille aux 8 exigences de sécurité du module (EXS-01 à EXS-08), sur la conception validée et les modules communs déjà écrits : 5 sont conformes (EXS-01, 02, 04, 05 et 07 : code des modules communs testé, maquettes vérifiées), 2 sont partiellement conformes (EXS-03 : format du journal défini mais protection du journal à préparer ; EXS-06 : deux composants à mettre à jour), 1 est à faire (EXS-08 : purge à coder).

Taux de conformité = 5 ÷ 8 = 62,5 %. Interprétation : ce n’est pas un échec, c’est le point de départ ; les trois écarts deviennent des tâches du sprint, avec la recette comme date de vérification.

8. Préparer l’épreuve E7

L’E7 est une étude de cas écrite de 4 heures, avec un dossier documentaire et plusieurs missions. Pour l’option SLAM, ce chapitre y revient souvent sous forme d’exigences à rédiger, de menaces à identifier sur un schéma, d’un extrait de code à critiquer ou d’une chaîne de développement à sécuriser.

Méthode

Répondre à une question de sécurité de conception en E7

  1. Repère dans le dossier les données traitées, les acteurs et les frontières : c’est le socle de toute réponse.
  2. Nomme précisément (famille STRIDE, principe de conception, catégorie de l’OWASP) et justifie par un élément du dossier.
  3. Transforme chaque menace en exigence testable : identifiant, formulation, vérification.
  4. Pour un extrait de code, cite la ligne, explique le défaut, donne la correction et le principe qu’elle applique.
  5. Calcule (criticité, délais, taux) en posant les données et la formule, puis interprète.
  6. Conclus par une recommandation adaptée au destinataire.

Erreurs fréquentes et points de vigilance

Erreur Ce qu’il faut faire
Écrire « l’application doit être sécurisée » une exigence identifiée, testable, justifiée, avec son moyen de vérification
Ne prévoir que des scénarios qui réussissent au moins un critère d’acceptation négatif par récit ; des cas d’abus
Contrôler les droits par une liste noire (« tous sauf… ») liste blanche, refus par défaut, échec sûr
Valider sans normaliser, ou seulement dans le navigateur normaliser puis valider par liste blanche, côté serveur, à la frontière
Afficher $e->getMessage() à l’utilisateur message générique et référence ; détail au journal
Supprimer un secret versionné « dans le commit suivant » rotation immédiate du secret ; il reste dans l’historique
Considérer le Top 10 comme une norme de conformité Top 10 pour sensibiliser ; ASVS, au niveau choisi, pour vérifier
Citer « l’OWASP » sans édition ni version Top 10:2025, ASVS v5.0.0 et identifiant de l’exigence

L’essentiel du chapitre

À retenir

À retenir

  • Sécurité dès la conception : la sécurité est une exigence du projet, à chaque étape (besoin, conception, développement, tests, déploiement, exploitation). Un défaut de conception ne se corrige pas par un code parfait.
  • Exigences de sécurité : identifiant, formulation testable, justification, vérification ; sources : risques, règles de gestion, réglementation, contrat, référentiels, menaces. Dans les récits : critères d’acceptation négatifs et cas d’abus.
  • Modélisation des menaces : diagramme de flux de données (entités, traitements, stockages, flux), frontières de confiance, STRIDE (usurpation, falsification, répudiation, divulgation, déni de service, élévation de privilèges), évaluation G × V (échelles de B3-01), une exigence par menace. Lien avec EBIOS RM (scénarios opérationnels).
  • Principes : moindre privilège (comptes de l’application compris), défense en profondeur, sécurité par défaut et échec sûr (liste blanche), normaliser puis valider à la frontière (champs non prévus refusés), erreurs génériques avec référence, secrets hors du code (gestionnaire, un secret par environnement, rotation), code modulaire, normes de codage, données normalisées.
  • Protection des données dès la conception et par défaut (art. 25 RGPD) : quantité, étendue, durée, accessibilité ; purge livrée avec le produit ; données de test fictives ; droits des personnes conçus comme des fonctions (export, rectification, effacement, limitation, opposition). Règlement sur la cyberrésilience : configuration sécurisée par défaut, application le 11/12/2027.
  • Chaîne de développement : inventaire (SBOM), composer.lock, composer audit, politique de délais ; branche protégée, merge request, revue de code ; crochet pre-commit et détection de secrets ; un secret versionné est divulgué ; environnements séparés.
  • Référentiels : OWASP Top 10:2025 (sensibilisation ; A06 conception non sûre, A10 conditions exceptionnelles) ; OWASP ASVS 5.0.0 (345 exigences, 17 chapitres, niveaux L1, L2, L3, identifiants du type v5.0.0-2.2.1) ; ANSSI « Les essentiels — DevSecOps ». Vérifier la conformité : périmètre, niveau, statut et preuve par exigence, traitement des écarts.

Sources et références

  • Arrêté du 29 avril 2019 portant définition et fixant les conditions de délivrance du BTS « Services informatiques aux organisations », modifié par les arrêtés du 8 juillet 2024 et du 22 novembre 2024 ; référentiel de la fiche RNCP40792 (annexe I.B, bloc 3, partie SLAM, activité B3.5), lu le 20/10/2026.
  • OWASP Top 10:2025, site top10.owasp.org (liste des dix catégories, pages A06:2025 « Insecure Design » et A10:2025 « Mishandling of Exceptional Conditions »), consulté le 20/10/2026.
  • OWASP, Application Security Verification Standard 5.0.0 (mai 2025), dépôt officiel github.com/OWASP/ASVS (étiquette v5.0.0_release) : chapitre « What is the ASVS » (niveaux) et chapitres V2, V8, V13, V15, V16 lus le 20/10/2026 ; décompte des exigences par niveau fait sur les fichiers de la version 5.0.0.
  • Microsoft Learn, « Threat Modeling Tool threats » (STRIDE), consulté le 20/10/2026.
  • ANSSI, « Les essentiels — DevSecOps », version 1.0 (février 2024 ; page de messervices.cyber.gouv.fr publiée le 13/03/2024), consulté le 20/10/2026 ; ANSSI, « Recommandations pour la mise en œuvre d’un site web : maîtriser les standards de sécurité côté navigateur », v2.0, page publiée le 28/04/2021, consultée le 20/10/2026.
  • Règlement (UE) 2024/2847 du 23 octobre 2024 (cyberrésilience), art. 2, art. 3 (définitions 13 et 22), art. 71, considérants 12, 15, 16 et 64, annexe I, partie I, lus sur EUR-Lex le 20/10/2026 et le 21/10/2026 ; page « Cyber Resilience Act » de la Commission européenne (mise à jour le 07/09/2026), consultée le 20/10/2026. Règlement (UE) 2016/679 (RGPD), art. 25 : voir CEJMA-08 (lu sur EUR-Lex le 20/10/2026).
  • Documentations consultées le 20/10/2026 : GitLab Docs (« Merge request approvals », « Protected branches », « Pipeline secret detection ») ; Composer (ligne de commande, audit, rôle de composer.lock ; aide de Composer 2.8.12) ; PHP-FIG, « PER Coding Style 3.1 ».
  • symfony.com, page « Symfony 7.3 » (sortie en mai 2025, fin de maintenance en janvier 2026, statut « non maintenue »), consultée le 21/10/2026.
  • Versions des outils de la machine de laboratoire LAB-UBU01 (Ubuntu 24.04.5 LTS) : PHP 8.3.6, Git 2.43.0.
  • FuturBTS : B1-06, B1-08, B1-10, B1-11, B3-01 à B3-07, SLAM-01, SLAM-10, B3SLAM-02 à B3SLAM-04, B3SISR-03, CEJM-14, CEJMA-02, CEJMA-03, CEJMA-08.

Contenu original FuturBTS. Vellacor Services Numériques, Kervanet Hôtels & Résidences et les personnes citées sont fictifs ; les noms de composants (exemple/…), les numéros d’avis et les mots de passe montrés sont des valeurs d’exemple sans usage réel. Les produits nommés (PHP, Composer, Git, GitLab) le sont à titre d’exemple. Aucun passage, exemple ou exercice n’est repris d’un manuel existant.

Garde la trace de ce que tu as lu

Avec un compte, ta progression, tes quiz et ton planning sont enregistrés.

Créer mon compte
Signaler une erreur dans ce chapitre