Case study · Sécurité & agent IA interne

Audit sécurité & TMA/MCO
multi-sites

Audit de trois sites WordPress d'une agence de services notariaux, incluant une intrusion active détectée. Un outil de suivi construit en cours de mission a transformé un audit figé en agent de suivi réutilisable — avec son propre connecteur MCP pour Claude.

Client
Agence de services notariaux
Sites audités
3 sites WordPress (vitrine, événementiel, thème sur mesure)
Rôle
Audit sécurité, UX/a11y, construction d'outil
Période
Juillet — septembre 2026
Stack outil
Flask, SQLite, Lighthouse, API WPScan
Résultat
34 / 38 actions livrées (89 %)

Point de départ, pas prévu au cahier des charges : un des trois sites a été piraté en cours de mission (accès non autorisé confirmé, vol d'identifiants), invalidant un premier diagnostic « aucune compromission détectée ». La vulnérabilité en cause — une faille critique d'un plugin tiers, déjà identifiée dans l'audit initial mais non encore corrigée — a servi de point d'entrée.

Contexte

Un audit classique, pas un outil

La demande initiale portait sur un audit TMA/MCO (Tierce Maintenance Applicative / Maintien en Condition Opérationnelle) sur trois sites WordPress hétérogènes, dont l'un hébergé en interne, sans spécialiste WordPress dédié côté client — le rapport devait rester lisible pour une IT généraliste.

Trois sites, trois profils

  • Site A — hébergement interne, compromis en cours d'audit.
  • Site B — site vitrine, extension d'édition de pages premium.
  • Site C — thème sur mesure, extension de champs premium.

15 catégories d'audit

Sécurité applicative, comptes, mises à jour, performance, accessibilité, SEO/GEO, RGPD, conformité RGAA — recoupées avec les référentiels officiels ANSSI (ReCyF), OWASP Top 10, CNIL et le guide de durcissement WordPress.org, pas une checklist maison.

Problème

Un rapport Word ne survit pas à une remédiation qui dure des mois

Un audit ponctuel produit un PDF figé le jour J. Mais la remédiation s'étale sur plusieurs mois, avec des régressions (une mise à jour de plugin peut annuler un correctif de sécurité), des faux positifs à trancher, et un client qui a besoin de voir l'état réel sans relire 30 pages à chaque point hebdo.

Ce qui ne marchait pas avec un rapport statique

  • Aucune trace de l'évolution des scores de performance/accessibilité dans le temps.
  • Les quotas de l'API Google PageSpeed Insights (erreur 429) rendaient le suivi Lighthouse peu fiable.
  • Les CVE des extensions premium ne sont pas détectables par un scan classique — bloqué par le rate-limiting de l'hébergeur.

Incident révélateur

Une mise à jour de l'extension de durcissement WP Hide l'a désactivée et a effacé ses règles .htaccess — annulant sans bruit une correction validée trois semaines plus tôt. Un rapport figé ne détecte jamais ce genre de régression silencieuse. Seul un suivi qui revérifie dans le temps le peut.

Solution

Un tracker local, construit au fil des besoins réels

Chaque fonctionnalité répond à une limite concrète rencontrée pendant l'audit, pas à un plan fixé à l'avance. L'outil (Flask + SQLite) tourne en local sur la machine, sans serveur distant à maintenir.

Scan automatisé sans identifiants

Un bouton « agent » par site exécute, serveur à serveur, les vérifications publiques : en-têtes de sécurité, points d'entrée connus pour le brute-force, exposition de comptes via l'API, robots.txt (règles IA), sitemap, balises SEO, images sans description. Résultat historisé.

Lighthouse en local, sans quota

Remplacement de l'API PageSpeed Insights (429 fréquent) par le moteur Lighthouse officiel piloté en local via Node.js/Chrome — mêmes scores, aucune limite d'usage, historique par site conservé en base.

Croisement CVE contournant le rate-limiting

Plutôt qu'un scan WPScan classique (bloqué par le pare-feu du client), l'outil interroge l'API WPScan plugin par plugin à partir d'un inventaire déjà relevé en wp-admin — même résultat, sans déclencher les protections anti-bot.

Export client en un clic

Un bouton régénère un fichier HTML autonome (checklist + preuves vidéo en base64 + derniers résultats figés) prêt à envoyer — sans base de données ni serveur requis côté destinataire.

Connecteur MCP — l'agent devient outillage pour Claude

L'outil expose ses fonctions (list_audits(), generate_presentation()) comme serveur MCP, enregistrable dans Claude Desktop ou Claude Code : générer une présentation HTML stylée (charte Ouidou, navigation clavier, loupe sur les preuves) depuis un prompt, directement depuis les mêmes données que le reste de l'outil, toujours à jour.

FlaskSQLiteLighthouse CLIAPI WPScanServeur MCPmu-plugins
Décisions

Trois choix qui ont évité des erreurs classiques

  1. HSTS sans includeSubDomains

    Un sous-domaine Matomo hors contrôle rendait l'option irréversible côté navigateur en cas de problème de certificat — écartée par prudence, pas par oubli.

  2. Corrections en mu-plugins et hors bloc WordPress

    Les correctifs d'accessibilité et de durcissement .htaccess sont posés en dehors des zones gérées par WordPress/les extensions, pour survivre à leurs mises à jour — exactement ce que l'incident WP Hide a confirmé nécessaire.

  3. WP Migrate DB Pro supprimé, pas juste désactivé

    Une extension désactivée reste du code présent et une vulnérabilité théoriquement atteignable. Sans usage réel, elle a été retirée (11 Mo de code, 20 options en base), licence conservée pour un éventuel renouvellement.

Impact

89 % de la sélection MCO livrée et vérifiée

Chaque correction a été précédée d'une sauvegarde et suivie d'un contrôle en production (code HTTP, poids de page, présence du formulaire/titre/images, absence d'erreur PHP) — rien n'a été livré sans vérification.

34 / 38

actions livrées et vérifiées en production (89 % du périmètre)

−79 %

poids de la vidéo de fond du Site C (26,3 → 5,4 Mo), page de 29,5 à 8,6 Mo

6/6

en-têtes de sécurité HTTP posés sur les deux sites qui n'en servaient aucun ou trois

103

médias décrits (textes alternatifs) sur le Site C, dont 6 forcés à vide dans le thème

« Une mise à jour de sécurité peut annuler une correction de sécurité. »Enseignement tiré de l'incident WP Hide — a motivé le passage des correctifs en mu-plugins autonomes.

Transparence

Ce qui reste bloqué, et pourquoi ce n'est pas un échec caché

4 actions sur 38 ne sont pas closes — aucune n'est bloquée techniquement, toutes nécessitent une décision ou un accès côté client.

BlocageNatureCe qu'il faut
Extensions premium (édition de pages / champs)Licences non validées côté éditeurAccès aux comptes ou identité du détenteur de licence
Formulaires du Site AEmails rejetés (configuration DNS du domaine client)Accord du responsable du domaine concerné
Comptes admin du Site ASite compromis — tout compte antérieur suspectLe client doit dire qui garde légitimement un accès
Environnement de préproductionCopie du site accessible sans authentificationProtection d'accès — signalé en priorité absolue