10 Tests, sécurité et qualité du code
Bugs, sécurité et performance
10.7 Détection de bugs avec Copilot 🐛
Définition
Copilot peut aider à identifier des bugs dans :
- fonctions ;
- services ;
- tests ;
- endpoints ;
- scripts ;
- configurations ;
- logique métier ;
- gestion d’erreur.
Exemple bug Python
Code volontairement bugué :
def add_item(item, items=[]):
items.append(item)
return itemsPrompt :
Review this function for bugs and explain the issue.Copilot devrait signaler :
L’argument par défaut mutable [] est partagé entre les appels.
Correction :
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return itemsTest :
def test_add_item_does_not_share_default_list():
first = add_item("a")
second = add_item("b")
assert first == ["a"]
assert second == ["b"]Ce test échoue avec la version bugguée : les deux appels partagent la même liste, donc first vaut aussi ["a", "b"]. Il réussit avec la version corrigée. C’est un test de régression : il échoue avant la correction et réussit après.
Exemple bug JavaScript
Code volontairement bugué :
function isAdult(age) {
return age > 18;
}Prompt :
Review this function for boundary issues.Copilot peut signaler :
Si l’âge légal adulte est 18, la condition devrait probablement être age >= 18.
C’est une hypothèse à confirmer avec la règle métier : Copilot ne sait pas quel âge ton produit retient.
Correction :
function isAdult(age) {
return age >= 18;
}Test :
expect(isAdult(18)).toBe(true);Exemple bug API
Code volontairement incomplet :
app.get("/users/:id", async (req, res) => {
const user = await userService.findById(req.params.id);
res.json(user);
});Problèmes possibles :
- pas de gestion not found ;
- pas de validation de l’ID ;
- pas de gestion d’erreur ;
- pas d’autorisation ;
- risque d’exposition de champs sensibles.
Prompt :
Review this route for correctness, security, and missing error handling.
Suggest minimal fixes and tests.Bon prompt bug detection
Analyze the selected code for bugs.
Focus on:
- boundary conditions
- null or undefined values
- error handling
- async behavior
- incorrect assumptions
- security-sensitive logic
Return:
- bug
- why it happens
- minimal fix
- test to prevent regressionPiège d’examen
Une explication de bug donnée par Copilot est une hypothèse, pas une preuve. Elle se confirme avec un test qui échoue avant la correction et réussit après, et avec la règle métier. Une explication assurée peut être fausse.
À retenir
Copilot est utile pour trouver des bugs probables, mais il faut confirmer avec des tests et une compréhension métier.
10.8 Suggestions de sécurité 🔐
Définition
Copilot peut aider à identifier et corriger des problèmes de sécurité dans le code.
Exemples :
- injection SQL ;
- XSS ;
- auth manquante ;
- autorisation manquante ;
- secrets hardcodés ;
- logs sensibles ;
- permissions trop larges ;
- validation insuffisante ;
- mauvaise gestion d’erreur ;
- dépendances obsolètes ;
- hashing faible.
Pour le GH-300
Les exemples de cette section sont volontairement vulnérables. Ils ne servent pas à apprendre une attaque : le GH-300 ne te demande pas de connaître une faille par cœur. Il te demande comment utiliser Copilot pour repérer le problème, demander une alternative plus sûre, générer un test de sécurité et valider la correction proposée.
Exemple SQL injection
Code dangereux :
query = f"SELECT * FROM users WHERE email = '{email}'"Prompt :
Review this database query for security issues and propose a safer implementation.Correction :
cursor.execute(
"SELECT * FROM users WHERE email = %s",
(email,)
)Exemple authorization manquante
Code volontairement non sécurisé :
app.get("/admin/users", async (req, res) => {
const users = await userService.getAllUsers();
res.json(users);
});Prompt :
Review this Express route for authentication and authorization issues.Copilot devrait signaler :
La route expose probablement tous les utilisateurs sans vérifier que le requester est admin.Correction conceptuelle :
app.get("/admin/users", authenticate, requireRole("admin"), async (req, res) => {
const users = await userService.getAllUsers();
res.json(users);
});Exemple secrets
Mauvais code :
const apiKey = "prod_123456789";Prompt :
Review this code for secret management issues.Correction :
const apiKey = process.env.API_KEY;
if (!apiKey) {
throw new Error("API_KEY is required");
}Si la clé a déjà été poussée dans un dépôt partagé, la retirer du code ne suffit pas : elle doit être renouvelée.
Exemple logs sensibles
Code volontairement non sécurisé :
logger.info("User login failed", {
email,
password
});Correction :
logger.info("User login failed", {
email
});Ne jamais logger :
- mots de passe ;
- tokens ;
- clés API ;
- secrets ;
- données personnelles sensibles.
Bon prompt sécurité
Review the selected code for security issues.
Focus on:
- authentication
- authorization
- input validation
- injection
- secrets
- sensitive logging
- error messages
- least privilege
Return:
- issue
- severity
- explanation
- recommended fix
- test to prevent regressionValider la correction proposée
Une correction de sécurité proposée par Copilot se valide comme n’importe quelle suggestion :
- relire la modification (le diff) et comprendre ce qui change ;
- relancer les tests existants et ajouter un test de non-régression sécurité ;
- vérifier que le comportement attendu est préservé ;
- laisser les outils du dépôt confirmer (analyse statique, détection de secrets, analyse des dépendances) ;
- demander une relecture humaine pour les zones sensibles.
Piège d’examen
Copilot peut aider, mais il ne remplace pas :
- SAST ;
- secret scanning ;
- dependency scanning ;
- pentest ;
- threat modeling ;
- review sécurité ;
- règles internes.
À retenir
Copilot peut proposer des améliorations sécurité, mais les décisions sécurité doivent être validées avec des outils et humains compétents.
10.9 Optimisations de performance ⚡
Définition
L’optimisation de performance consiste à améliorer :
- temps de réponse ;
- consommation CPU ;
- mémoire ;
- appels réseau ;
- requêtes DB ;
- temps de build ;
- complexité algorithmique ;
- coût cloud.
Copilot peut aider à identifier des opportunités, mais il faut mesurer avant/après.
Exemple simple
Code :
def find_user(users, email):
for user in users:
if user["email"] == email:
return user
return NoneSi cette recherche est faite souvent sur une grande liste, Copilot peut proposer un index :
def build_user_index(users):
return {user["email"]: user for user in users}
def find_user(user_index, email):
return user_index.get(email)Mais ce n’est utile que si :
- la liste est grande ;
- les recherches sont fréquentes ;
- le coût mémoire est acceptable ;
- les données ne changent pas trop souvent.
Exemple DB
Code conceptuel :
const users = await userRepository.findAll();
for (const user of users) {
user.orders = await orderRepository.findByUserId(user.id);
}Problème probable :
N+1 queriesPrompt :
Review this code for performance issues.
Focus on database query patterns and suggest a safer optimization.Copilot peut proposer :
Fetch orders for all users in a single query and group them by userId.Exemple amélioration :
const users = await userRepository.findAll();
const userIds = users.map(user => user.id);
const orders = await orderRepository.findByUserIds(userIds);
const ordersByUserId = groupBy(orders, order => order.userId);
return users.map(user => ({
...user,
orders: ordersByUserId[user.id] ?? []
}));Prompt performance
Analyze this code for performance issues.
Focus on:
- algorithmic complexity
- repeated database queries
- unnecessary network calls
- memory usage
- caching opportunities
- trade-offs
Suggest optimizations and explain risks.
Do not change behavior.Piège d’examen
Optimiser sans mesurer est un piège classique : Copilot peut proposer une optimisation plausible sans garantir qu’elle améliore quoi que ce soit.
Mauvais réflexe :
Optimize everything.Meilleur réflexe :
Identify likely bottlenecks and suggest measurable optimizations.Bonnes pratiques
Toujours :
- mesurer avant/après (Copilot peut aider à proposer un test de performance ou une mesure) ;
- préserver le comportement ;
- ajouter des tests ;
- vérifier les effets de bord ;
- éviter le cache dangereux ;
- surveiller la cohérence des données.
À retenir
Copilot peut suggérer des optimisations, mais les performances doivent être mesurées.
10.10 Cas d’examen : tester, sécuriser ou refactorer ? 🧪🔐🛠️
Cette section est très importante.
L’examen peut présenter une situation et demander la meilleure action.
Tableau de décision rapide
| Situation | Meilleure action |
|---|---|
| Fonction isolée sans tests | Générer des tests unitaires |
| Endpoint complet à vérifier | Générer des tests d’intégration |
| Comportement aux limites inconnu | Identifier edge cases |
| Tests trop faibles | Améliorer les assertions |
| Dépendance externe lente ou coûteuse | Utiliser mocks/stubs |
| Couverture faible | Ajouter tests pour branches manquantes |
| Bug récurrent | Générer test de régression + correction |
| Route sans auth | Sécuriser avant refactor |
| Code vulnérable SQL injection | Corriger sécurité immédiatement |
| Code illisible mais fonctionnel | Refactorer avec tests |
| Code legacy critique sans tests | Comprendre + ajouter tests avant refactor |
| Performance suspecte | Identifier bottleneck + mesurer |
Cas 1 — Fonction sans tests
Scénario :
Une fonction critique calcule les remises, mais aucun test n’existe.
Bonne réponse :
Utiliser Copilot pour générer des tests unitaires couvrant cas normaux, limites et erreurs.Cas 2 — API avec dépendances
Scénario :
Une API crée un utilisateur via controller, service et repository.
Bonne réponse :
Utiliser Copilot pour générer des tests d’intégration.Cas 3 — Service externe
Scénario :
Un service appelle une API de paiement externe.
Bonne réponse :
Utiliser des mocks pour simuler succès, refus, timeout et erreur réseau.Cas 4 — Bug de production
Scénario :
Un bug se produit quand la liste d’items est vide.
Bonne réponse :
Demander à Copilot de créer un test de régression pour ce cas, puis corriger le bug.Cas 5 — SQL injection
Scénario :
Copilot détecte une requête SQL construite par concaténation de string.
Bonne réponse :
Corriger avec des requêtes paramétrées et ajouter un test sécurité si possible.Cas 6 — Code legacy critique
Scénario :
Une équipe veut refactorer un vieux module de paiement sans tests.
Bonne réponse :
Les tests d’abord : des tests de caractérisation avant tout refactoring, comme en 9.6.Cas 7 — Performance
Scénario :
Une page est lente à cause de nombreuses requêtes DB répétées.
Bonne réponse :
Demander à Copilot d’identifier les patterns N+1, proposer une optimisation mesurable, puis tester et mesurer.À retenir pour le GH-300
- Une explication de bug ou une optimisation proposée par Copilot est une hypothèse : on la confirme par un test de régression ou par une mesure avant et après.
- Pour la sécurité, on demande une alternative plus sûre et un test, puis on valide la correction (diff, tests, outils, relecture) : Copilot ne remplace ni les outils ni la review.
- Avant de refactorer du code vulnérable ou une route non protégée, on le sécurise d’abord.
- Une optimisation est un compromis : Copilot ne garantit aucun gain, on préserve le comportement et on mesure.
Pratique : Que faire de ce code généré ?
Chaque exemple montre du code généré par Copilot, volontairement risqué, bugué ou lent. Choisis la meilleure suite : ce qu’on demande à Copilot et ce qu’on vérifie ensuite. Il ne s’agit pas de nommer la faille, et aucun code n’est exécuté.
Chargement de la question…
Questions de la leçon
Chargement de la question…
Pour finir
À retenir
- Une explication de bug ou une optimisation proposée par Copilot est une hypothèse : on la confirme par un test de régression ou par une mesure avant et après.
- Pour la sécurité, on demande une alternative plus sûre et un test, puis on valide la correction (diff, tests, outils, relecture) : Copilot ne remplace ni les outils ni la review.
- Avant de refactorer du code vulnérable ou une route non protégée, on le sécurise d’abord.
- Une optimisation est un compromis : Copilot ne garantit aucun gain, on préserve le comportement et on mesure.
Objectif GH-300
- Sécurité et performance (Suggest security improvements and performance optimizations)
Achèvement
Il reste à faire : , .