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.
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.
En Scrum, ces activités se répètent à chaque sprint (B1-10).
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.
| 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.
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.
| 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 |
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.
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).
« 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.
Rédiger les exigences de sécurité d'un projet
- Partir des données et de leurs besoins DICP (B3-01) ; repérer les données personnelles (B3-02).
- Lister les acteurs et leurs droits (matrice des droits).
- Modéliser les menaces (partie 3) et en tirer les exigences qui manquent.
- Compléter avec un référentiel (OWASP ASVS, partie 7) au niveau choisi.
- Rédiger chaque exigence : identifiant, formulation testable, justification, vérification.
- 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 :
- Que construit-on ? On représente l’application : ses utilisateurs, ses traitements, ses données, ses échanges.
- Que peut-il mal se passer ? On cherche les menaces, élément par élément.
- Que fait-on contre chaque menace ? On choisit une mesure, qui devient une exigence (partie 2).
- A-t-on bien travaillé ? On vérifie que chaque menace retenue a une mesure, un responsable et un test.
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.
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.
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é.
| 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 |
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).
| 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.
Modéliser les menaces d'une application
- Dessiner le diagramme de flux de données : entités, traitements, stockages, flux.
- Tracer les frontières de confiance et repérer les flux qui les franchissent.
- Appliquer STRIDE à chaque élément, en commençant par les flux qui franchissent une frontière.
- Décrire chaque menace retenue en une phrase (qui, comment, quel élément, quel effet).
- Évaluer gravité et vraisemblance avec les échelles de l’organisation ; classer.
- Associer à chaque menace une mesure, traduite en exigence testable, et un responsable.
- Conserver le modèle avec le projet et le mettre à jour à chaque évolution importante.
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é.
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
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 ».
É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.
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).
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.
Concevoir la gestion des erreurs
- Désactiver l’affichage des erreurs en production
(
display_errorsà 0) et tout mode de débogage ; le vérifier à chaque mise en production. - Traiter les erreurs prévisibles là où elles se produisent (saisie invalide, élément introuvable), avec un message utile mais sans détail technique.
- Prévoir un gestionnaire de dernier recours pour toutes les autres : message générique, référence, détail au journal.
- É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.
- Journaliser sans mot de passe, sans jeton, sans donnée personnelle inutile (B3-02).
- 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.
| 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.
| 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
| 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 |
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.
| 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
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
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.jsondéclare les bibliothèques voulues et les versions acceptables (contraintes, par exemple « 6.4 ou plus, mais pas 7 ») ;composer.lockenregistre 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.
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.
Choisir et suivre un composant
- 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 ?
- Figer la version dans
composer.locket le versionner. - Inscrire le composant dans l’inventaire (SBOM) avec sa raison d’être.
- Contrôler les avis à chaque merge request et chaque
nuit (
composer audit, veille). - Mettre à jour dans les délais de la politique, après tests en recette.
- 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 0Le 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).
« 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.
| 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).
| 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 ».
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 :
| 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.
| 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.
Vérifier la conformité d'une application à l'ASVS
- Fixer le périmètre (application, version, environnement) et le niveau visé, avec sa justification.
- 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).
- 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.
- Noter le statut (conforme, non conforme, partiellement conforme, non applicable) et la preuve (extrait de code, sortie de test, capture, date).
- Traiter les écarts : correction avec un responsable et une échéance, ou acceptation écrite du risque par le responsable.
- Restituer une synthèse (taux de conformité par chapitre, écarts prioritaires) et recommencer à chaque version majeure.
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.
Répondre à une question de sécurité de conception en E7
- Repère dans le dossier les données traitées, les acteurs et les frontières : c’est le socle de toute réponse.
- Nomme précisément (famille STRIDE, principe de conception, catégorie de l’OWASP) et justifie par un élément du dossier.
- Transforme chaque menace en exigence testable : identifiant, formulation, vérification.
- Pour un extrait de code, cite la ligne, explique le défaut, donne la correction et le principe qu’elle applique.
- Calcule (criticité, délais, taux) en posant les données et la formule, puis interprète.
- 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
- 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 ; crochetpre-commitet 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 decomposer.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.