Checklist sécurité Python : 25 vérifications avant de lancer un script sérieux

Sécuriser un script Python, c’est anticiper ce qui peut mal tourner avant de le lancer sur de vraies données : protéger les fichiers d’origine, sortir les secrets du code, rendre les erreurs visibles et limiter ce que le script a le droit de faire. La checklist en 25 points et le mini-lab « dry-run » ci-dessous vous donnent une méthode concrète, même en débutant.

Un script Python commence presque toujours comme un petit fichier sans prétention : renommer des fichiers, appeler une API, traiter un CSV, automatiser une corvée. Puis il grandit. Il lit de vrais fichiers, manipule des données clients, utilise une clé API, tourne sur un serveur… et ce n’est plus « juste un petit script ». En accompagnant des apprenants en Python, c’est le basculement que je vois revenir le plus souvent : ce jour-là, le script devient un outil qui peut casser, fuir une donnée ou agir au mauvais endroit.

Cette checklist sert à éviter ça. Elle ne transforme pas un script en application parfaite, elle aide simplement à poser les bonnes questions avant de lancer du Python dans un contexte réel.

À qui s’adresse cette checklist ?

Elle est utile si vous :

  • apprenez Python avec des projets pratiques,
  • automatisez des fichiers ou des rapports,
  • utilisez des API,
  • manipulez des données sensibles,
  • écrivez des scripts internes,
  • préparez une montée en compétence en cybersécurité,
  • voulez éviter les erreurs classiques avant de partager un script.

L’objectif n’est pas de faire peur, mais de faire mieux que « ça marche chez moi », que vous visiez un poste de développeur Python ou simplement des scripts plus propres au quotidien.

Un script qui fonctionne n’est pas forcément un script fiable

Un script peut fonctionner sur votre machine et rester dangereux. Quelques exemples :

  • une clé API écrite en clair dans le fichier,
  • un chemin de dossier mal configuré,
  • une suppression de fichiers sans confirmation,
  • des erreurs masquées,
  • des logs qui exposent des données,
  • une dépendance installée sans version,
  • un fichier de sortie qui écrase des données existantes.

La fiabilité commence quand on anticipe les erreurs, pas quand on espère qu’elles n’arriveront pas.

Le regard du formateur : chez les débutants, ce qui casse un script n’est presque jamais une faille sophistiquée. C’est une clé API laissée en clair, ou un script lancé directement sur les vrais fichiers, sans copie ni filet. Les points qui suivent visent d’abord ces erreurs simples, celles qui font le plus de dégâts.

La checklist rapide en 25 points

Checklist sécurité pour sécuriser un script Python

1. Le script a-t-il un objectif clair ?

Un bon script doit pouvoir être résumé en une phrase. Mauvais exemple :

Ce script traite des fichiers.

Meilleur exemple :

Ce script lit les fichiers CSV d’un dossier, supprime les lignes vides et génère un rapport de synthèse sans modifier les fichiers originaux.

Si vous ne pouvez pas expliquer clairement ce que fait le script, vous ne devriez pas encore l’utiliser sur de vraies données.

2. Les fichiers originaux sont-ils protégés ?

Avant de modifier ou déplacer des fichiers, posez-vous une question :

Est-ce que je peux revenir en arrière ?

Bonnes pratiques :

  • travailler sur une copie,
  • créer un dossier de sortie séparé,
  • ne jamais modifier l’original au premier passage,
  • ajouter un mode simulation,
  • sauvegarder la liste des actions réalisées (important au delà du script pur, car aussi utile au niveau des commandes entrées dans le système).

3. Le script possède-t-il un mode dry-run ?

Un mode dry-run permet d’afficher ce que le script ferait, sans le faire réellement. Exemple :

python nettoyage.py --dossier exports/ --dry-run

Le script indique alors :

[SIMULATION] 24 fichiers seraient analysés
[SIMULATION] 3 fichiers seraient déplacés
[SIMULATION] Aucun fichier n'a été modifié

C’est l’une des protections les plus simples et les plus utiles. Vous pouvez l’implémenter très facilement dans vos scripts en utilisant vos fonctions et en modifiant l’action concrète par un affiche lors du passage de la commande dry run.

4. Les chemins sont-ils contrôlés ?

Un chemin mal géré peut faire travailler le script au mauvais endroit. Voici les points à vérifier :

  • le dossier existe bien,
  • le script ne pointe pas vers la racine du système,
  • les chemins sont affichés avant action,
  • les chemins relatifs sont compris,
  • l’utilisateur confirme les actions sensibles.

Utilisez des outils comme pathlib pour manipuler les chemins plus proprement.

5. Les secrets sont-ils absents du code ?

Ne mettez jamais directement dans le script : clé API, mot de passe, token, identifiant de service, secret de webhook, chaîne de connexion sensible. Mauvais exemple :

API_KEY = "sk-1234654feg64gfe"

Meilleur principe :

  • utiliser une variable d’environnement,
  • charger un fichier .env non versionné,
  • utiliser un coffre de secrets si le contexte le justifie,
  • vérifier que .env est dans .gitignore.

6. Le fichier .gitignore est-il présent ?

Si le projet est versionné, ajoutez au minimum :

.env
.venv/
__pycache__/
*.log
*.sqlite3
exports/
output/

Le but est d’éviter d’envoyer par erreur des secrets, des fichiers générés, des logs ou des données sensibles dans un dépôt.

7. Les dépendances sont-elles isolées ?

Utilisez un environnement virtuel. Exemple :

python -m venv .venv

Puis activez-le et installez les packages nécessaires. Un projet Python sérieux ne doit pas dépendre d’un environnement global bricolé au fil du temps.

8. Les dépendances sont-elles listées ?

Créez un fichier requirements.txt. Exemple :

requests==2.32.3
python-dotenv==1.0.1

Versionner les dépendances aide à relancer le projet plus tard et réduit les surprises.

9. Les erreurs sont-elles visibles ?

Ne masquez pas toutes les erreurs avec un except trop large. Mauvais exemple :

try:
    lancer_traitement()
except:
    pass

Ce code enterre les problèmes. Meilleur exemple :

try:
    lancer_traitement()
except FileNotFoundError as erreur:
    print(f"Fichier introuvable : {erreur}")
except PermissionError as erreur:
    print(f"Permission refusée : {erreur}")

Un script fiable doit échouer clairement.

10. Les logs exposent-ils des données sensibles ?

Les logs sont utiles, mais dangereux s’ils affichent tout. À éviter dans les logs : mots de passe, tokens, clés API, données personnelles, contenus confidentiels, fichiers sensibles complets. Préférez des messages comme :

24 lignes traitées, 2 erreurs détectées

plutôt que :

[...] Token utilisé : sk-1315677rehh

11. Les entrées utilisateur sont-elles validées ?

Si le script demande une valeur à l’utilisateur, vérifiez-la. Exemples :

  • le dossier existe,
  • le fichier a la bonne extension,
  • la valeur numérique est dans une plage acceptable,
  • l’URL commence bien par https:// si nécessaire.

Ne faites pas confiance à une entrée simplement parce qu’elle vient d’un collègue ou de vous-même.

12. Le script écrase-t-il des fichiers ?

Avant d’écrire un fichier de sortie, vérifiez s’il existe déjà. Stratégies possibles :

  • refuser d’écraser,
  • ajouter un suffixe,
  • demander confirmation,
  • créer un dossier daté,
  • sauvegarder l’ancien fichier.

13. Le script a-t-il un journal d’actions ?

Pour un script qui modifie ou déplace des fichiers, gardez une trace : fichier traité, action réalisée, destination, date, erreur éventuelle. C’est utile pour comprendre ce qui s’est passé si un résultat semble étrange.

14. Le script limite-t-il son périmètre ?

Un script doit agir seulement sur ce qui est nécessaire. À éviter :

  • scanner tout le disque,
  • modifier tous les fichiers d’un dossier sans filtre,
  • envoyer toutes les données à une API,
  • donner trop de droits au script.

Le principe est simple : moins le script peut faire de dégâts, mieux c’est.

15. Les appels API sont-ils contrôlés ?

Si le script appelle une API, vérifiez :

  • timeout défini,
  • gestion des erreurs HTTP,
  • limitation du nombre de requêtes,
  • absence de secrets dans l’URL,
  • stockage minimal des réponses,
  • validation du contenu reçu.

Un appel API qui fonctionne une fois peut échouer demain. Prévoyez l’échec.

16. Les données envoyées à un service externe sont-elles nécessaires ?

Avant d’envoyer un texte, un fichier ou une donnée à une API, demandez :

Est-ce que cette donnée doit vraiment sortir de mon environnement ?

Si non, ne l’envoyez pas. Si oui, minimisez :

  • envoyez moins de champs,
  • masquez les identifiants,
  • supprimez les données sensibles,
  • conservez seulement ce qui est nécessaire.

17. Le script est-il documenté ?

Un fichier README.md simple suffit souvent. Il doit indiquer : ce que fait le script, comment l’installer, comment le lancer, les paramètres disponibles, les fichiers modifiés, les limites connues. Un script non documenté devient vite inutilisable, même par son auteur.

18. Le script est-il testable sur de fausses données ?

Créez un dossier tests_fichiers ou exemples avec de petites données sans risque. Un bon script doit pouvoir être testé sans toucher aux vrais fichiers.

19. Les actions dangereuses demandent-elles confirmation ?

Pour toute action irréversible ou sensible, demandez confirmation : suppression, déplacement massif, écrasement, envoi externe, publication, modification de données. Une confirmation humaine ne règle pas tout, mais elle évite beaucoup d’accidents.

20. Le script respecte-t-il le principe du moindre privilège ?

N’exécutez pas un script avec plus de droits que nécessaire. Si un script peut fonctionner sans compte administrateur, ne le lancez pas en administrateur. Si une clé API peut être limitée en lecture seule, ne lui donnez pas un accès complet.

21. Le script affiche-t-il un résumé final ?

À la fin, affichez : le nombre d’éléments traités, le nombre de succès, le nombre d’erreurs, l’emplacement des fichiers générés, les éventuelles actions ignorées. Un script qui se termine en silence est moins pratique à contrôler.

22. Le code est-il assez lisible pour être relu ?

Si vous ne comprenez plus votre script deux semaines plus tard, il est trop fragile. À améliorer : des noms de variables clairs, des fonctions courtes, des commentaires utiles, la suppression du code mort, un découpage logique.

23. Le script contient-il des valeurs codées en dur ?

Évitez de disperser partout des chemins, des URLs, des noms de fichiers, des seuils ou des paramètres. Regroupez-les en haut du fichier ou dans un fichier de configuration.

24. Le script a-t-il été relu avec un scénario d’échec ?

Demandez-vous : que se passe-t-il si le dossier est vide ? Si le fichier n’existe pas ? Si l’API ne répond pas ? Si la connexion coupe ? Si un fichier existe déjà ? Si une valeur est mal formée ? Un script fiable n’est pas celui qui marche quand tout va bien. C’est celui qui réagit proprement quand quelque chose se passe mal.

25. Le script est-il prêt à être partagé ?

Avant de l’envoyer à quelqu’un : retirez les secrets, ajoutez un README, ajoutez des exemples, précisez les limites, testez sur un environnement propre, vérifiez les dépendances, ajoutez un mode dry-run si besoin.


Mini-lab : ajouter un mode dry-run à un script Python

Voici un exemple simple de script qui affiche ce qu’il ferait avant d’agir.

Objectif

Créer un script qui liste les fichiers .txt d’un dossier. En mode normal, il les déplacerait dans un dossier Textes. En mode dry-run, il affiche seulement l’action prévue.

Code exemple

from pathlib import Path
import argparse
import shutil

def organiser_textes(dossier_source, dry_run=False):
    dossier_source = Path(dossier_source)
    dossier_destination = dossier_source / "Textes"

    if not dossier_source.exists():
        print("Le dossier source n'existe pas.")
        return

    fichiers_txt = list(dossier_source.glob("*.txt"))

    if not fichiers_txt:
        print("Aucun fichier .txt trouvé.")
        return

    if not dry_run:
        dossier_destination.mkdir(exist_ok=True)

    for fichier in fichiers_txt:
        destination = dossier_destination / fichier.name
        if dry_run:
            print(f"[SIMULATION] {fichier} serait déplacé vers {destination}")
        else:
            shutil.move(str(fichier), str(destination))
            print(f"[OK] {fichier} déplacé vers {destination}")

    print(f"Traitement terminé : {len(fichiers_txt)} fichier(s) concerné(s).")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Organise les fichiers texte d'un dossier.")
    parser.add_argument("dossier", help="Dossier à analyser")
    parser.add_argument("--dry-run", action="store_true", help="Affiche les actions sans les exécuter")
    args = parser.parse_args()
    organiser_textes(args.dossier, args.dry_run)

Lancer en simulation

python organiser_textes.py exemples/ --dry-run

Lancer réellement

python organiser_textes.py exemples/

Pourquoi ce mini-lab est important

Le mode dry-run oblige à penser avant d’agir. C’est une excellente habitude pour tous les scripts qui déplacent des fichiers, suppriment des éléments, écrivent dans un dossier, appellent une API ou modifient des données. Un débutant qui prend cette habitude tôt s’évite beaucoup d’ennuis plus tard. 🙂


Kit téléchargeable : checklist sécurité Python

Vous pouvez copier ce bloc dans un fichier checklist-securite-script-python.md :

# Checklist sécurité pour script Python

## Objectif du script
- [ ] Le script peut être résumé en une phrase claire.
- [ ] Les fichiers ou données modifiés sont identifiés.
- [ ] Les limites du script sont écrites.

## Données et fichiers
- [ ] Le script travaille sur une copie ou un dossier de test.
- [ ] Les fichiers originaux ne sont pas modifiés au premier passage.
- [ ] Un mode dry-run est disponible pour les actions sensibles.
- [ ] Les fichiers de sortie n'écrasent pas silencieusement des fichiers existants.
- [ ] Un journal d'actions est créé si le script modifie des fichiers.

## Secrets et configuration
- [ ] Aucune clé API n'est écrite dans le code.
- [ ] Les secrets sont chargés depuis l'environnement ou un coffre adapté.
- [ ] Le fichier .env est absent du dépôt.
- [ ] Le .gitignore exclut .env, .venv, logs et fichiers générés.

## Dépendances
- [ ] Le projet utilise un environnement virtuel.
- [ ] Les dépendances sont listées dans requirements.txt.
- [ ] Les versions importantes sont fixées.
- [ ] Les packages inutiles sont supprimés.

## Erreurs et logs
- [ ] Les erreurs ne sont pas masquées par un except trop large.
- [ ] Les messages d'erreur sont compréhensibles.
- [ ] Les logs n'affichent pas de secrets ou de données sensibles.
- [ ] Le script affiche un résumé final.

## API et services externes
- [ ] Les appels API ont un timeout.
- [ ] Les erreurs HTTP sont gérées.
- [ ] Les données envoyées sont minimisées.
- [ ] Les réponses externes sont validées avant usage.

## Sécurité d'exécution
- [ ] Le script n'est pas lancé avec plus de droits que nécessaire.
- [ ] Les actions dangereuses demandent confirmation.
- [ ] Le périmètre d'action est limité.
- [ ] Le script a été testé sur de fausses données.

## Documentation
- [ ] Un README explique l'installation.
- [ ] Un exemple d'utilisation est fourni.
- [ ] Les paramètres sont documentés.
- [ ] Les limites connues sont indiquées.

Vous voulez écrire du Python fiable et sécurisé ?

De la gestion des secrets au principe du moindre privilège, ces réflexes sont au cœur de notre formation Python, accessible aux débutants et finançable. On apprend à sécuriser pour de vrai, pas juste à faire « marcher ».

Questions fréquentes

Comment sécuriser un script Python ?

On ne cherche pas la perfection, on anticipe ce qui peut mal tourner : travailler sur une copie, prévoir un mode dry-run, sortir les secrets (clés API) du code vers une variable d’environnement ou un fichier .env non versionné, isoler les dépendances dans un environnement virtuel, rendre les erreurs visibles plutôt que de les masquer, et limiter les droits du script au strict nécessaire.

Qu’est-ce qu’un mode dry-run et pourquoi l’utiliser ?

C’est un mode qui affiche ce que le script ferait, sans le faire réellement. C’est l’une des protections les plus simples et les plus utiles pour tout script qui déplace, supprime ou écrase des fichiers, ou qui appelle une API.

Où stocker une clé API dans un script Python ?

Jamais en clair dans le code. On la charge depuis une variable d’environnement ou un fichier .env non versionné (ajouté au .gitignore), ou depuis un coffre de secrets si le contexte le justifie.

Faut-il un environnement virtuel pour un simple script ?

Dès que le script a des dépendances, oui. Un venv isole les packages du système, et un requirements.txt avec des versions fixées permet de relancer le projet plus tard sans surprise.

Un script qui fonctionne est-il forcément sécurisé ?

Pas forcément. Un script peut tourner parfaitement sur votre machine et rester dangereux : clé API en clair, suppression sans confirmation, erreurs masquées, fichier de sortie qui en écrase un autre. La fiabilité commence quand on anticipe les erreurs, pas quand on espère qu’elles n’arriveront pas.

Comment gérer les erreurs proprement en Python ?

Évitez l’except trop large qui enterre les problèmes. Capturez des exceptions précises (FileNotFoundError, PermissionError…) avec des messages clairs. Un script fiable doit échouer clairement, pas en silence.

Sur le même thème