L'état d'esprit
La sécurité n'est pas une fonctionnalité qu'on ajoute à la fin : c'est une propriété du système, qui se gagne (ou se perd) à chaque ligne. Le premier réflexe à acquérir : penser comme celui qui voudra vous attaquer.
Un développeur écrit le chemin « normal ». Un attaquant, lui, explore tous les autres : l'entrée qu'on n'a pas validée, l'étape qu'on a supposée impossible, l'erreur qui révèle un secret. Le code sécurisé n'est pas du code qui marche — c'est du code qui résiste à un usage hostile.
Trois idées guident toute la formation : décaler la sécurité vers la gauche (« shift left » : penser aux risques dès la conception, pas en audit final), supposer la compromission (« assume breach » : que se passe-t-il quand une couche tombe ?), et ne jamais faire confiance à une entrée, d'où qu'elle vienne.
« Je ne vais pas suivre votre formulaire. Je vais envoyer un champ que vous n'attendez pas, un identifiant qui n'est pas le mien, une valeur cent fois trop grande, ou rejouer votre requête. Je cherche l'hypothèse que vous avez oublié de vérifier. » — Ce point de vue, c'est le fil rouge de l'OWASP Top 10.
Ce parcours suit deux référentiels complémentaires : l'OWASP Top 10:2025, qui classe les dix risques applicatifs les plus critiques, et les principes de l'ANSSI (défense en profondeur, moindre privilège, hygiène), qui structurent une posture durable. On les traduit en code concret — en TypeScript ou en Python.
Les grands principes
Avant les failles, les fondations. Ces principes — au cœur des recommandations de l'ANSSI et du « secure by design » — vous évitent des familles entières de vulnérabilités.
Le socle à mémoriser
- Défense en profondeur — empilez les protections ; aucune n'est censée être la dernière.
- Moindre privilège — chaque composant, compte ou jeton n'a que les droits strictement nécessaires, pas un de plus.
- Réduire la surface d'attaque — moins de code, d'endpoints, de dépendances et d'options exposés = moins à défendre.
- Sécurisé par défaut — l'état initial est le plus fermé ; on ouvre explicitement, jamais l'inverse.
- Ne jamais faire confiance aux entrées — tout ce qui vient de l'extérieur est suspect jusqu'à validation.
- Échouer en sécurité — en cas d'erreur, on refuse l'accès (fail-closed), on ne l'accorde pas.
- Simplicité — un design simple se vérifie ; la complexité cache les failles.
- Tracer — ce qu'on ne journalise pas, on ne le verra jamais venir.
Ces principes irriguent le Guide d'hygiène informatique de l'ANSSI et ses recommandations de développement. L'idée directrice : la sécurité se construit par accumulation de bonnes pratiques simples et constantes, pas par une mesure miracle.
Contrôle d'accès défaillant
Le risque — Un utilisateur accède à des données ou des actions qui ne devraient pas lui être permises. N°1 du classement, et désormais la SSRF y est rattachée.
La faute la plus courante : vérifier l'authentification (« qui es-tu ? ») mais oublier l'autorisation (« as-tu le droit pour CETTE ressource ? »). Un identifiant dans l'URL qu'on incrémente, et l'on lit la facture du voisin — c'est l'IDOR.
« /factures/1041 me renvoie ma facture. Et /factures/1042 ? … Tiens, c'est celle de quelqu'un d'autre. Je boucle de 1 à 99999. »
Défenses clés
- Autorisation côté serveur sur chaque requête, par déni par défaut (deny-by-default).
- Ne jamais se fier à un rôle, un prix ou un identifiant venant du client.
- SSRF : valider et restreindre toute URL fournie par l'utilisateur (liste blanche de domaines, pas d'accès aux IP internes).
Mauvaise configuration
Le risque — Le code est correct, mais la configuration est ouverte : mode debug en prod, identifiants par défaut, services inutiles, en-têtes manquants. En forte hausse (de la 5ᵉ à la 2ᵉ place).
À mesure que les applications dépendent de configuration (variables, conteneurs, cloud), la surface d'erreur explose. Les classiques : une console d'admin laissée ouverte, des messages d'erreur verbeux qui exposent la stack, un bucket de stockage « public », un compte admin/admin jamais changé.
« Je teste les chemins classiques : /.env, /admin, la page d'erreur détaillée, les identifiants par défaut de l'outil que vous utilisez. Souvent, l'un d'eux répond. »
Défenses clés
- Durcir par défaut : debug désactivé en prod, fonctionnalités et comptes inutiles supprimés, secrets par défaut changés.
- Erreurs génériques côté client ; les détails restent dans les logs serveur (voir A10).
- En-têtes de sécurité HTTP :
Content-Security-Policy,Strict-Transport-Security,X-Content-Type-Options, cookiesSecure; HttpOnly; SameSite. - Configuration identique et reproductible entre environnements (infra-as-code), revue comme du code.
Chaîne d'approvisionnementNouveau
Le risque — La menace ne vient pas de votre code, mais de ce dont il dépend : dépendances, systèmes de build, distribution. Cette catégorie étend l'ancienne « Composants vulnérables et obsolètes » de 2021 à tout l'écosystème logiciel.
Un seul paquet compromis — maintainer piraté, dépendance malveillante, build trafiqué — et le code hostile s'exécute avec votre confiance, souvent dès le poste du développeur, puis traverse CI, conteneurs et prod. Une dépendance malveillante peut se propager à travers les systèmes CI, les conteneurs et les environnements cloud en quelques heures, souvent sans déclencher les scanners traditionnels.
Défenses clés
- Verrouiller les versions (lockfile) et installer à l'identique (
npm ci, hashes pip). - Scanner en continu (SCA) et tenir les dépendances à jour ; supprimer celles qu'on n'utilise pas.
- Vérifier la provenance (intégrité, signatures, registres de confiance) et figer l'intégrité du build (CI/CD).
- Se méfier des installations de scripts non vérifiés et des dépendances « fantômes ».
Défaillances cryptographiques
Le risque — Données sensibles mal (ou pas) protégées : transport en clair, mauvais algorithme, mots de passe stockés naïvement, clés en dur.
L'erreur emblématique : « hacher » les mots de passe avec un SHA rapide. Un hash rapide est exactement ce que veut l'attaquant pour les casser en masse. Il faut une fonction lente et salée dédiée aux mots de passe : Argon2id (ou bcrypt/scrypt).
À faire — TLS partout ; algorithmes éprouvés et à jour ; clés gérées hors du code ; chiffrer les données sensibles au repos.
À éviter — inventer sa crypto ; MD5/SHA1 ; ECB ; secrets dans le dépôt ; aléa non cryptographique pour des jetons.
Le RGS (Référentiel Général de Sécurité) et les guides cryptographiques de l'ANSSI fixent les algorithmes et tailles de clés recommandés. La règle d'or reste : n'implémentez jamais votre propre cryptographie, utilisez des bibliothèques éprouvées.
Injection
Le risque — Une entrée non fiable est interprétée comme du code ou une commande : SQL, NoSQL, OS, LDAP… et le XSS (injection dans le navigateur). La cause unique : mélanger données et instructions.
« Dans le champ email, j'écris x' OR '1'='1. Si votre requête est construite par concaténation, je viens de transformer votre WHERE en « toujours vrai ». »
Défenses clés
- Toujours des requêtes paramétrées / ORM ; jamais de concaténation d'entrées dans une requête ou une commande.
- XSS : encoder les sorties selon le contexte (le framework le fait — évitez
dangerouslySetInnerHTML,|safe,eval) et posez uneContent-Security-Policy. - Valider les entrées en complément (voir « Entrées & sorties »), jamais comme unique défense.
Conception non sécurisée
Le risque — La faille n'est pas un bug d'implémentation, mais un défaut de conception : on a oublié un cas d'abus, une limite, un contrôle métier. Aucune ligne de code « propre » ne rattrape un design qui n'a pas pensé l'attaque.
Exemple : un tunnel de réinitialisation de mot de passe qui envoie un code à 4 chiffres sans limite d'essais — le code est correct, le design est cassé. La parade se joue en amont : modélisation des menaces (« qu'est-ce qui peut mal tourner ? ») et cas d'abus à côté des cas d'usage.
Défenses clés
- Threat modeling dès la conception (STRIDE, arbres d'attaque) sur les flux sensibles.
- Écrire les cas d'abus en regard des user stories ; définir les limites (débit, quotas, montants).
- Réutiliser des patterns sûrs et des bibliothèques éprouvées plutôt que réinventer.
- Revue de sécurité de la conception avant de coder les fonctionnalités à risque.
« Shift left » prend ici tout son sens : une faille de conception détectée sur un tableau blanc coûte mille fois moins cher qu'en production. La sécurité commence avant le premier commit.
Défaillances d'authentification
Le risque — Prouver l'identité est mal fait : mots de passe faibles tolérés, pas de limite d'essais, sessions mal gérées, énumération de comptes. Renommée en 2025 (auparavant « Identification and Authentication Failures »).
Quelques détails font toute la différence : limiter le débit sur /login, comparer les jetons en temps constant (sinon une attaque temporelle les devine), et renvoyer le même message pour « email inconnu » et « mauvais mot de passe » (sinon on énumère vos comptes).
Défenses clés
- Déléguer à des frameworks d'authentification éprouvés ; activer le MFA.
- Politiques de mots de passe modernes (longueur > complexité), blocage des mots de passe compromis connus.
- Sessions : jetons aléatoires forts, expiration, invalidation à la déconnexion, cookies
Secure; HttpOnly; SameSite. - Limitation du débit et temporisation progressive contre le bourrage d'identifiants.
Défauts d'intégrité
Le risque — Du code ou des données sont acceptés sans vérifier leur intégrité : désérialisation dangereuse, mise à jour non signée, artefact de build trafiqué, pipeline CI/CD non protégé.
Là où A03 regarde tout l'écosystème, A08 se concentre sur les frontières de confiance internes : croit-on aveuglément un objet sérialisé reçu, un plugin chargé dynamiquement, un artefact poussé par la CI ? Désérialiser des données non fiables est un grand classique d'exécution de code à distance.
Défenses clés
- Ne jamais désérialiser de données non fiables ; préférer des formats de données « sans code » (JSON validé) aux formats qui instancient des objets.
- Signer et vérifier les mises à jour, artefacts et configurations critiques.
- Protéger le pipeline CI/CD : accès restreint, étapes vérifiées, dépendances de build figées.
Journalisation & alerte
Le risque — Sans journaux ni alertes, une attaque passe inaperçue pendant des mois. Renommée en 2025 pour souligner l'importance de l'alerte, et plus seulement de la surveillance.
Le but n'est pas de tout logger, mais de logger ce qui permet de détecter et investiguer : connexions (réussies et échouées), changements de droits, accès sensibles, erreurs de sécurité. Et surtout, de déclencher une alerte sur les signaux qui comptent.
Ne journalisez jamais de mots de passe, jetons, numéros de carte ou données personnelles en clair. Un log trop bavard devient lui-même une fuite de données — et une cible.
Défenses clés
- Journaliser les événements de sécurité avec contexte (qui, quoi, quand, d'où) — sans secrets ni PII.
- Centraliser, horodater, protéger les logs en intégrité (un attaquant cherche à les effacer).
- Définir des alertes et un plan de réponse : un log que personne ne regarde ne sert à rien.
Conditions exceptionnellesNouveau
Le risque — La façon dont le système réagit à l'anormal : erreurs mal gérées, logique qui « échoue ouvert » (fail-open), exceptions qui fuient des détails. Catégorie entièrement nouvelle en 2025, centrée sur la gestion sécurisée des erreurs et la résilience.
Le pire scénario : un contrôle de sécurité qui, en cas d'exception, laisse passer. Et son cousin : la page d'erreur qui affiche la stack trace, le chemin du serveur, voire une requête SQL. La règle : échouer fermé, et ne révéler aucun détail à l'extérieur.
Défenses clés
- Concevoir les contrôles pour échouer fermé (deny par défaut sur exception).
- Messages d'erreur génériques à l'extérieur ; pile et contexte uniquement dans les logs serveur.
- Gérer explicitement les cas limites (timeouts, valeurs nulles, dépassements) plutôt que de les laisser remonter.
Entrées & sorties
La règle — Valider en entrée, encoder en sortie. Deux gestes qui, à eux seuls, désamorcent une grande part de l'OWASP Top 10.
Valider par liste blanche (ce qui est autorisé), pas par liste noire (ce qu'on interdit) : on décrit la forme attendue — type, format, bornes, valeurs permises — et on rejette tout le reste. Une bibliothèque de schémas le rend déclaratif :
Validation = filtrer ce qui entre (côté serveur, toujours). Encodage de sortie = neutraliser ce qui sort, selon le contexte de destination (HTML, SQL, shell, URL). L'un protège l'intérieur, l'autre empêche vos données de devenir du code ailleurs.
Secrets & configuration
La règle — Aucun secret dans le code. Jamais. Un secret committé est un secret compromis — il reste dans l'historique git même après suppression.
Défenses clés
- Secrets via environnement ou coffre-fort ;
.envdans le.gitignore, jamais committé. - Scanner les secrets en CI et au commit (détection de clés) ; révoquer immédiatement tout secret exposé.
- Rotation régulière et droits minimaux par clé (une clé = un usage).
Le cycle de dev sécurisé
La sécurité n'est pas une étape, c'est un fil tendu sur tout le cycle de vie. Voici où elle s'accroche.
Concevoir — modéliser les menaces
Cartographier les flux sensibles, lister cas d'abus et limites avant d'écrire le code (A06).
Coder — règles & revues
Conventions de codage sécurisé, revue de code orientée sécurité, validation/encodage systématiques.
Outiller — SAST · SCA · secrets
Analyse statique du code, scan des dépendances (A03) et détection de secrets, intégrés en CI.
Tester — DAST & cas d'attaque
Tests dynamiques sur l'appli en marche, tests de sécurité ciblés, fuzzing des entrées.
Livrer — pipeline verrouillé
Build reproductible et signé, configuration durcie, secrets injectés, portes de sécurité bloquantes.
Exploiter — observer & réagir
Journalisation, alertes (A09), gestion des vulnérabilités et plan de réponse aux incidents.
SAST, SCA et scan de secrets en portes de CI bloquantes transforment la sécurité en garde-fou permanent plutôt qu'en revue ponctuelle. Le coût d'une faille croît de façon exponentielle à mesure qu'elle avance dans le cycle.
Le réflexe ANSSI
L'esprit — L'ANSSI (agence française de cybersécurité) ne raisonne pas « faille par faille » mais posture globale : une hygiène constante qui rend l'attaque coûteuse à chaque étape.
Au-delà des principes vus en §01, quelques repères concrets côté ANSSI : le Guide d'hygiène informatique (les mesures de base à ne jamais négliger), le RGS pour les choix cryptographiques, et des recommandations sectorielles (développement, journalisation, administration sécurisée).
Réflexes ANSSI — défense en profondeur · moindre privilège · cloisonnement · mises à jour · sauvegardes testées · cartographie du SI · journalisation centralisée.
Anti-réflexes — un seul rempart · comptes tout-puissants · systèmes non maintenus · « ça n'arrivera pas chez nous ».
OWASP vous dit quelles failles guetter dans l'application ; l'ANSSI vous dit comment tenir une organisation et un SI dans la durée. Les deux se complètent : le code sécurisé vit dans un système sécurisé.
Checklist du dev sécurisé
À passer en revue avant de livrer une fonctionnalité sensible.
Content-Security-Policy en place.Antisèche & lectures
L'OWASP Top 10:2025 en un coup d'œil, le vocabulaire, et par où continuer.
| A01 | Contrôle d'accès défaillant — autorisation manquante, IDOR ; inclut désormais la SSRF. |
| A02 | Mauvaise configuration — debug, défauts, en-têtes, services inutiles. ↑ n°2. |
| A03 | Chaîne d'approvisionnement Nouveau — dépendances, build, distribution. |
| A04 | Défaillances cryptographiques — données mal protégées, mauvais hash, clés exposées. |
| A05 | Injection — SQL/NoSQL/OS/LDAP et XSS ; données interprétées comme du code. |
| A06 | Conception non sécurisée — défaut de design, cas d'abus oubliés. |
| A07 | Défaillances d'authentification — sessions, débit, énumération, MFA. |
| A08 | Défauts d'intégrité — désérialisation, mises à jour non signées, CI/CD. |
| A09 | Journalisation & alerte — détecter, investiguer, réagir. |
| A10 | Conditions exceptionnelles Nouveau — fail-closed, erreurs sûres. |
Vocabulaire
| IDOR | Accès à un objet d'autrui via un identifiant manipulé (défaut d'autorisation). |
| SSRF | Forcer le serveur à émettre une requête vers une cible interne choisie par l'attaquant. |
| XSS | Injection de script exécuté dans le navigateur d'autres utilisateurs. |
| Fail-closed | En cas d'erreur/doute, refuser l'accès plutôt que l'accorder. |
| Liste blanche | N'autoriser que l'explicitement permis ; tout le reste est rejeté. |
| SAST / DAST / SCA | Analyse du code / de l'appli en marche / des dépendances. |
| Threat modeling | Anticiper, dès la conception, ce qui peut être attaqué et comment. |
| Défense en profondeur | Empiler les protections pour ne jamais dépendre d'une seule. |
Pour aller plus loin
- OWASP Top 10:2025 — la liste officielle, par catégorie, avec mappings CWE (owasp.org/Top10/2025).
- OWASP ASVS & Cheat Sheet Series — exigences vérifiables et fiches pratiques par sujet.
- ANSSI — Guide d'hygiène informatique, RGS, recommandations de développement (cyber.gouv.fr).
- MITRE CWE — le référentiel des types de faiblesses logicielles.
La sécurité parfaite n'existe pas — l'objectif est de rendre l'attaque plus coûteuse que ce qu'elle rapporte. Validez, autorisez, chiffrez, échouez fermé, journalisez, et tenez vos dépendances. Le reste, c'est de la constance. 🛡️