Dès qu’une extension WordPress propose une fonctionnalité basée sur l’IA, elle a besoin d’une clé API pour s’authentifier auprès du fournisseur de modèle de langage. Cette clé donne un accès direct à un service facturé à l’usage : quiconque se l’approprie peut consommer le quota du site, voire engendrer une facture importante en quelques heures de génération automatisée. Pourtant, il n’est pas rare de trouver des clés API stockées sans aucune protection dans les options WordPress, visibles en clair par n’importe qui a accès à la base de données ou, pire, exposées via un point de terminaison REST mal configuré.
Cet article passe en revue les trois approches courantes pour stocker une clé API dans un projet WordPress, avec leurs compromis respectifs.
L’option la plus simple : wp-config.php
Pour un site où une seule clé API sert à toute l’installation, la définir comme constante dans wp-config.php reste l’approche la plus robuste :
define( 'MON_EXTENSION_LLM_API_KEY', 'sk-xxxxxxxxxxxxxxxxxxxx' );
Ce fichier se trouve en dehors du répertoire servi publiquement sur la plupart des hébergements, n’est jamais exposé par l’API REST de WordPress, et échappe à toute requête SQL malveillante puisque la valeur n’est pas stockée en base. Son principal défaut est l’absence d’interface : changer la clé nécessite un accès au serveur, ce qui ne convient pas à une extension distribuée que des utilisateurs non techniques doivent pouvoir configurer eux-mêmes.
Le cas courant : un champ de réglages en base
Pour une extension grand public, la clé est généralement saisie dans un écran de réglages, via l’API register_setting(), puis stockée dans la table wp_options. Ce choix est légitime, mais il implique deux précautions souvent négligées.
La première concerne l’affichage : le champ de saisie doit être de type password et ne jamais renvoyer la valeur complète de la clé après enregistrement — afficher les derniers caractères seulement, à la manière des interfaces bancaires, suffit à confirmer qu’une clé est bien configurée sans la ré-exposer à chaque chargement de la page de réglages.

La seconde précaution concerne l’exposition via l’API REST de WordPress. Une option enregistrée avec register_setting() et le paramètre show_in_rest activé devient potentiellement lisible via un point de terminaison REST standard si les permissions ne sont pas correctement restreintes. Pour une clé API, ce paramètre doit rester désactivé, ou la lecture doit être protégée par un permission_callback strict limité aux administrateurs.
Chiffrer la clé avant stockage
Pour une protection supplémentaire, certaines extensions chiffrent la clé avant de l’écrire en base, plutôt que de la stocker en clair dans wp_options. L’idée est simple : même en cas d’accès direct à la base de données — sauvegarde mal protégée, faille SQL, export laissé accessible — la clé reste illisible sans la clé de chiffrement, généralement dérivée des constantes uniques définies dans wp-config.php comme AUTH_KEY ou SECURE_AUTH_KEY.
function mon_extension_chiffrer_cle( $cle_api ) {
$iv = random_bytes( 16 );
$chiffree = openssl_encrypt(
$cle_api,
'aes-256-cbc',
wp_salt( 'auth' ),
0,
$iv
);
return base64_encode( $iv . $chiffree );
}
Cette approche ajoute de la complexité et nécessite de conserver la même valeur de sel entre déchiffrements — un point de vigilance si le site migre d’environnement — mais elle réduit fortement la surface d’exposition en cas de fuite partielle des données.
Bonnes pratiques transverses
- Ne jamais journaliser une clé API dans les logs d’erreur, même en cas d’échec d’appel
- Ne jamais transmettre la clé côté client, y compris masquée dans un attribut HTML
- Limiter les capacités nécessaires pour modifier le réglage à
manage_options - Prévoir une rotation facile de la clé en cas de compromission suspectée
Une clé API se traite comme un mot de passe applicatif : elle ne s’affiche jamais entière une fois enregistrée.
En résumé
Le choix du mode de stockage dépend surtout du contexte : une constante dans wp-config.php convient à un site unique géré par une équipe technique, tandis qu’un champ de réglages chiffré s’impose pour une extension distribuée à un public plus large. Dans tous les cas, la règle reste la même : une clé API n’a rien à faire en clair dans une réponse REST, dans un log ou dans le code source d’une page.