vendredi 25 septembre 2026

À propos

Contact

Sécurité

register_activation_hook : ce qu’une extension ne doit jamais faire à l’install

Certaines extensions créent des comptes admin ou désactivent des protections dès l'activation. Revue des dérives observées et de ce qu'un hook d'activation doit se limiter à faire.

Par Clément Hadrot • 28 juillet 2020 • 3 min de lecture • Aucun commentaire
register_activation_hook : ce qu'une extension ne doit jamais faire à l'install

En reprenant la maintenance d’un site e-commerce pour un nouveau client, nous passons en revue la liste des utilisateurs avant de faire le point sur les accès. Trois comptes avec le rôle administrator ne correspondent à personne dans l’équipe : support_plugin, backup_admin et un compte au nom d’une extension de formulaire. Aucun des trois n’a jamais servi à se connecter manuellement. En creusant le code des extensions installées, la cause apparaît : chacune crée un compte administrateur dans son register_activation_hook, « pour faciliter le support », sans jamais le supprimer ni même le documenter dans la description du plugin.

Ce n’est pas un cas isolé. Le hook d’activation, exécuté une seule fois quand une extension est activée, est un moment de confiance quasi totale : le code s’exécute avec les mêmes privilèges que n’importe quelle action d’administration, avant même que l’utilisateur ait pu configurer quoi que ce soit. C’est précisément ce qui en fait une cible tentante pour des raccourcis dangereux, volontaires ou non.

Le rôle légitime d’un hook d’activation

register_activation_hook( __FILE__, 'ma_fonction_activation' ) est prévu pour préparer le terrain, pas pour agir sur le compte ou la sécurité du site. Ses usages légitimes sont bien délimités :

  • Créer les tables personnalisées nécessaires au fonctionnement du plugin, via dbDelta().
  • Enregistrer des options par défaut avec add_option(), jamais avec des valeurs qui modifient un comportement de sécurité existant.
  • Planifier une tâche cron avec wp_schedule_event() si l’extension en a besoin.
  • Vérifier la version de PHP ou de WordPress et désactiver proprement l’extension avec un message clair si les prérequis ne sont pas remplis.

Rien dans cette liste ne justifie de toucher aux comptes utilisateurs, aux rôles existants, ou aux réglages de sécurité déjà en place sur le site.

Les dérives observées sur des extensions réelles

L'essentiel à retenir : L'activation n'est pas un moment de confiance illimitée ; Créer un compte doit rester un choix explicite ; Se limiter à préparer, jamais à modifier la sécurité existante

Au fil de nos audits, plusieurs mauvaises pratiques reviennent avec une régularité frappante :

  • Création d’un compte administrateur caché. Le prétexte est presque toujours le support technique, mais un compte silencieux avec un mot de passe généré une seule fois et jamais communiqué au client est une porte dérobée, qu’elle soit intentionnelle ou non.
  • Désactivation de vérifications de sécurité existantes. Nous avons vu un plugin de formulaire retirer la vérification par nonce sur ses propres points d’entrée « pour simplifier l’intégration », en modifiant une option globale au lieu de gérer son propre traitement.
  • Modification de wp-config.php ou du .htaccess sans consentement, par exemple pour augmenter WP_MEMORY_LIMIT ou ajouter des règles de réécriture, sans jamais prévenir ni permettre de revenir en arrière proprement.
  • Envoi de données vers un serveur distant dès l’activation, avant tout consentement explicite de l’administrateur, pour du télémétrie ou de la validation de licence.

Chacun de ces cas partage un point commun : l’action est irréversible ou invisible pour l’administrateur du site, qui n’a aucun moyen simple de savoir qu’elle a eu lieu.

Ce qu’un hook d’activation propre ressemble

register_activation_hook( __FILE__, 'moncpt_activation' );

function moncpt_activation() {
    // Vérification des prérequis, sans effet de bord.
    if ( version_compare( PHP_VERSION, '7.4', '<' ) ) {
        deactivate_plugins( plugin_basename( __FILE__ ) );
        wp_die(
            esc_html__( 'Cette extension nécessite PHP 7.4 ou supérieur.', 'moncpt' )
        );
    }

    // Création de table dédiée, isolée du reste du site.
    global $wpdb;
    require_once ABSPATH . 'wp-admin/includes/upgrade.php';

    $table   = $wpdb->prefix . 'moncpt_favoris';
    $charset = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE {$table} (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        user_id BIGINT UNSIGNED NOT NULL,
        post_id BIGINT UNSIGNED NOT NULL,
        PRIMARY KEY (id)
    ) {$charset};";

    dbDelta( $sql );

    // Valeur par défaut, sans jamais toucher à une option existante d'un autre plugin.
    add_option( 'moncpt_version', '1.0.0' );

    // On planifie proprement, on vide au moment de la désactivation.
    if ( ! wp_next_scheduled( 'moncpt_nettoyage_quotidien' ) ) {
        wp_schedule_event( time(), 'daily', 'moncpt_nettoyage_quotidien' );
    }
}

Rien ici ne crée de compte, ne modifie de réglage existant, ni n’envoie de données. Tout est réversible via le hook de désactivation symétrique, register_deactivation_hook(), qui doit annuler exactement ce que l’activation a mis en place.

Une checklist de revue avant de valider une extension tierce

Avant d’installer une extension inconnue sur un site client, la lecture de son fichier principal et de ses hooks d’activation permet de repérer les signaux d’alerte en quelques minutes : recherche des chaînes wp_insert_user, add_user, update_option( 'users_can_register', ou d’appels réseau (wp_remote_post, curl_exec) directement dans la fonction d’activation. Leur présence n’est pas toujours malveillante, mais elle mérite systématiquement une explication.

Sur nos projets, la règle est simple : si une action au moment de l’activation n’est pas explicable en une phrase à un client non technique, elle n’a rien à faire dans register_activation_hook.

En résumé

L’activation d’une extension doit rester un moment de préparation technique, jamais un moment de décision silencieuse sur la sécurité ou les comptes du site. Les trois comptes fantômes retrouvés chez ce client ont été supprimés, les mots de passe des comptes restants régénérés par précaution, et une règle a été ajoutée à notre processus d’intégration : toute nouvelle extension passe désormais par une lecture rapide de son code d’activation avant d’être autorisée sur un site en production.

Partager :

À propos de l'auteur

Clément Hadrot

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

Voir tous ses articles

Dans la même veine

À lire aussi