# Ce qu’un état exposé par wp_interactivity_state ne doit jamais contenir

> L'état partagé par un bloc interactif atterrit tel quel dans le HTML envoyé au navigateur. Certaines données n'ont tout simplement rien à y faire.

- Auteur : Clément Hadrot
- Publié le : 2025-12-08
- Mis à jour le : 2025-12-08
- Catégorie : Sécurité
- URL : https://wpmoderne.dev.wordpress-developpement.fr/securite/etat-expose-wp-interactivity-state-ne-doit-jamais-contenir/

## L’essentiel

- L'état déclaré avec wp_interactivity_state est visible dans le code source
- Un identifiant de commande complet y avait été placé par erreur
- Seules les données nécessaires au rendu client doivent y figurer

`wp_interactivity_state()` ne chiffre rien, ne masque rien : la donnée qu'on y place se retrouve, telle quelle, dans une balise `script type="application/json"` insérée dans le HTML renvoyé au visiteur. C'est un point que beaucoup de développeurs découvrent en inspectant le code source d'une page après avoir intégré leur premier bloc interactif, souvent trop tard, après avoir placé une donnée sensible dans cet état par réflexe habituel. Ce billet ne revient pas sur le fonctionnement général de l'Interactivity API, mais sur une catégorie précise d'erreurs à éviter.

## Comprendre où va réellement l'état

Quand un bloc appelle `wp_interactivity_state('mon-espace-de-noms', array(...))` côté serveur, WordPress sérialise ce tableau en JSON et l'injecte directement dans le document HTML, avant même que la moindre interaction n'ait eu lieu côté navigateur. N'importe quel visiteur peut consulter cette donnée en ouvrant simplement le code source de la page, sans avoir besoin d'interagir avec le bloc ni de disposer d'outils particuliers.

## L'erreur observée sur un bloc de suivi de commande

> L'essentiel à retenir : L'état déclaré avec wp_interactivity_state est visible dans le code source ; Un identifiant de commande complet y avait été placé par erreur ; Seules les données nécessaires au rendu client doivent y figurer

Un développeur avait construit un bloc affichant le statut d'une commande en cours, avec une mise à jour dynamique de l'état de livraison sans rechargement de page. Pour simplifier l'accès aux données côté client, l'intégralité de l'objet commande avait été placée dans l'état partagé :

```
wp_interactivity_state('suivi-commande', array(
  'commande' => array(
    'id'              => $commande->get_id(),
    'email_client'    => $commande->get_billing_email(),
    'adresse'         => $commande->get_billing_address_1(),
    'montant_total'   => $commande->get_total(),
    'statut'          => $commande->get_status(),
    'jeton_paiement'  => $commande->get_meta('_jeton_stripe'),
  ),
));
```

L'adresse e-mail, l'adresse postale et surtout un jeton de paiement interne se retrouvaient ainsi visibles dans le code source de la page, accessibles à quiconque ouvrait les outils de développement du navigateur, y compris un visiteur n'ayant aucun lien avec cette commande s'il tombait sur la page par un lien mal protégé.

## Ce qui n'a rien à faire dans un état partagé

- Les jetons d'API, secrets de paiement ou identifiants de session internes.
- Les données personnelles non indispensables au rendu visuel du bloc (adresse complète, e-mail, numéro de téléphone).
- Les identifiants internes de base de données qui pourraient faciliter l'énumération d'autres ressources.
- Toute donnée dont la présence contredirait un contrôle d'accès déjà en place ailleurs sur le site.

## Reconstruire un état minimal

La correction retenue ne transmet plus que ce qui sert réellement l'affichage côté client, sous une forme déjà résumée côté serveur :

```
wp_interactivity_state('suivi-commande', array(
  'commande' => array(
    'statut_libelle' => domaine_libelle_statut($commande->get_status()),
    'etape_courante' => domaine_etape_livraison($commande),
  ),
));
```

Les données sensibles nécessaires au calcul du statut restent côté serveur, dans la fonction PHP qui prépare l'affichage, et ne transitent jamais vers le client. Si une mise à jour ultérieure a besoin d'une donnée supplémentaire, elle passe par un appel à un point de terminaison REST authentifié, plutôt que par un ajout dans l'état initial exposé à tous.

## Un principe simple à appliquer systématiquement

> Avant d'appeler `wp_interactivity_state()`, posez-vous la question suivante : accepteriez-vous que cette donnée figure en clair dans un e-mail envoyé à tous vos visiteurs ? Si la réponse est non, elle n'a pas sa place dans l'état partagé.

## Vérifier les blocs déjà en production

Un audit rapide consiste à ouvrir le code source des pages utilisant des blocs interactifs et à rechercher les balises `type="application/json"` associées à un espace de noms d'interactivité, puis à examiner ce qu'elles contiennent réellement. Cette vérification, rapide à mener, révèle souvent des données placées par commodité lors du développement et jamais retirées avant la mise en production.

## En résumé

L'état de l'Interactivity API est un canal public par construction, pas un espace de stockage serveur. Tout ce qui y figure doit être considéré comme visible par n'importe quel visiteur du site, ce qui impose de limiter son contenu aux seules données strictement nécessaires au rendu de l'interface.
