Passer au contenu principal
eLearner.app
Module 8 · Leçon 4 sur 432/32 dans le cours~14 min
Leçons du module (4/4)

Écrire des motifs ReDoS-safe

Le ReDoS (Regular expression Denial of Service) est une classe d'attaques où une entrée soigneusement conçue fait exploser le temps de calcul d'une regex. Le moteur JS utilise le backtracking (retour en arrière) : si un motif est "ambigu", sur une entrée malheureuse, il peut effectuer un nombre exponentiel de tentatives.

Le motif catastrophique classique

Code
Pattern: ^(a+)+$
Input:   "aaaaaaaaaaaaaaaaaaaaab"

Pour trouver une correspondance, le moteur essaie chaque partition possible de "a" entre les deux quantificateurs +. Sur 20 "a", cela représente 2^20 = ~1 million de tentatives. Sur 30 "a", un milliard.

D'autres exemples dangereux :

  • (a*)*b -- "étoiles imbriquées".
  • (a|a)* -- alternatives qui se chevauchent.
  • (\w+)+@ -- groupes gourmands avec un quantificateur externe.

Comment repérer le danger

Recherchez ces structures :

  1. Quantificateur à l'intérieur d'un quantificateur : (...+)+, (...*)*, (...{n,})+.
  2. Alternatives chevauchantes sous un quantificateur : (a|ab)*, (\w|\d)+.
  3. Lookahead/lookbehind avec des alternatives complexes répétées.

Réécriture défensive

Code
Dangerous:  ^(\w+\s+)+$
Safe:       ^(?:\w+\s+)*\w+$

La version sûre sépare le cas de base du cas répété, éliminant ainsi l'ambiguïté. Autres techniques :

  • Quantificateurs possessifs (a++) -- non pris en charge en JS, mais disponibles dans d'autres moteurs.
  • Motifs atomiques ((?>...)) -- non pris en charge en JS.
  • Limiter la longueur de l'entrée avant la recherche de correspondance.
  • Timeout sur le calcul (l'éditeur de ce cours utilise un worker avec un délai d'expiration de 500 ms).

Recommandations pour des motifs sûrs contre le ReDoS

  1. Assurez-vous que les options dans une alternance sont mutuellement exclusives (ex. n'utilisez pas (a|a+)).
  2. Évitez d'appliquer des quantificateurs imbriqués à des expressions qui se chevauchent (ex. (\\s*)*).
  3. Préférez toujours des classes de caractères négatives spécifiques ([^\\n]*) au point générique (.*).

À vous de jouer

Exercice#regex.m8.l4.e1
Tentatives : 0Chargement…

Identifiez des motifs de lettres répétées -- mais d'une manière sûre contre le ReDoS. Utilisez une seule classe de caractères, PAS de groupes imbriqués comme (a+)+.

Chargement de l'éditeur…
Afficher l'indice

Remplacez le dangereux (a+)+ par un simple a+. Le résultat est le même, mais sûr.

Solution disponible après 3 tentatives

Exercice de révision

Exercice#regex.m8.l4.e2
Tentatives : 0Chargement…

Reconnaissez une séquence de mots séparés par des espaces, de manière précise et sûre contre le ReDoS. Utilisez la structure `(?:word+spaces+)*word` au lieu de `(word+space+)+`.

Chargement de l'éditeur…
Afficher l'indice

Remplacez le groupe de capture (\w+\s+)+ avec la version disjointe (?:\w+\s+)*\w+.

Solution disponible après 3 tentatives

Défi supplémentaire

Exercice#regex.m8.l4.e3
Tentatives : 0Chargement…

Rendez sûr le motif vulnérable `(\w+\s*)+:` qui provoque le ReDoS, en supprimant la récursion des espaces qui se chevauchent.

Chargement de l'éditeur…
Afficher l'indice

Déplacez l'espace pour qu'il ne chevauche pas la répétition du groupe : (?:\w+\s+)*\w+:

Solution disponible après 3 tentatives