pre-commit intercepte vos commits et vérifie automatiquement le code avant qu’il n’atteigne le dépôt. Espaces en fin de ligne, fichiers YAML mal formés, secrets exposés : tout est détecté et souvent corrigé automatiquement. Ce guide couvre l’installation, la configuration et les hooks les plus utiles pour un workflow DevOps.
Le problème que pre-commit résout
Section intitulée « Le problème que pre-commit résout »Sans validation automatique, les problèmes de qualité s’accumulent :
- Espaces en fin de ligne qui polluent les diffs
- Fichiers YAML ou JSON mal formés qui cassent les pipelines
- Secrets (clés API, mots de passe) commités par erreur
- Code non formaté qui crée des conflits de merge
La détection manuelle est impossible à maintenir. Les revues de code perdent du temps sur des détails triviaux au lieu de se concentrer sur la logique.
pre-commit automatise ces vérifications :
| Sans pre-commit | Avec pre-commit |
|---|---|
| Secrets détectés en production | Bloqués au commit |
| YAML invalide → pipeline cassé | Validé avant push |
| Formatage incohérent entre devs | Uniformisé automatiquement |
| Revue de code sur des détails | Focus sur la logique métier |
Fonctionnement
Section intitulée « Fonctionnement »pre-commit utilise les hooks Git — des scripts exécutés automatiquement par Git à certains moments (pré-commit, pré-push, etc.).
Chaque hook est un outil indépendant (linter, formatteur, scanner) configuré dans un fichier .pre-commit-config.yaml.
Installation
Section intitulée « Installation »Version actuelle : 4.5.1 (février 2026)
pre-commit est écrit en Python. L’installation recommandée utilise pipx pour isoler les dépendances.
-
Installer pipx (si pas déjà fait)
Fenêtre de terminal # Ubuntu/Debiansudo apt install pipxpipx ensurepath# Ou avec pippip install --user pipxpipx ensurepath -
Installer pre-commit
Fenêtre de terminal pipx install pre-commitSortie attendue :
done! ✨ 🌟 ✨installed package pre-commit 4.5.1, installed using Python 3.12.3These apps are now globally available- pre-commit -
Vérifier l’installation
Fenêtre de terminal pre-commit --version# pre-commit 4.5.1
Configuration de base
Section intitulée « Configuration de base »Créer le fichier de configuration
Section intitulée « Créer le fichier de configuration »À la racine de votre projet Git, créez .pre-commit-config.yaml :
repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml - id: check-json - id: check-added-large-files args: ['--maxkb=500'] - id: check-merge-conflict - id: detect-private-keyChaque entrée définit :
- repo : URL du dépôt contenant les hooks
- rev : version (tag Git) à utiliser
- hooks : liste des hooks à activer, avec options facultatives
Activer les hooks
Section intitulée « Activer les hooks »pre-commit installSortie attendue :
pre-commit installed at .git/hooks/pre-commitÀ partir de maintenant, chaque git commit déclenche les vérifications.
Tester manuellement
Section intitulée « Tester manuellement »Pour exécuter les hooks sans commiter :
# Sur les fichiers modifiés (staging area)pre-commit run
# Sur tous les fichiers du dépôtpre-commit run --all-files
# Un hook spécifiquepre-commit run trailing-whitespace --all-filesHooks essentiels pour DevOps
Section intitulée « Hooks essentiels pour DevOps »Qualité des fichiers de config
Section intitulée « Qualité des fichiers de config »repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: - id: check-yaml args: ['--unsafe'] # Permet les tags YAML personnalisés (Ansible, K8s) - id: check-json - id: check-toml - id: check-xmlSécurité : détection de secrets
Section intitulée « Sécurité : détection de secrets »repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: - id: detect-private-key
- repo: https://github.com/gitleaks/gitleaks rev: v8.18.2 hooks: - id: gitleaksExemple de détection :
# Créer un fichier avec une clé privéeecho "-----BEGIN RSA PRIVATE KEY-----" > secret.pemgit add secret.pemgit commit -m "Add config"Sortie :
detect private key...................................................Failed- hook id: detect-private-key- exit code: 1
Private key found: secret.pemLe commit est bloqué — le secret ne rejoint jamais le dépôt.
Formatage Python
Section intitulée « Formatage Python »repos: - repo: https://github.com/psf/black rev: 24.4.2 hooks: - id: black
- repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.4.4 hooks: - id: ruff args: ['--fix']Black formate le code automatiquement. Ruff détecte et corrige les erreurs de style (remplace flake8, isort, et plus).
Linting YAML avancé (Ansible, K8s)
Section intitulée « Linting YAML avancé (Ansible, K8s) »repos: - repo: https://github.com/adrienverge/yamllint rev: v1.35.1 hooks: - id: yamllint args: ['-c', '.yamllint.yaml']Créez .yamllint.yaml pour personnaliser les règles :
extends: defaultrules: line-length: max: 120 truthy: check-keys: falseInfrastructure as Code
Section intitulée « Infrastructure as Code »repos: - repo: https://github.com/antonbabenko/pre-commit-terraform rev: v1.88.4 hooks: - id: terraform_fmt - id: terraform_validate - id: terraform_tflint
- repo: https://github.com/ansible/ansible-lint rev: v24.2.1 hooks: - id: ansible-lintDockerfile
Section intitulée « Dockerfile »repos: - repo: https://github.com/hadolint/hadolint rev: v2.12.0 hooks: - id: hadolintConfiguration complète recommandée
Section intitulée « Configuration complète recommandée »Voici une configuration DevOps complète :
repos: # Vérifications de base - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml args: ['--unsafe'] - id: check-json - id: check-added-large-files args: ['--maxkb=500'] - id: check-merge-conflict - id: detect-private-key - id: check-case-conflict - id: mixed-line-ending args: ['--fix=lf']
# Sécurité - repo: https://github.com/gitleaks/gitleaks rev: v8.18.2 hooks: - id: gitleaks
# YAML - repo: https://github.com/adrienverge/yamllint rev: v1.35.1 hooks: - id: yamllint
# Markdown - repo: https://github.com/igorshubovych/markdownlint-cli rev: v0.39.0 hooks: - id: markdownlint args: ['--fix']
# Shell - repo: https://github.com/shellcheck-py/shellcheck-py rev: v0.10.0.1 hooks: - id: shellcheckMaintenir les hooks à jour
Section intitulée « Maintenir les hooks à jour »Les hooks utilisent des versions fixes (rev:). Pour les mettre à jour :
pre-commit autoupdateSortie exemple :
[https://github.com/pre-commit/pre-commit-hooks] updating v5.0.0 -> v6.0.0[https://github.com/gitleaks/gitleaks] updating v8.18.2 -> v8.30.0Commitez ensuite le fichier .pre-commit-config.yaml mis à jour.
Intégration CI/CD
Section intitulée « Intégration CI/CD »Exécutez pre-commit dans votre pipeline pour détecter les commits qui auraient contourné les hooks locaux.
GitHub Actions
Section intitulée « GitHub Actions »name: pre-commit
on: push: pull_request:
jobs: pre-commit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: '3.12' - uses: pre-commit/action@v3.0.1GitLab CI
Section intitulée « GitLab CI »pre-commit: image: python:3.12 stage: lint before_script: - pip install pre-commit script: - pre-commit run --all-files --show-diff-on-failureOptions utiles pour CI
Section intitulée « Options utiles pour CI »| Option | Description |
|---|---|
--all-files | Vérifie tous les fichiers, pas seulement les modifiés |
--show-diff-on-failure | Affiche le diff si un hook modifie des fichiers |
--fail-fast | Arrête dès le premier échec |
Sécurité : pre-commit dans le référentiel LOTP
Section intitulée « Sécurité : pre-commit dans le référentiel LOTP »pre-commit est un outil de qualité de code, mais son mécanisme d’exécution en fait aussi un outil référencé dans LOTP (Living Off The Pipeline), la base de connaissances qui catalogue les fonctionnalités légitimes d’outils de pipeline exploitables à des fins malveillantes.
Le risque repose sur les hooks locaux (repo: local) avec
language: system. Ce type de hook exécute directement une commande shell
sur la machine — sans aucun sandboxing, sans isolation, avec les droits de
l’utilisateur courant (ou du runner CI/CD).
Ce mécanisme fonctionne parce que pre-commit run charge et exécute
automatiquement les hooks définis dans .pre-commit-config.yaml. Quand le
hook utilise language: system, pre-commit passe directement le champ
entry au shell système — c’est exactement le même mécanisme qu’un
Makefile ou un package.json avec des scripts lifecycle.
Scénarios d’exploitation
Section intitulée « Scénarios d’exploitation »L’attaque la plus courante est la Poisoned Pipeline Execution (PPE) :
- Un attaquant ouvre une PR qui modifie
.pre-commit-config.yaml - Le pipeline CI exécute
pre-commit run --all-filesaprès checkout du code de la PR - Le hook malveillant s’exécute et exfiltre les secrets (
GITHUB_TOKEN, clés API, credentials cloud)
Variante plus subtile : l’attaquant ajoute un hook légitime et un hook
malveillant dans la même PR. Le nom (name: lint check) paraît inoffensif
mais le champ entry contient du code malveillant.
Contre-mesures
Section intitulée « Contre-mesures »-
Protégez
.pre-commit-config.yamlavec CODEOWNERS pour qu’une revue soit obligatoire avant toute modification :# .github/CODEOWNERS.pre-commit-config.yaml @security-team -
Ne lancez pas
pre-commit runautomatiquement sur les PRs de forks. Vérifiez que.pre-commit-config.yamln’a pas été modifié avant d’exécuter les hooks en CI :Fenêtre de terminal # Vérifier si le fichier a changé dans la PRif git diff --name-only origin/main...HEAD | grep -q '.pre-commit-config.yaml'; thenecho "⚠️ .pre-commit-config.yaml modifié — revue manuelle requise"exit 1fi -
Évitez
language: systemdans vos propres hooks sauf nécessité documentée. Préférezlanguage: python,language: nodeoulanguage: dockerqui offrent une isolation minimale. -
Auditez régulièrement les hooks locaux et les dépôts référencés. Vérifiez que les
rev:pointent vers des tags signés de dépôts de confiance.
Commandes principales
Section intitulée « Commandes principales »| Commande | Description |
|---|---|
pre-commit install | Active les hooks dans le dépôt |
pre-commit run | Exécute sur les fichiers stagés |
pre-commit run --all-files | Exécute sur tout le dépôt |
pre-commit run <hook-id> | Exécute un hook spécifique |
pre-commit autoupdate | Met à jour les versions des hooks |
pre-commit clean | Supprime le cache des environnements |
pre-commit gc | Nettoie les repos non utilisés |
pre-commit uninstall | Désactive les hooks |
pre-commit validate-config | Valide la syntaxe du fichier config |
pre-commit try-repo <url> | Teste un hook sans l’installer |
Contourner temporairement
Section intitulée « Contourner temporairement »Dans de rares cas, vous pouvez avoir besoin de passer outre les hooks :
# Ignorer tous les hooksgit commit --no-verify -m "WIP: work in progress"
# Ignorer un hook spécifique (via variable d'environnement)SKIP=trailing-whitespace git commit -m "Keep trailing spaces"Stages de hooks
Section intitulée « Stages de hooks »Par défaut, les hooks s’exécutent au pre-commit. Vous pouvez configurer d’autres moments :
repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: - id: check-added-large-files stages: [pre-commit, pre-push]| Stage | Moment | Cas d’usage |
|---|---|---|
pre-commit | Avant le commit | Formatage, linting rapide |
pre-push | Avant le push | Tests longs, scans de sécurité |
commit-msg | Après saisie du message | Validation format commit |
post-checkout | Après checkout | Mise à jour dépendances |
Pour activer plusieurs stages :
pre-commit install --hook-type pre-commit --hook-type pre-pushDépannage
Section intitulée « Dépannage »| Symptôme | Cause | Solution |
|---|---|---|
| ”command not found: pre-commit” | pipx pas dans le PATH | pipx ensurepath puis relancer le shell |
| Hook très lent au premier run | Téléchargement des environnements | Normal, le cache accélère les runs suivants |
| Erreur “not a git repository” | Pas de dépôt Git | git init d’abord |
| Hook échoue en CI mais pas en local | Versions différentes | Utiliser pre-commit autoupdate |
| ”No .pre-commit-config.yaml” | Fichier absent | Créer le fichier à la racine |
À retenir
Section intitulée « À retenir »- pre-commit = garde-fou automatique — Vérifie le code avant qu’il n’atteigne le dépôt
- Installation :
pipx install pre-commitpuispre-commit installdans chaque projet - Configuration : fichier
.pre-commit-config.yamlà la racine - Mise à jour :
pre-commit autoupdatepour utiliser les dernières versions - CI/CD : ajouter
pre-commit run --all-filesdans le pipeline - Hooks essentiels : trailing-whitespace, check-yaml, detect-private-key, gitleaks
- Contournement :
git commit --no-verify(à éviter) - Les hooks locaux
language: systemsont référencés dans le référentiel LOTP : protégez.pre-commit-config.yamlvia CODEOWNERS et ne lancez paspre-commit runautomatiquement sur les PRs de forks.