Exercice 04 : Capstone - Sécuriser un projet de A à Z
🎯 Objectifs
À la fin de cet exercice, vous serez capable de :
- ✅ Partir d'un projet non sécurisé et appliquer les 4 protections de base
- ✅ Créer un
.gitignorecomplet et un.env.exampledocumenté - ✅ Scanner l'historique avec Gitleaks avant tout premier push
- ✅ Auditer les dépendances et corriger les vulnérabilités critiques
- ✅ Activer Dependabot pour les alertes de sécurité automatiques
Durée estimée : 45 minutes
Difficulté : ⭐⭐☆☆☆ (Intermédiaire)
Prérequis : Exercices 01, 02, 03 complétés - Compte GitHub disponible
📖 Contexte
Vous venez de rejoindre une startup. On vous demande de "sécuriser" un projet Node.js existant avant son premier déploiement. Le code fonctionne, mais personne n'a pensé à la sécurité lors du développement. Votre mission : appliquer les fondamentaux en moins d'une heure.
📋 Énoncé
Sécurisez le projet de démonstration fourni en appliquant les 4 couches de protection de base : secrets, git, dépendances, et alertes automatiques.
🧭 Déroulement de l'exercice
Tâche 1 : Créer le projet non sécurisé
Commencez par créer un projet "tel qu'on le trouve souvent" :
mkdir capstone-securite-debutant && cd capstone-securite-debutant
git init
# package.json
cat > package.json << 'EOF'
{
"name": "mon-app",
"version": "1.0.0",
"dependencies": {
"express": "4.17.1",
"jsonwebtoken": "8.0.0",
"mongoose": "5.9.0"
}
}
EOF
# Code avec secrets hardcodés (mauvaise pratique initiale)
cat > server.js << 'EOF'
const express = require('express');
const app = express();
// PROBLÈME : secrets hardcodés
const DB_PASSWORD = "admin123";
const JWT_SECRET = "secret";
const STRIPE_KEY = "sk_live_hardcoded_key_abc123";
app.get('/', (req, res) => {
res.json({ message: 'API démarrée' });
});
app.listen(3000);
EOF
# Premier commit avec secrets (simuler l'historique problématique)
git add .
git commit -m "init: première version de l'app"Tâche 2 : Audit de l'existant
Avant de corriger, évaluez l'état de sécurité actuel :
# 1. Scanner l'historique pour les secrets
gitleaks detect --source . --verbose
# 2. Installer et auditer les dépendances
npm install
npm auditNotez combien de secrets et de vulnérabilités sont détectés.
Attendu : Gitleaks doit détecter le
STRIPE_KEYet potentiellement leJWT_SECRET. npm audit doit trouver des CVE dans les versions old-school.
Tâche 3 : Corriger les secrets dans le code
Refactorisez server.js pour utiliser les variables d'environnement :
cat > server.js << 'EOF'
const express = require('express');
const app = express();
// BONNE PRATIQUE : lire depuis l'environnement
const DB_PASSWORD = process.env.DB_PASSWORD;
const JWT_SECRET = process.env.JWT_SECRET;
const STRIPE_KEY = process.env.STRIPE_API_KEY;
if (!DB_PASSWORD || !JWT_SECRET || !STRIPE_KEY) {
console.error('ERREUR : variables d\'environnement manquantes');
process.exit(1);
}
app.get('/', (req, res) => {
res.json({ message: 'API démarrée' });
});
app.listen(3000, () => console.log('Serveur démarré'));
EOFTâche 4 : Mettre en place les 3 fichiers de protection
# Fichier .env (non commité)
cat > .env << 'EOF'
DB_PASSWORD=MonMotDePasseLocal123
JWT_SECRET=$(openssl rand -hex 32)
STRIPE_API_KEY=sk_test_VOTRE_CLE_TEST
EOF
# Fichier .env.example (commité)
cat > .env.example << 'EOF'
# Copiez en .env et remplissez vos valeurs
# cp .env.example .env
# Base de données
DB_PASSWORD=MOT_DE_PASSE_BD
# JWT (générer : openssl rand -hex 32)
JWT_SECRET=CHAINE_ALEATOIRE_64_CARACTERES
# Stripe (récupérer sur https://dashboard.stripe.com)
STRIPE_API_KEY=sk_test_VOTRE_CLE
EOF
# Fichier .gitignore
cat > .gitignore << 'EOF'
# Secrets
.env
.env.local
.env.*.local
# Certificats et clés
*.key
*.pem
# Node.js
node_modules/
npm-debug.log*
# Système
.DS_Store
Thumbs.db
EOFTâche 5 : Corriger les dépendances et commiter proprement
# Corriger les dépendances
npm audit fix
# Vérifier que Gitleaks valide le nouveau commit
git add server.js .gitignore .env.example package.json package-lock.json
gitleaks protect --staged --verbose
# Commiter
git commit -m "security: refactoring secrets + deps audit fix"Vérification importante : Gitleaks
protect --stagedanalyse uniquement les fichiers dans la zone de staging (contrairement àdetectqui analyse tout l'historique). Il doit passer sans erreur.
Tâche 6 : Activer Dependabot sur GitHub
Créez le fichier de configuration Dependabot :
mkdir -p .github
cat > .github/dependabot.yml << 'EOF'
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "08:00"
open-pull-requests-limit: 5
labels:
- "security"
- "dependencies"
EOF
git add .github/dependabot.yml
git commit -m "ci: activer Dependabot pour les mises à jour de sécurité"Si vous pushez vers GitHub, Dependabot créera automatiquement des PRs chaque semaine pour les dépendances avec des mises à jour de sécurité disponibles.
✅ Vérification du résultat
gitleaks detectidentifie les secrets dans l'historique initialserver.jsne contient plus aucune valeur hardcodée.envexiste localement mais est dans.gitignore.env.exampleest commité avec des placeholdersnpm auditaffiche 0 vulnérabilités critiques/high.github/dependabot.ymlest configurégitleaks protect --stagedpasse sans alerte sur le dernier commit
💡 À retenir
La sécurité de base d'un projet Node.js se résume à 4 actions :
1. git commit → gitleaks protect (hook pre-commit)
2. npm install → npm audit (en CI)
3. .env → jamais commité
4. GitHub → Dependabot activéCes 4 actions ensemble réduisent drastiquement la surface d'attaque sans ralentir le développement.
✨ Solution Complète
# Protection des secrets
echo ".env" >> .gitignore
cp .env .env.example && sed -i 's/=.*/=PLACEHOLDER/' .env.example
# Audit dépendances
npm audit fix
# Gitleaks hook
echo '#!/bin/sh\ngitleaks protect --staged || exit 1' > .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
# Dependabot
mkdir -p .github && cat > .github/dependabot.yml << 'EOF'
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule: {interval: "weekly"}
EOF