Je me souviens d'un projet où, après un an, une ancienne vulnérabilité pourtant bien identifiée lors de notre atelier initial avait réapparu. Pourquoi ? Parce que notre Threat Modeling était resté une photo d'un instant, sans suivi.
C'est là que j'ai compris l'importance d'un Threat Modeling continu. Pas juste un atelier au début, mais une démarche vivante, intégrée dans le cycle de développement, qui évolue avec le projet.
Intégrer le Threat Modeling dans le quotidien
15 minutes pour sécuriser une User Story
L'intégration CI/CD est essentielle pour attraper les régressions, mais la meilleure défense reste encore d'éviter d'introduire la faille dès le départ.
Avant de commencer à coder une nouvelle fonctionnalité (par exemple, un export de données utilisateur), prenez 15 minutes avec le Product Owner et un développeur pour un "mini-TM". Pas besoin d’outil complexe ni de schéma UML : un tableau blanc ou une feuille de papier suffit.
Tracez rapidement le flux de données et posez-vous 3 questions simples, inspirées de STRIDE :
- Usurpation (Spoofing) : Qui peut lancer cet export ? Est-ce vérifié côté back ?
- Altération (Tampering) : Les paramètres de l’export peuvent-ils être manipulés via l’URL ou le corps de la requête ?
- Divulgation d'information (Information Disclosure) : Quelles données sont exportées, où partent-elles, et à qui sont-elles visibles ?
Ce rituel permet de faire émerger très tôt des exigences de sécurité concrètes, comme :
- L’ID de l’utilisateur doit provenir de son jeton de session, pas d’un paramètre client.
- L’export doit être loggué et validé côté serveur.
- Un filtrage des colonnes ou un masquage doit être mis en place si des données sensibles sont en jeu.
Cette approche évite de se reposer uniquement sur les tests en fin de chaîne. Et surtout, elle responsabilise l’équipe produit dans l’identification précoce des risques.
Le modèle de menace ne sert à rien s'il ne débouche pas sur des exigences vérifiables, et ça ca permet également de l’intégrer dans le quotidien des développeurs, des revues de code, des pipelines CI/CD. Par exemple, en utilisant des outils comme Semgrep ou Checkov pour détecter automatiquement les patterns de code à risque identifiés lors de l'atelier initial.
Prenons un contexte réglementaire exigeant : **une application web/API dans un scope PCI-DSS**, avec du paiement en ligne, de la gestion de cartes, et un front Angular exposé publiquement.
Voici des exigences issues du Threat Modeling qu'on peut vérifier automatiquement :
Menace identifiée | Exigence | Implémentation technique |
Fuite de PAN (Primary Account Number) dans les logs applicatifs | Masquage systématique des données sensibles dans les traces | Règle Semgrep sur logger.*(".*[0-9]{13,16}.*"), test d’intégration + mock logs dans CI |
Faible ségrégation des rôles sur les APIs de refund | Contrôle strict RBAC/API Gateway sur les opérations critiques | Scan d’infra avec Checkov + test d’appel POST /api/refund en tant qu’utilisateur de niveau standard |
Absence de vérification de la conformité des en-têtes de sécurité HTTP (CSP, HSTS, X-Frame-Options) | Présence obligatoire d’un jeu complet d’en-têtes sécurité dans toutes les réponses HTTP publiques | Test dans le pipeline CI/CD avec curl -I + script de validation des headers critiques attendus |
Appels sortants non filtrés depuis des conteneurs applicatifs | Détection et restriction des communications sortantes inutiles | Analyse du manifest K8s avec OPA + test runtime via proxy de sortie en mode audit |
Et niveau code ça pourrait donner ça :
Vérification des en-têtes HTTP (extrait .gitlab-ci.yml)
security_headers_check:
image: curlimages/curl:latest
script:
- |
curl -I https://monapp.exemple.com > headers.txt
grep -q "Strict-Transport-Security" headers.txt || (echo "HSTS manquant" && exit 1)
grep -q "Content-Security-Policy" headers.txt || (echo "CSP manquant" && exit 1)
grep -q "X-Frame-Options" headers.txt || (echo "X-Frame-Options manquant" && exit 1)
only:
- merge_requests
Test Semgrep sur les logs sensibles
# .semgrep.yml
rules:
- id: log-pan-detection
patterns:
- pattern: logger.$METHOD("$MSG")
- pattern-regex: ".*[0-9]{13,16}.*"
message: "PAN potentiellement loggé"
languages: [python, java, javascript]
severity: ERROR
Et dans le pipeline :
semgrep:
image: returntocorp/semgrep
script:
- semgrep --config .semgrep.yml
allow_failure: false
C'est un peu comme avoir un rappel constant : "Hé, souviens-toi, cette partie du code est sensible, fais attention." Et si une nouvelle menace est identifiée, on met à jour les règles, on adapte les outils, on continue à apprendre et à s'améliorer.
Gouvernance et conformité : un bonus non-négligeable
Ce modèle s'aligne parfaitement avec **OWASP SAMM (Design/Threat Assessment)**, et répond aussi à des exigences **ISO 27001 / PCI-DSS / RGPD**. Chaque contrôle automatisé devient une preuve, un indicateur, un gage de maturité.
Pas besoin de défendre son modèle à la prochaine revue de sécurité. Tu montres les logs. Tu montres que c'est dans le pipeline. Tu montres que ça tourne.
Conclusion
Le Threat Modeling ne doit pas être un artefact figé, oublié dans un coin. C’est un levier stratégique, un guide pour les choix d’architecture, un pont entre métier, tech et sécurité.
En le reconnectant au quotidien du delivery — via des contrôles automatisés, des règles vivantes, et une vigilance continue — tu lui redonnes sa place : celle d’un copilote. Discret mais essentiel.
*Références :*
- OWASP Threat Modeling: https://owasp.org/www-community/Threat_Modeling
- SAMM: https://owaspsamm.org/model/design/threat-assessment/
- Gitleaks: https://github.com/gitleaks/gitleaks
- Checkov: https://www.checkov.io/
- Semgrep: https://semgrep.dev/
- PCI-DSS v4.0: https://www.pcisecuritystandards.org/