Votre code dans le viseur : pourquoi la sécurité TypeScript n'est pas une option, mais une nécessité
\n\nAvez-vous déjà pensé à ce qui se passe lorsqu'un utilisateur saisit dans le champ de recherche de votre site non pas « livres Python », mais quelque chose comme '; DROP TABLE users; -- ? Si votre backend en TypeScript n'est pas préparé à une telle éventualité, vous risquez non seulement d'obtenir une erreur, mais de perdre toute votre base de données. Cela ressemble à un scénario de film d'horreur ? Bienvenue dans le monde réel du développement web, où la sécurité TypeScript n'est pas une fonctionnalité à la mode, mais une hygiène de code de base.
Dans cet article, nous ne ferons pas de cours ennuyeux. Nous allons décortiquer les deux principaux ennemis de toute application web : les injections SQL et le XSS (Cross-Site Scripting). Vous apprendrez comment les pirates attaquent vos projets et, surtout, comment transformer votre code TypeScript en une forteresse imprenable grâce à des exemples concrets et aux meilleures pratiques.
\n\nInjections SQL : comment les attaquants « parlent » à votre base de données
\n\nImaginez que votre application est un concierge poli qui exécute toutes les demandes d'un client. Si le client demande : « Montrez-moi la chambre n°5 », le concierge la montre. Mais que se passe-t-il si le client demande : « Montrez-moi toutes les chambres et donnez-moi les clés du coffre » ? Sans vérification, le concierge le fera aussi. L'injection SQL fonctionne exactement de cette manière : l'attaquant « intègre » ses propres commandes dans une saisie utilisateur normale.
\n\nSupposons que vous ayez une requête simple pour rechercher un utilisateur par son nom :
\n\n// ❌ DANGEREUX : code vulnérable\nconst userName = req.body.username; // l'utilisateur a saisi "admin"\nconst query = `SELECT * FROM users WHERE name = '${userName}'`;\ndb.execute(query);\n\nCela semble inoffensif ? Imaginez maintenant que l'utilisateur saisisse : admin' OR '1'='1. La requête devient :
SELECT * FROM users WHERE name = 'admin' OR '1'='1'\n\nFélicitations ! Vous venez de donner à l'attaquant la liste de tous les utilisateurs du système. Et s'il veut supprimer quelque chose ? Facile : admin'; DROP TABLE users; -- — et votre base de données n'existe plus.
Comment se protéger : les requêtes paramétrées, votre bouclier
\n\nLa règle principale pour la protection contre les injections SQL en TypeScript : n'insérez jamais les données utilisateur directement dans une chaîne de requête. Utilisez des requêtes paramétrées (prepared statements). Elles séparent le code SQL des données, et la base de données traite la saisie utilisateur uniquement comme des données, et non comme des commandes.
\n\nExemple avec la bibliothèque pg (pour PostgreSQL) :
// ✅ SÉCURISÉ : requête paramétrée\nimport { Pool } from 'pg';\n\nconst pool = new Pool({\n connectionString: process.env.DATABASE_URL\n});\n\nasync function getUserByName(userName: string): Promise<any> {\n const query = 'SELECT * FROM users WHERE name = $1';\n const result = await pool.query(query, [userName]);\n return result.rows;\n}\n\n// Utilisation\nconst userInput = req.body.username; // même si c'est "admin' OR '1'='1"\nconst user = await getUserByName(userInput);\n// La base de données traitera cela comme une recherche d'utilisateur avec ce nom étrange\nconsole.log(user); // [] — rien trouvé\n\nLe même principe s'applique avec d'autres ORM, comme Prisma ou TypeORM. Ils utilisent par défaut des requêtes paramétrées, ce qui fait de la sécurité TypeScript une fonctionnalité intégrée.
\n\n// ✅ SÉCURISÉ : utilisation de Prisma\nimport { PrismaClient } from '@prisma/client';\n\nconst prisma = new PrismaClient();\n\nasync function findUser(name: string) {\n return prisma.user.findUnique({\n where: { name: name } // Prisma échappe lui-même les données d'entrée\n });\n}\n\nAttaques XSS : quand votre site commence à diffuser du code étranger
\n\nSi les injections SQL frappent la base de données, le XSS (Cross-Site Scripting) attaque vos utilisateurs. Imaginez qu'un atta