5 bonnes pratiques de sécurité pour React avec TypeScript
Marcelo Oliveira
8 décembre 2022
0 minutes de lectureEn tant que bibliothèque dédiée à la création d’interfaces utilisateur, et non un framework complet, React permet aux développeurs de choisir les bibliothèques qu’ils préfèrent pour différents aspects d’une application, comme le routage, l’historique et l’authentification. De son côté, Microsoft a créé TypeScript comme une extension de JavaScript afin d’ajouter le typage statique facultatif à un langage autrement faiblement typé.
L’utilisation de TypeScript avec React présente plusieurs avantages pour le développement d’applications, notamment la possibilité de créer des composants React plus simples et de mieux prendre en charge JavaScript XML (JSX) pour la validation des types statiques. Comme nous pouvons utiliser des composants JavaScript dans un projet TypeScript, les équipes de développement qui maîtrisent JavaScript peuvent mettre à profit ces connaissances et bénéficier du typage fort.
Il existe de nombreux modèles de base pour démarrer des projets React, notamment Create React App, Create Next App, Vite, React Boilerplate et React Starter Kit.
Create React App est un outil autonome qui fonctionne avec npm ou Yarn. Une fois installé, il suffit de quelques commandes pour générer et lancer un nouveau projet.
Commencez par ouvrir votre terminal et exécutez la commande suivante pour installer l’outil Create React App :
Créez ensuite un projet à l’aide du modèle TypeScript avec l’exécution de paquets Node (npx) :
Vous pouvez également créer le projet avec le gestionnaire de paquets Yarn :
les risques de sécurité potentiels et les moyens de les atténuer.
Activer le mode strict
Le mode strict active automatiquement les paramètres du compilateur TypeScript liés aux règles de types de données. Lorsque le mode strict de TypeScript est activé, le code est validé selon des règles de typage strictes. Les développeurs doivent ainsi écrire du code qui respecte les limites des types de données attribués aux variables, constantes, paramètres et valeurs de retour des fonctions. Le mode strict est important, car il permet aux développeurs de détecter et de corriger les erreurs d’incompatibilité de types dès les premières phases du développement.
Supposons qu’une application contienne la fonction suivante :
Nous appelons la fonction deleteComment en passant l’argument slug sous forme de chaîne et commentId sous forme de nombre :
Toutefois, rien ne nous empêche d’appeler la fonction avec deux chaînes :
Le code ci-dessus n’est peut-être pas autorisé par les règles métier, mais comme nous n’avons pas indiqué de types, les deux paramètres sont considérés comme étant de type any par défaut. Par conséquent, TypeScript ne peut pas nous aider à détecter le problème tant que nous n’activons pas le mode strict.
Le mode strict est défini sur true dans les applications React nouvellement créées. Cette valeur peut toutefois être différente dans les projets existants.
Pour vérifier que notre projet TypeScript fonctionne en mode strict, ouvrez le fichier tsconfig.json et vérifiez que la valeur de la configuration strict est true :
Revenons à la fonction deleteComment. Une petite modification suffit à déclencher des erreurs de compilation TypeScript :

Ajoutez les types chaîne et nombre aux paramètres de deleteComment :
Cela génère des erreurs de compilation et empêche les développeurs de créer du code côté client qui appelle par inadvertance la fonction deleteComment avec des types non valides, comme dans l’exemple ci-dessous :

L’option strict active automatiquement d’autres options de compilateur recommandées, liées à la vérification des types plus stricte.
N’utilisez pas le type de retour any pour les fonctions de rappel dont la valeur sera ignorée
Si vous déclarez le type de retour d’une fonction de rappel comme any, puis utilisez par inadvertance sa valeur de retour alors que la fonction ne renvoie aucune valeur, vous risquez de faire une erreur qui passera inaperçue.
Prenons l’exemple d’une fonction nommée onListFieldKeyUp qui prend en paramètre une fonction de rappel nommée onEnter :
Notez que la variable enterResult ci-dessus stocke le résultat de la fonction de rappel onEnter afin de pouvoir le réutiliser. Bien que cette fonction de rappel ne renvoie aucune valeur, nous avons déclaré la variable enterResult de type any. TypeScript ne peut donc pas vous signaler le problème.
Quelle est la solution ?
Tout d’abord, si vous savez que la fonction onEnter ne renvoie aucune valeur, remplacez le type any du paramètre de la fonction de rappel par void. TypeScript affiche alors l’erreur « Une expression de type 'void' ne peut pas être testée pour sa valeur de vérité. »

Enfin, supprimez le code qui stocke la valeur de retour de onEnter dans la variable enterResult :
Attaques par rendu côté serveur dans React
Une application web peut générer le code HTML côté client ou côté serveur. Les bibliothèques et frameworks JavaScript modernes, comme React, utilisent le rendu côté serveur. Cette approche améliore les performances, notamment en accélérant le chargement des pages : le back-end peut pré-générer rapidement la page entière et transmettre le contenu HTML, CSS et JavaScript statique au front-end. Les utilisateurs peuvent ainsi naviguer et afficher la page web instantanément. Cette approche contribue également au référencement naturel (SEO), car les pages qui se chargent rapidement obtiennent de meilleurs scores dans les algorithmes de recherche.
Le cross-site scripting (XSS) est une méthode d’attaque qui consiste à injecter des scripts malveillants côté client dans une page web. React a été conçu pour se protéger des attaques XSS. Toutefois, une programmation incorrecte et le rendu côté serveur dans React peuvent entraîner une vulnérabilité XSS que des utilisateurs malveillants chercheront à exploiter.
Par exemple, ne concaténez jamais de données non assainies avec le résultat de la fonction renderToStaticMarkup avant d’envoyer la chaîne au client :
Le code ci-dessus est dangereux, car un pirate pourrait avoir compromis la variable someUnsanitizedData afin d’y inclure du code JavaScript malveillant, comme ci-dessous :
Pour prévenir les attaques XSS, utilisez un assainisseur HTML comme DomPurify.
Utiliser des types opaques
Un type de données opaque garantit le masquage des informations. Sa structure de données n’est pas définie dans l’interface, ce qui masque et encapsule l’implémentation d’un type de données concret. Les modules externes peuvent utiliser le type opaque sans accéder à ses composants internes, tandis que les fonctions internes disposant des informations manquantes peuvent manipuler ce type. Les types opaques vous permettent de modifier et de faire évoluer les détails internes sans changer le code qui les utilise. Leur utilisation reste donc une bonne pratique de développement.
TypeScript ne fournit pas de types opaques prêts à l’emploi, mais il est facile de les implémenter. Voyons comment résoudre un cas concret.
Imaginons une application de commerce en ligne qui utilise une fonction TypeScript pour ajouter un produit au panier d’un client :
Ces paramètres typés garantissent que le programmeur ne pourra pas utiliser des nombres ou d’autres types à la place de chaînes pour les paramètres customerCode et productCode :
Ce code ne présente rien de problématique en soi, mais le type n’exprime pas les valeurs avec précision. À la simple lecture de la ligne de code, on ne peut pas savoir quel paramètre correspond au code client ou au code produit. De plus, TypeScript n’affichera aucun avertissement si les deux valeurs sont interverties.
Voyons maintenant comment la fonction addToCart a été remaniée dans l’exemple ci-dessous pour utiliser des types opaques :
Grâce à nos nouveaux types opaques et à leur validation par expression régulière, le code génère une erreur de compilation si vous fournissez des codes incorrects :
Quand utiliser dangerouslySetInnerHTML et respecter les bonnes pratiques d’assainissement
React utilise un DOM virtuel, une stratégie légère permettant de mettre à jour efficacement le code HTML de la page et évitant aux utilisateurs de devoir manipuler directement les éléments HTML au moyen des API natives du navigateur.
Il peut toutefois arriver que vous deviez contourner ce mécanisme et définir du code HTML brut dans vos applications React. Pour manipuler directement ce code HTML, React utilise une propriété spéciale de composant appelée dangerouslySetInnerHTML :
Comme son nom l’indique, la propriété dangerouslySetInnerHTML peut rendre une application vulnérable si elle n’est pas utilisée correctement. Les pirates peuvent exploiter les applications qui s’appuient sur dangerouslySetInnerHTML pour lancer des attaques de cross-site scripting (XSS) et injecter dans votre site web des scripts malveillants déguisés en saisies utilisateur fiables.
Pour éviter ce risque, assainissez toujours le contenu HTML avant de l’insérer afin d’éliminer les « impuretés » et le code malveillant. Vous pouvez utiliser une bibliothèque comme DOMPurify et appliquer la fonction sanitize :
Il est essentiel de noter que, comme toute autre bibliothèque, DOMPurify peut occasionnellement présenter une vulnérabilité de sécurité. Heureusement, la Snyk Vulnerability Database a rapidement intégré les données sur cette vulnérabilité et proposé une solution. Ainsi, quelle que soit la fiabilité historique d’une bibliothèque, nous devons tout de même faire preuve de diligence et utiliser un outil comme Snyk pour rechercher régulièrement les vulnérabilités connues.
Et ce n’est là qu’un des problèmes de sécurité auxquels les développeurs doivent prêter attention. Dans cette vidéo, Liran Tal explique comment les développeurs React peuvent commettre des erreurs qui entraînent d’autres vulnérabilités exploitables par les pirates.

Conclusion
Dans cet article, nous avons présenté plusieurs bonnes pratiques pour développer des applications React avec TypeScript, décrit les risques de sécurité potentiels et proposé des solutions.
Le mode strict permet d’imposer des contraintes de types et de détecter tôt dans le développement les erreurs d’incompatibilité de types. L’utilisation de
voiddans les fonctions de rappel empêche les développeurs d’utiliser une valeur de retour lorsque la fonction de rappel n’en renvoie aucune.Les attaques par injection de commandes constituent une grave menace pour la sécurité. Évitez de créer du code dynamique à partir de saisies utilisateur suspectes et utilisez la fonction
execFileplutôt queexec.Les injections HTML constituent une autre grave menace pour la sécurité. Lorsque vous utilisez
dangerouslySetInnerHTML, assainissez toujours le balisage inséré afin d’empêcher les pirates de manipuler les saisies utilisateur et d’injecter du code malveillant.Enfin, les types opaques donnent du sens aux domaines et facilitent la validation des types ainsi que la prévention des doublons.
Il est facile d’utiliser TypeScript et React pour créer des applications rapides et sécurisées, en particulier avec des frameworks comme Create React App et en s’appuyant sur vos connaissances préalables de JavaScript.



