Table of Contents
Sécurité
Principes
Le projet applique trois règles absolues pour protéger les secrets :
- Aucun secret en clair : ni dans le code source, ni dans les logs, ni dans les messages d'erreur, ni dans les fixtures de test.
- Masquage systématique : utiliser
redact_url(),redact_secrets()etredact_exception()depuisutils/redaction.py. - Chaînage d'exceptions : ne jamais conserver une exception externe brute comme
__cause__ou__context__. Journaliser la version expurgée puis utiliserraise ... from None, ou chaîner une cause elle-même expurgée.
Masquage des données sensibles
Masquage des URLs
La fonction redact_url() masque les paramètres sensibles dans les URLs. Les clés sensibles (insensibles à la casse) sont : icalsecurise, token, key, password, secret. Elle utilise urlsplit/urlunsplit/parse_qsl pour reconstruire l'URL. En cas d'erreur de parsing, elle retourne REDACTED_URL.
Masquage des secrets dans le texte
La fonction redact_secrets() masque les URLs et les tokens isolés dans un texte. Elle traite les motifs comme : icalsecurise=XXX, token=XXX, password=XXX, secret=XXX. Les secrets supplémentaires (extra_secrets) sont triés par longueur décroissante pour éviter les masquages partiels.
Masquage des exceptions
La fonction redact_exception(exc, extra_secrets=()) applique redact_secrets au message de l'exception et aux secrets configurés. La méthode Settings.redaction_secrets() retourne un tuple de tous les secrets configurés (mots de passe, clés API) à transmettre.
Configuration des logs
Le formatter RedactingFormatter dans utils/logging.py masque les secrets dans tous les enregistrements de log :
- Masquage de
record.msg - Masquage de
record.args(gère les tuples et les dictionnaires) setup_logging()configure un handlerstdoutavec ce formatter- Les loggers tiers (
urllib3,slixmpp) sont positionnés surWARNING
Types sécurisés
Les mots de passe et clés API utilisent pydantic.SecretStr :
- Ils ne sont jamais sérialisés en clair.
- Ils sont masqués dans les messages d'erreur Pydantic (
hide_input_in_errorspour les paramètres XMPP).
Vérification avant déploiement
Règles de détection
Le script scripts/check_secrets.py analyse le dépôt pour détecter les secrets littéraux avec trois motifs regex :
- Affectation littérale :
key = "value"oukey: "value"(valeur de 3+ caractères entre guillemets) - Affectation non quotée : pour les fichiers de configuration (
.conf,.ini,.toml,.yaml,.yml),key = value(valeur de 3+ caractères non quotée) - Paramètre d'URL :
?token=XXXou&api_key=XXX(valeur de 3+ caractères)
Exclusions
Le script exclut :
- Les répertoires
.git,.venv,.worktrees,__pycache__ - Les fichiers
.env(jamais versionnés) - Le fichier
GUIDE_DEV_PYTHON.md(exemples intentionnels) - Le répertoire
tests/ - Les lignes marquées avec
secret-check: allow(liste blanche locale pour les fixtures/exemples)
Utilisation
# Vérifier tout le dépôt
python scripts/check_secrets.py
# Vérifier uniquement les fichiers indexés (avant un commit)
python scripts/check_secrets.py --staged
Les codes de sortie sont :
0: aucun secret détecté1: secrets trouvés2: erreur lors de l'exécution
Les résultats n'exposent jamais la valeur détectée, seulement le chemin, le numéro de ligne et le nom de la règle.
Tests de non-fuite
La suite de tests inclut des tests de non-fuite obligatoires :
- Injecter des valeurs sentinelles distinctes dans l'URL, les identifiants, le mot de passe et la clé API
- Provoquer une erreur externe
- Vérifier l'absence dans :
- Le message d'erreur
- Les logs
__cause__et__context__- Le traceback complet
Chaque secret utilise une sentinelle distincte pour identifier précisément toute fuite éventuelle.
Fichier .env
Le fichier .env n'est jamais commité (couvert par .gitignore). Utiliser .env.example comme modèle. En production, le fichier doit être local et lisible uniquement par le compte de service :
sudo install -d -m 0700 -o <service-user> -g <service-group> <config-dir>
sudo install -m 0600 -o <service-user> -g <service-group> .env <env-file>
Bonnes pratiques
- Ne jamais placer de secrets dans les unités systemd, les commandes shell ou les journaux système.
- Éviter de partager les exports de logs sans revue : les données sensibles de l'environnement ou des outils tiers ne doivent pas être supposées sûres par défaut.
- Après modification des identifiants, relancer
check_secrets.pyet un--dry-runavant de redémarrer le service. - En cas d'échec, ne pas redémarrer automatiquement après modification des identifiants : corriger la configuration, relancer les vérifications, puis consulter le journal expurgé.
Voir aussi : Configuration pour les variables d'environnement, Déploiement pour la configuration en production.