Chez un client qui gère une boutique de vente de mobilier sur mesure, l’intégration avec Make (l’ancien Integromat) sert à créer automatiquement une commande de fabrication dans un CPT personnalisé dès qu’une commande WooCommerce passe en statut « payée ». Le scénario Make se connecte à WordPress via un mot de passe d’application, généré depuis le profil d’un utilisateur nommé make-integration. Ce compte avait été créé avec le rôle administrator, « pour être sûr que ça marche », comme l’a expliqué le prestataire précédent.
C’est une pratique extrêmement répandue et, sur le papier, elle fonctionne toujours : un administrateur peut tout faire, donc l’intégration ne tombera jamais en panne faute de droits. Le problème apparaît le jour où ce mot de passe d’application fuite, que ce soit par un scénario Make mal partagé, une capture d’écran envoyée sur un canal Slack, ou une fuite chez le prestataire tiers lui-même. Un attaquant en possession de ces identifiants obtient alors un accès administrateur complet au site, alors que l’intégration n’avait besoin, dans les faits, que de créer des articles d’un seul type de contenu.
Identifier ce dont l’intégration a réellement besoin
La première étape consiste à lister précisément les appels que l’intégration effectue, pas ce qu’elle pourrait théoriquement faire un jour. Pour ce scénario Make, l’inventaire donne : créer un article du CPT commande_fabrication, y attacher des champs personnalisés via ACF, et lire les commandes WooCommerce pour récupérer les informations client. Rien qui nécessite de gérer les utilisateurs, d’installer des extensions ou de modifier les réglages du site.
WordPress distingue les rôles (des étiquettes) des capacités (les permissions elles-mêmes). Un rôle n’est qu’un ensemble nommé de capacités, et rien n’empêche de créer un rôle sur mesure qui ne contient que celles dont un compte de service a besoin. C’est l’approche à privilégier plutôt que de retirer des capacités une à une à un rôle existant, ce qui laisse toujours un doute sur ce qui reste accessible.
Construire le rôle pas à pas

Voici comment créer, via un plugin utilitaire ou un script d’activation, un rôle service_make limité au strict nécessaire :
add_action( 'init', function () {
if ( get_role( 'service_make' ) ) {
return;
}
add_role( 'service_make', 'Service Make', array(
'read' => true,
'edit_commande_fabrication' => true,
'edit_others_commande_fabrications' => false,
'publish_commande_fabrications' => true,
'edit_published_commande_fabrications' => true,
) );
} );
Ce rôle n’accorde pas edit_posts au sens large, mais uniquement les capacités spécifiques au type de contenu personnalisé, à condition que ce CPT ait été enregistré avec des capability_type dédiés plutôt qu’avec les capacités génériques de post. C’est un détail de conception qui se décide au moment de la création du CPT :
register_post_type( 'commande_fabrication', array(
'capability_type' => 'commande_fabrication',
'map_meta_cap' => true,
'capabilities' => array(
'edit_post' => 'edit_commande_fabrication',
'edit_posts' => 'edit_commande_fabrications',
'publish_posts' => 'publish_commande_fabrications',
'read_post' => 'read_commande_fabrication',
),
// ...
) );
Restreindre la lecture des commandes WooCommerce
Le deuxième besoin, lire les commandes WooCommerce, pose un problème différent : la capacité native est edit_shop_orders, qui donne accès en lecture et en écriture aux commandes, avec un champ d’action large. Plutôt que d’accorder cette capacité telle quelle, il est préférable d’exposer un endpoint REST personnalisé, en lecture seule, qui ne renvoie que les champs strictement nécessaires à l’automatisation :
- Un endpoint
/wp-json/monsite/v1/commandes-payeesqui filtre déjà par statut côté serveur. - Un
permission_callbackqui vérifie une capacité personnalisée, par exemplelire_commandes_payees, ajoutée uniquement au rôleservice_make. - Aucune capacité d’écriture accordée sur les commandes elles-mêmes : la création de commande de fabrication passe par le CPT dédié, jamais par une modification directe de la commande WooCommerce.
Tester que rien d’autre n’est accessible
Une fois le rôle créé, il faut vérifier concrètement ses limites, pas seulement faire confiance à la déclaration des capacités. La méthode la plus fiable consiste à générer un mot de passe d’application pour un compte de test doté du rôle service_make, puis à tenter, avec ce jeton, une série d’appels qui ne devraient pas fonctionner :
curl -u service-test:xxxx-xxxx-xxxx-xxxx \
https://exemple.fr/wp-json/wp/v2/users
curl -u service-test:xxxx-xxxx-xxxx-xxxx \
-X POST https://exemple.fr/wp-json/wp/v2/plugins
Ces deux appels doivent renvoyer une erreur rest_forbidden avec un code 401 ou 403, jamais une réponse exploitable. Si l’un d’eux réussit, c’est qu’une capacité a été accordée par erreur, souvent via un plugin tiers qui étend automatiquement les droits d’un rôle qu’il ne connaît pas.
Un compte de service ne devrait jamais pouvoir faire, sur le papier, plus que ce que son scénario d’automatisation fait réellement. Le jour où ce n’est plus vrai, c’est que quelqu’un a coché « administrateur » par facilité.
Pour aller plus loin
Cette logique de compte de service à capacités minimales s’applique à toute intégration tierce, pas seulement à Zapier ou Make : un plugin de synchronisation avec un ERP, un connecteur de comptabilité, un outil de marketing automation. La règle reste la même : lister les actions réelles avant de créer le compte, construire un rôle sur mesure plutôt que de partir d’un rôle existant qu’on restreint, et vérifier par des appels concrets que les portes fermées le sont vraiment. Le gain en cas de fuite d’identifiants est considérable : un mot de passe d’application volé sur un compte service_make ne permet de créer que des commandes de fabrication, là où le même vol sur un compte administrateur aurait ouvert tout le site.