Le WordPress d'aujourd'hui, décodé pour les développeurs

Headless & API

Un annuaire de praticiens headless : un champ trop exposé via WPGraphQL

Le schéma WPGraphQL d'un annuaire de praticiens exposait par défaut des coordonnées internes que le front n'aurait jamais dû recevoir. Correctif par contrôle d'accès par champ.

Par WordPress Développement • 16 septembre 2023 • 4 min de lecture • Aucun commentaire
Un annuaire de praticiens headless : un champ trop exposé via WPGraphQL

Une simple requête d’introspection GraphQL a suffi à révéler le problème : un champ nommé adresse_facturation, censé rester strictement interne à la gestion administrative d’un annuaire de praticiens, apparaissait dans le schéma public consommé par le front de recherche. N’importe quel visiteur capable de lire une documentation GraphQL pouvait interroger ce champ pour l’ensemble des 340 fiches publiées.

Ce type de fuite ne provient presque jamais d’une intention malveillante côté développement, mais d’un réflexe habituel avec les champs personnalisés ACF : dès qu’un champ est ajouté au groupe de champs d’un type de contenu, WPGraphQL for ACF l’expose automatiquement dans le schéma, sans distinction entre une donnée destinée au front public et une donnée strictement administrative.

Le problème : l’exposition par défaut des champs ACF

Le groupe de champs personnalisés associé au type praticien contenait, pêle-mêle, des informations pensées pour un usage back-office (adresse de facturation, numéro de SIRET, notes internes de validation) et des informations destinées à l’affichage public (spécialité, ville d’exercice, disponibilités). WPGraphQL for ACF ne fait pas cette distinction automatiquement : tout champ activé pour l’affichage dans le groupe ACF devient, par défaut, un champ interrogeable du schéma GraphQL, sans notion de visibilité par rôle intégrée nativement.

Le front de recherche, développé en Astro, n’interrogeait effectivement que les champs publics dans ses requêtes. Rien n’empêchait cependant un tiers d’écrire sa propre requête ciblant directement adresseFacturation, dès lors que ce champ figurait dans le schéma exposé publiquement à l’endpoint /graphql.

Diagnostic par introspection

La méthode de vérification la plus rapide consiste à interroger le schéma lui-même :

query {
  __type(name: "Praticien") {
    fields {
      name
    }
  }
}
L'essentiel à retenir : Un champ ACF ajouté au schéma WPGraphQL est visible par défaut sans restriction de rôle ; Le hook graphql_object_fields permet de retirer un champ du schéma pour les requêtes non authentifiées ; Un audit de schéma avec l'introspection GraphQL révèle rapidement ce qui est publiquement accessible

Cette requête, envoyée sans aucune authentification, a listé l’intégralité des champs disponibles sur le type, révélant immédiatement la présence de champs qui n’auraient jamais dû sortir du back-office.

Correctif : retirer le champ du schéma public

Deux approches ont été envisagées. La première, désactiver purement et simplement l’exposition GraphQL du champ dans la configuration ACF, a été écartée car un usage interne au back-office nécessitait malgré tout d’y accéder via une requête authentifiée pour un outil de gestion administrative séparé. La seconde approche, retenue, restreint l’accès selon le contexte de la requête grâce au filtre graphql_object_fields :

add_filter('graphql_object_fields', function ($fields, $type_name) {
    if ($type_name !== 'Praticien') {
        return $fields;
    }

    $champs_sensibles = ['adresseFacturation', 'numeroSiret', 'notesInternesValidation'];

    foreach ($champs_sensibles as $champ) {
        if (!is_user_logged_in() || !current_user_can('manage_options')) {
            unset($fields[$champ]);
        }
    }

    return $fields;
}, 10, 2);

Avec ce filtre, une requête non authentifiée reçoit désormais une erreur explicite de type Cannot query field sur ces champs, plutôt que de simplement recevoir une valeur vide qui aurait pu masquer le problème sans le résoudre.

Aller plus loin : un audit systématique du schéma

Ce type de fuite justifie la mise en place d’un contrôle automatisé, exécuté à chaque déploiement, comparant la liste des champs exposés du schéma public à une liste blanche validée par l’équipe. Un script CI simple, interrogeant l’endpoint d’introspection et comparant le résultat à un fichier de référence versionné, suffit à détecter tout nouveau champ ajouté par erreur avant sa mise en production.

  • Extraction du schéma via une requête d’introspection standard
  • Comparaison avec une liste blanche de champs autorisés par type
  • Échec du pipeline de déploiement en cas d’écart non validé

Ce que cet incident ne couvre pas

Cet audit s’est volontairement limité à la question de l’exposition technique du schéma. Les praticiens exerçant dans le secteur de la santé, la question plus large de la conformité RGPD sur les données de santé au sens strict relève d’un traitement à part, avec ses propres bases légales et exigences de sécurisation renforcée, qui dépasse le cadre de ce correctif ponctuel.

En résumé

WPGraphQL for ACF expose par défaut tout champ activé dans un groupe de champs personnalisés, sans distinction implicite entre données publiques et données internes. Un contrôle d’accès explicite par champ, couplé à un audit régulier du schéma, reste la seule garantie fiable contre ce type de fuite silencieuse, bien plus discrète qu’une faille applicative classique.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi