Quand une clé de traduction devient une fuite de données
Un rapport d'incident à 2h du matin, une facture inattendue de 1 200 $ et une semaine de données produit exfiltrées vers l'Europe de l'Est. C'est l'histoire racontée par NEXU WP sur dev.to : une simple clé d'API de traduction partagée dans un thread Slack pour déboguer, oubliée là six mois, puis récupérée par un acteur malveillant.
Ce type d'incident est symptomatique d'une mauvaise hygiène des secrets dans les projets WordPress et PHP en général. Une clé d'API de traduction (Loco Translate, DeepL, Google Cloud Translation…) n'est pas une simple configuration : c'est un bearer token avec un rayon d'impact financier et opérationnel réel. Voici le playbook que nous appliquons chez MulerTech pour ne pas revivre ce scénario.
1. 🔍 Inventaire de vos credentials : savoir ce qui existe
Avant de sécuriser quoi que ce soit, il faut savoir ce qu'on possède. Lancez un audit rapide de vos dépôts et configurations :
# Rechercher des clés API potentiellement committées
git log --all --full-history -- '*.env' '*.php' | head -50
git grep -i 'api_key\|secret\|password\|token' -- '*.php' '*.env' '*.yml'
# Scanner l'historique git avec truffleHog
docker run --rm trufflesecurity/trufflehog:latest git file://. --only-verified
Ce qu'il faut inventorier :
- Clés d'API de services tiers (traduction, envoi d'e-mails, paiement, monitoring)
- Credentials de base de données (wp-config.php, .env)
- Tokens OAuth pour les intégrations CI/CD
- Clés SSH et certificats
Chaque secret doit avoir un propriétaire, une date de création et un scope défini.
2. 🔐 Migrer vers un gestionnaire de secrets
Le problème du « set and forget » décrit dans l'article source est universel. La solution passe par un gestionnaire de secrets centralisé. Deux options selon votre infrastructure :
Option A — HashiCorp Vault (auto-hébergé)
Adapté si vous gérez votre propre serveur (comme notre stack Docker sur IONOS).
# Démarrer Vault en mode dev pour tester
docker run --rm -p 8200:8200 hashicorp/vault server -dev
# Stocker un secret
export VAULT_ADDR='http://127.0.0.1:8200'
vault kv put secret/wordpress/loco-translate api_key="sk-xxxxxxxxxxxx"
# Lire le secret depuis une app PHP
vault kv get -field=api_key secret/wordpress/loco-translate
Dans votre code PHP/Symfony, utilisez le client officiel ou une simple requête HTTP vers l'API Vault :
$response = Http::withToken(env('VAULT_TOKEN'))
->get(env('VAULT_ADDR') . '/v1/secret/data/wordpress/loco-translate');
$apiKey = $response->json('data.data.api_key');
Option B — AWS Secrets Manager (cloud)
Si votre infrastructure est déjà AWS, c'est l'option la plus simple à maintenir :
# Créer un secret
aws secretsmanager create-secret \
--name "prod/wordpress/loco-translate" \
--secret-string '{"api_key":"sk-xxxxxxxxxxxx"}'
# Rotation automatique intégrée disponible via la console AWS
Règle d'or : aucune clé ne doit jamais transiter dans le code source, les logs ou les messages Slack. Les variables d'environnement sont un minimum ; un secret manager est la cible.
3. ♻️ Rotation automatisée et scopes par environnement
L'article source souligne une faiblesse critique : une seule clé couvre production, staging et développement local. C'est une violation du principe de moindre privilège.
Bonnes pratiques à appliquer immédiatement :
- Une clé par environnement (
prod,staging,dev) - Rotation planifiée : tous les 90 jours au maximum, via un cron ou un pipeline CI
- Scopes restreints : une clé de traduction ne doit lire que les langues concernées, pas exporter l'intégralité du catalogue
Exemple de script de rotation à intégrer dans un workflow n8n ou un cron :
#!/bin/bash
# rotate-loco-key.sh
NEW_KEY=$(generate_new_api_key) # appel à votre provider
vault kv patch secret/wordpress/loco-translate api_key="$NEW_KEY"
echo "[$(date)] Clé Loco Translate rotée avec succès" >> /var/log/key-rotation.log
4. 🛡️ Détection en CI/CD : bloquer avant le merge
La dernière ligne de défense est votre pipeline CI. Intégrez une étape de détection de secrets avant chaque merge :
# .github/workflows/security.yml (ou équivalent GitLab CI)
security-scan:
stage: test
image: trufflesecurity/trufflehog:latest
script:
- trufflehog git file://. --only-verified --fail
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
Pour les projets WordPress avec Composer, ajoutez également gitleaks comme hook pre-commit :
# Installation locale
brew install gitleaks # ou téléchargement depuis GitHub Releases
# Hook pre-commit
gitleaks protect --staged -v
Ces deux outils sont gratuits, rapides et détectent la grande majorité des patterns de clés connues (AWS, OpenAI, DeepL, Stripe, etc.).
Conclusion : la sécurité des secrets n'est pas une option
Une clé d'API partagée dans Slack peut sembler anodine. 1 200 $ de facture imprévue et une semaine de données exfiltrées plus tard, la leçon est claire : les credentials méritent le même niveau de rigueur que le code lui-même.
Le playbook est simple à déployer :
- Auditer l'existant avec truffleHog ou gitleaks
- Migrer vers Vault ou AWS Secrets Manager
- Scoper les clés par environnement et par usage
- Automatiser la rotation tous les 90 jours
- Bloquer toute fuite en CI avant le merge
Ces pratiques s'appliquent à tout projet PHP/Symfony/WordPress, quelle que soit sa taille. Le coût d'une mise en place est négligeable face au coût d'un incident.
Article inspiré du retour d'expérience de NEXU WP sur dev.to.