Hooks

Hook regex : détecter les motifs vulnérables au ReDoS

Analysez une base de code à la recherche de regex exposées au ReDoS, ou évaluez un seul motif, en ligne de commande.

Le hook regex est le moteur déterministe de sûreté des regex qu'exécute la spécialisation regex, et vous pouvez l'exécuter vous-même. Il fonctionne en deux modes depuis une seule commande : une analyse qui parcourt une base de code à la recherche de motifs exposés au ReDoS et de motifs construits à l'exécution, et une vérification qui évalue un seul motif que vous lui donnez.

Analyser une base de code​

Sans option, il analyse tout le projet. --dir limite l'analyse à un répertoire, --file à un seul fichier. Les deux peuvent être répétées et se combinent en un seul rapport, où chaque fichier n'apparaît qu'une fois même quand plusieurs cibles le couvrent.

npx lagune read regex

La sortie est du texte brut dont les en-têtes indiquent comment lire chaque section. Une section n'apparaît que si elle contient des résultats.

Vulnerable regular expressions found:

cmd/server/main.go
([a-z]+)+$ (exponential, search)

Dynamically built regular expressions (review manually by simulating a constructed regex):

app/payments.php
crates/parser/lexer.rs
lib/validate.py

Static regex wrapped in a constructor (use a literal instead):

config/token.rb

Quand rien n'est trouvé, il affiche une seule ligne.

npx lagune read regex --dir src/clean
# => no unsafe patterns found

Lire les sections​

SectionSignification
Vulnerable regular expressions foundMotifs exposés au ReDoS, regroupés par fichier avec chaque motif en retrait en dessous, suivi entre parenthèses de la raison pour laquelle il n'est pas sûr et, s'il en a, de sa portée et de ses flags. Chaque ligne est non sûre, donc le verdict n'est pas répété.
Regular expressions the analysis could not settle (review manually)Motifs que l'analyse n'a pas pu trancher dans sa limite de travail, listés de la même façon.
Dynamically built regular expressions (review manually by simulating a constructed regex)Fichiers qui construisent une regex à partir d'une variable, d'une concaténation ou d'une interpolation.
Static regex wrapped in a constructor (use a literal instead)Fichiers qui passent un simple littéral de chaîne à un constructeur de regex là où un littéral de regex est plus simple et évite une compilation à l'exécution.

La première section est un constat de sécurité. La deuxième et la troisième ne sont pas des constats en soi : elles pointent vers du code qu'une vérification statique ne peut pas trancher, donc elles demandent une lecture humaine. La quatrième est une suggestion de clarté, pas un constat de sécurité.

Options de la CLI​

OptionValeurDescription
--patternla source d'une regexVérifie un motif. Répétez-la pour en vérifier plusieurs, un verdict par motif, dans l'ordre.
--flagsdes flags de regexVérifie chaque --pattern avec ces flags, comme im. S'applique uniquement au mode check.
--dirun répertoireLimite l'analyse à un répertoire. Peut être répétée et combinée avec --file.
--fileun fichierLimite l'analyse à un seul fichier. Peut être répétée et combinée avec --dir.
--limitun entier positif ou nulFixe la limite de répétition du ReDoS (25 par défaut). S'applique aux deux modes. Une limite plus basse est plus stricte.

Sans option, il analyse tout le projet. --pattern correspond au mode check et ne peut pas être combinée avec --dir ou --file.

Langages pris en charge​

L'analyse lit ces langages, selon l'extension du fichier, chacun selon ses propres règles, donc un motif d'un langage n'est jamais testé selon les règles d'un autre. Tout le reste est ignoré plutôt qu'analysé avec les mauvaises règles.

#LangageExtensions
1JavaScript / TypeScript.js, .jsx, .mjs, .cjs, .ts, .tsx, .mts, .cts, .astro, .vue, .svelte, .marko, .riot
2Python.py, .pyi
3Ruby.rb
4Go.go
5PHP.php
6Rust.rs
7Java.java
8C#.cs
9C.c, .h
10C++.cc, .cpp, .cxx, .hpp, .hh, .hxx
11Kotlin.kt, .kts
12Swift.swift
13Scala.scala, .sc
14Dart.dart
15PowerShell.ps1, .psm1, .psd1
16Elixir.ex, .exs
17Objective-C.m, .mm
18R.r
19Julia.jl
20Clojure.clj, .cljs, .cljc, .edn
21Crystal.cr
22Nim.nim, .nims
23V.v
24D.d
25Perl.pl, .pm
Au mieux, pas de façon exhaustive

Il lit le code source comme du texte, donc il ne peut pas juger un motif assemblé à l'exécution, et un motif réparti sur plusieurs lignes, caché derrière un alias ou écrit sous une forme qu'il ne reconnaît pas peut lui échapper. Considérez les sections comme un point de départ solide, pas comme un inventaire complet, et continuez à lire le code pour ce qu'elles ne peuvent pas atteindre.

Vérifier un seul motif​

Passez --pattern avec la source du motif pour l'évaluer. Le hook affiche un mot : safe, unsafe, undetermined quand l'analyse atteint sa limite de travail avant de trancher, ou invalid regex. Répétez --pattern pour en évaluer plusieurs à la fois, un verdict par motif, dans l'ordre.

npx lagune read regex --pattern '(a+)+$'
# => unsafe

npx lagune read regex --pattern '^[a-z0-9_]{3,20}$'
# => safe
Pourquoi un argument entre guillemets

Chaque motif est passé comme valeur d'option, jamais interpolé dans la commande. Une valeur contenant des guillemets ou des backticks reste inerte et ne peut rien injecter dans le shell. Entourez toujours le motif de guillemets simples pour que votre shell ne l'interprète pas d'abord.

astuce

C'est le même moteur qu'exécute la spécialisation regex : l'analyse ouvre une passe ReDoS, la vérification confirme un motif qu'elle fait ressortir.

Questions fréquentes

Exécutez npx lagune read regex --pattern '<pattern>'. Il renvoie safe, unsafe, undetermined ou invalid regex.

Exécutez le hook regex en mode scan sur la base de code. Il signale les motifs exposés au ReDoS dans 25 langages pris en charge.