Question 1Pourquoi valider aussi côté serveur, alors que les valeurs du formulaire sont déjà contrôlées à l'écran ?
Les points à surveiller en sécurité — ne pas faire confiance aux entrées, protéger les secrets
Cet article fait partie du cours Les bases de l'informatique, qui construit depuis zéro les connaissances informatiques pratiques indispensables pour programmer et faire du vibe coding.
Deux principes de base : ne pas faire confiance aux entrées de l'utilisateur, et protéger les informations secrètes. Des schémas montrent comment surviennent l'injection SQL et le XSS.
Cet article traite deux des points à surveiller en sécurité.
Le premier : ne pas utiliser tel quel le texte écrit par un utilisateur. Le second : ne pas placer de valeurs secrètes là où davantage de personnes peuvent les lire.
- Pourquoi la validation des entrées se fait côté serveur
- L'injection SQL, qui survient quand une entrée est concaténée à une instruction, et les placeholders
- Le XSS, évité par l'échappement juste avant l'affichage à l'écran
- Où tu peux conserver les informations secrètes comme les clés d'API et les mots de passe
Si l'un de ces problèmes survient une fois le site en ligne, on ne peut pas revenir en arrière : les données déjà lues sont irrécupérables.
« Il n'y a pas de validation des entrées » signifie qu'une valeur est utilisée telle qu'elle arrive
La validation des entrées (input validation) consiste à vérifier, avant de l'utiliser, qu'une valeur reçue respecte le format, la longueur et l'intervalle attendus.
Tu fixes une condition par champ : le nom jusqu'à 50 caractères, le nombre d'étoiles de 1 à 5.
| Valeur reçue | Condition fixée à l'avance | Ce que fait le serveur |
|---|---|---|
| Champ nom : Alice | Jusqu'à 50 caractères → conforme | Passe à l'enregistrement |
| Nombre d'étoiles : 7 | Un nombre de 1 à 5 → non conforme | Refusé et renvoyé sans enregistrement |
| Corps du message : laissé vide | Au moins un caractère → non conforme | Refusé et renvoyé sans enregistrement |
Seule la première ligne remplit la condition et passe à l'enregistrement ; les deux autres ne sont pas enregistrées et le serveur renvoie ce qui ne convient pas.
Le contrôle à l'écran est exécuté par le JavaScript (un programme qui tourne dans le navigateur) livré à l'appareil de l'utilisateur.
L'utilisateur peut le désactiver, et il peut aussi envoyer les données directement au serveur sans passer par un navigateur.
Le contrôle à l'écran sert à faire corriger la saisie, et seule la validation côté serveur décide si une valeur peut être utilisée.
Si tu enregistres sans validation, les valeurs non conformes restent telles quelles dans la base de données.
Des nombres d'étoiles en dehors de 1 à 5 faussent les moyennes et le tri, et des valeurs qui ne se lisent pas comme des nombres interrompent le calcul des totaux.
Corriger les valeurs déjà entrées suppose d'examiner les données restantes une par une.
Vérifie la valeur reçue sur le serveur avant de l'utiliser
La validation des entrées consiste à regarder, avant utilisation, si une valeur reçue remplit les conditions fixées.
Le contrôle à l'écran sert à faire corriger la saisie sur le moment et peut être désactivé avant l'envoi : tu vérifies donc la même chose une seconde fois côté serveur.
Concaténé à une instruction, le texte saisi s'exécute comme une instruction
Pour retrouver par nom les avis enregistrés, le serveur assemble une instruction en SQL (Structured Query Language, le langage qui transmet les instructions à une base de données).
Quand le texte saisi est concaténé à cette chaîne, l'ensemble est transmis comme une seule chaîne.
- SELECT * FROM reviews WHERE name =
- Une instruction qui extrait de la table reviews les lignes dont le name correspond
- Cette forme est écrite à l'avance dans le code
- Alice — un nom ordinaire
- ' OR '1'='1 — du texte contenant des symboles
- Le texte saisi vient se placer tel quel à cet endroit
Une fois transmises, la partie écrite par le développeur et celle venue du champ nom font partie d'une seule et même chaîne.
La base de données lit la chaîne qu'elle reçoit comme une instruction, dans son intégralité.
| Texte saisi dans le champ nom | Instruction produite par la concaténation | Ce que renvoie la base de données |
|---|---|---|
| Alice | name = 'Alice' | Uniquement les avis d'Alice |
| Alice' | name = 'Alice'' | L'instruction est mal formée et provoque une erreur |
| ' OR '1'='1 | name = '' OR '1'='1' | Tous les avis |
Le fait qu'un texte saisi soit exécuté comme une instruction au lieu d'être traité comme une valeur est une injection, et celle qui survient dans une base de données est une injection SQL (SQL injection).
L'écriture qui l'empêche est le placeholder : dans l'instruction, un symbole marque seulement l'emplacement de la valeur, et la valeur est transmise séparément.
Quand ils sont transmis séparément, la base de données ne lit pas la valeur comme une instruction : elle cherche ce texte comme un nom et ne trouve aucun résultat.
La validation vérifie le format d'une valeur, tandis que le placeholder fait traiter l'entrée comme une valeur, quel que soit son format.
Les rôles sont différents, donc tu fais les deux.
Ne pas réunir l'instruction et le texte saisi en une seule chaîne
Quand un texte saisi est concaténé à une instruction, même les symboles saisis sont lus comme une partie de l'instruction.
Transmettre l'instruction et la valeur séparément fait qu'un texte contenant des symboles est traité comme un simple nom ; tu gardes donc les deux : la validation qui vérifie le format, et l'écriture qui fait traiter la valeur comme une valeur quel que soit son format.
Sans transformation juste avant l'affichage, une publication s'exécute dans le navigateur d'un autre utilisateur
La même chose se produit à l'endroit où une publication est affichée à l'écran.
Le fait qu'un texte saisi s'exécute comme du JavaScript dans le navigateur d'un autre utilisateur est le XSS (Cross-Site Scripting).
Dans les deux cas, l'entrée est lue comme une instruction ; seul ce qui la lit change.
Le remède du côté de l'affichage est l'échappement (escape), c'est-à-dire la conversion des caractères qui ont un sens particulier en une forme qui s'affiche comme de simples caractères.
Le point de bascule n'est pas le moment de l'enregistrement, mais juste avant l'affichage à l'écran.
| Caractère au sens particulier en HTML | Écriture après remplacement | Caractère visible à l'écran |
|---|---|---|
| < | < | < |
| > | > | > |
| & | & | & |
| " | " | " |
| ' | ' | ' |
Remplacés juste avant l'affichage, les messages restent du texte
Si tu affiches une publication telle quelle, ce qui y était mêlé s'exécute dans le navigateur d'un autre utilisateur.
Ce qui arrête cela, c'est le remplacement effectué juste avant l'affichage ; comme seuls les symboles sont remplacés, le texte que voit le lecteur ne change pas.
Arrêter les valeurs secrètes avant qu'elles ne deviennent lisibles par plus de personnes
L'autre point concerne l'endroit où sont conservées les informations secrètes.
Ce que tu regardes ici, c'est combien de personnes peuvent lire l'endroit où tu les as placées.
- .env — les valeurs des clés d'API et des mots de passe
- Fichiers de configuration utilisés seulement chez toi
- server.js — le code qui tourne sur le serveur
- .gitignore — la liste des fichiers à ne pas enregistrer
- .env.example — un modèle qui ne contient que les noms
- index.html — l'écran des avis
- script.js — le code qui tourne sur la page
Plus le cadre est intérieur, plus il y a de lecteurs : script.js est lisible par n'importe qui, et server.js, une fois enregistré dans Git, est lisible par toutes les personnes à qui tu as donné le code.
Écrire .env dans le .gitignore (un fichier qui liste les noms des fichiers que Git ne doit pas enregistrer) empêche les valeurs d'entrer dans l'historique, mais
une fois enregistrées, elles ne disparaissent plus de l'historique : tu régénères donc les valeurs elles-mêmes.
Une valeur entrée dans un dépôt public est lisible par n'importe qui dans le monde.
- script.js — le code livré au navigateur
- La fin de l'URL que tu appelles
- Les messages d'erreur affichés à l'écran
- server.js — le code enregistré dans Git
- .env une fois enregistré — reste dans l'historique
- Variables d'environnement du serveur — les clés d'API et les mots de passe vont ici
Le cercle le plus intérieur ne contient que les variables d'environnement du serveur.
Tu n'écris pas les valeurs dans les endroits des deux cercles extérieurs, ni dans les logs (l'enregistrement de l'activité que garde le serveur), qui peuvent sortir du serveur.
Le my-app qui tourne dans le cadre de droite charge la valeur depuis les variables d'environnement.
Cette valeur n'entre jamais dans les deux cadres de gauche : le nombre de personnes qui peuvent la lire n'augmente pas.
L'endroit où placer un secret dépend du nombre de lecteurs
L'endroit où tu peux conserver une valeur secrète dépend du nombre de personnes qui peuvent lire cet endroit.
Un fichier livré au navigateur est lisible par n'importe qui et un fichier enregistré dans Git parvient à toutes les personnes à qui tu donnes le code : tu n'écris la valeur ni dans l'un ni dans l'autre, tu la places dans les variables d'environnement du serveur.
Vérification des connaissances
Répondez à chaque question une par une.
Question 2Que fait l'écriture avec placeholder, qui empêche l'injection SQL ?
Question 3Quel est le bon endroit pour conserver la clé d'API d'un service externe ?