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

Extensions

Une capacité ajoutée par une extension, jamais retirée à la désinstallation

Pour les développeurs qui doivent nettoyer proprement les capacités créées par leur extension au moment de sa désinstallation.

Par WordPress Développement • 5 septembre 2023 • 4 min de lecture • Aucun commentaire
Une capacité ajoutée par une extension, jamais retirée à la désinstallation

« Pourquoi ce rôle éditeur a-t-il encore la capacité gerer_campagnes_promo alors que l’extension qui l’a créée a été supprimée depuis huit mois ? » Cette question, posée en audit de sécurité sur un site qui avait changé plusieurs fois de prestataire, a mis au jour un comportement méconnu du système de rôles WordPress : une capacité ajoutée par une extension via add_cap() ne disparaît jamais toute seule, même après désactivation et suppression complète du code qui l’a créée.

Ce comportement n’est pas un bug de WordPress mais une conséquence directe de la façon dont les rôles sont stockés : dans l’option wp_user_roles, sérialisée en base de données, indépendamment du code des extensions qui les ont modifiés à un instant donné.

Symptôme : une capacité qui survit à son créateur

Le rôle editor du site audité listait, parmi ses capacités, gerer_campagnes_promo, une capacité qui ne correspondait à aucune extension active. Une recherche dans l’historique Git du dépôt du site a permis de retrouver son origine : une extension de gestion de campagnes promotionnelles, développée en interne, qui avait ajouté cette capacité au rôle éditeur lors de son activation, puis avait été retirée du site sans jamais avoir prévu de nettoyage à la désinstallation.

Le risque ne se limite pas à une ligne superflue dans la table des rôles : une capacité orpheline peut être réutilisée, volontairement ou par erreur, par une future extension qui choisirait le même nom sans savoir qu’il correspond déjà à des permissions actives sur certains rôles.

Diagnostic : où vivent les capacités

L'essentiel à retenir : add_cap modifie durablement la table des rôles en base ; La désactivation n'efface jamais les capacités ajoutées ; remove_cap doit être appelé explicitement à la désinstallation

Les rôles et leurs capacités associées sont stockés dans une option unique, généralement nommée {prefixe}_user_roles, sous forme de tableau sérialisé associant chaque rôle à la liste de ses capacités booléennes. Contrairement aux options de réglage d’une extension, cette structure n’est jamais liée à un préfixe ou un identifiant d’extension : rien dans sa structure ne permet de savoir automatiquement quelle extension a ajouté quelle capacité.

global $wp_roles;
$capacites_editor = $wp_roles->roles['editor']['capabilities'];
var_dump( $capacites_editor );
// Affiche notamment : ["gerer_campagnes_promo"] => bool(true)

Cette commande, exécutée via WP-CLI avec wp eval, a permis de confirmer la présence de la capacité orpheline directement dans la structure en mémoire des rôles, chargée depuis l’option en base.

Correctif : retirer explicitement à la désinstallation

La correction pour une extension encore active consiste à appeler remove_cap() sur chaque rôle concerné, dans le hook de désinstallation, en miroir exact des appels à add_cap() effectués à l’activation.

register_activation_hook( __FILE__, function () {
    $role = get_role( 'editor' );
    if ( $role ) {
        $role->add_cap( 'gerer_campagnes_promo' );
    }
} );

register_uninstall_hook( __FILE__, 'campagnes_promo_desinstallation' );

function campagnes_promo_desinstallation() {
    $role = get_role( 'editor' );
    if ( $role ) {
        $role->remove_cap( 'gerer_campagnes_promo' );
    }
}

Pour l’extension déjà désinstallée sans ce nettoyage sur le site audité, la correction ponctuelle est passée par une commande WP-CLI exécutée une seule fois : wp eval "get_role('editor')->remove_cap('gerer_campagnes_promo');", après avoir confirmé qu’aucune autre extension active ne dépendait de cette capacité.

Prévenir la récidive

  • Tenir la liste des capacités personnalisées ajoutées par une extension directement dans son fichier principal, en commentaire, pour que le retrait à la désinstallation ne soit jamais oublié lors d’une refonte du code.
  • Préfixer les noms de capacités personnalisées, comme les noms de fonctions, pour repérer facilement leur origine des mois ou des années plus tard.
  • Auditer périodiquement les rôles d’un site avec wp role list et une inspection des capacités, en particulier après la désinstallation de toute extension qui gérait des permissions personnalisées.

Le réflexe que je recommande systématiquement : toute extension qui appelle add_cap() à l’activation doit prévoir, dès son écriture, l’appel symétrique à remove_cap() dans son hook de désinstallation, avant même que la fonctionnalité principale ne soit terminée.

En résumé

Une capacité ajoutée à un rôle survit indéfiniment à l’extension qui l’a créée, tant qu’un retrait explicite n’est pas programmé. Ce nettoyage relève d’une discipline d’écriture d’extension simple mais souvent négligée ; il ne concerne pas les types d’intersection PHP, sujet distinct qui touche au typage du langage plutôt qu’au système de rôles WordPress.

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