Hooki

Hook regex: Wykrywanie wzorców podatnych na ReDoS

Przeszukuj bazę kodu pod kątem wyrażeń regularnych podatnych na ReDoS albo oceniaj pojedynczy wzorzec z wiersza poleceń.

Hook regex to deterministyczny silnik bezpieczeństwa wyrażeń regularnych, z którego korzysta specjalizacja regex, i możesz uruchomić go samodzielnie. Jedno polecenie działa w dwóch trybach: scan przeszukuje bazę kodu pod kątem wzorców podatnych na ReDoS i budowanych w czasie działania, a check ocenia pojedynczy wzorzec, który mu przekażesz.

Przeszukaj bazę kodu​

Bez żadnej flagi hook przeszukuje cały projekt. Opcja --dir ogranicza skanowanie do folderu, a --file do jednego pliku. Obie można powtarzać i łączyć w jeden raport, w którym każdy plik pojawia się tylko raz, nawet jeśli obejmuje go więcej niż jeden cel.

npx lagune read regex

Wynik to zwykły tekst, którego nagłówki mówią, jak czytać każdą sekcję. Sekcja pojawia się tylko wtedy, gdy zawiera ustalenia.

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

Gdy nic nie znajdzie, hook wypisuje jedną linię.

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

Jak odczytać sekcje​

SekcjaZnaczenie
Vulnerable regular expressions foundWzorce podatne na ReDoS, pogrupowane według plików, każdy wzorzec z wcięciem pod nazwą pliku, a za nim w nawiasie powód, dla którego jest niebezpieczny, oraz, jeśli je ma, jego zakres i flagi. Każda linia jest niebezpieczna, więc werdykt się nie powtarza.
Regular expressions the analysis could not settle (review manually)Wzorce, których analiza nie zdołała rozstrzygnąć w ramach swojego limitu pracy, wypisane w ten sam sposób.
Dynamically built regular expressions (review manually by simulating a constructed regex)Pliki, które budują wyrażenie regularne ze zmiennej, konkatenacji lub interpolacji.
Static regex wrapped in a constructor (use a literal instead)Pliki, które przekazują zwykły literał tekstowy do konstruktora wyrażenia regularnego tam, gdzie literał wyrażenia regularnego jest prostszy i pozwala uniknąć kompilacji w czasie działania.

Pierwsza sekcja to ustalenie bezpieczeństwa. Druga i trzecia same w sobie nie są ustaleniami: wskazują kod, którego statyczne sprawdzenie nie rozstrzygnie, więc wymagają, aby przeczytał go człowiek. Czwarta to wskazówka dotycząca czytelności, a nie ustalenie bezpieczeństwa.

Opcje CLI​

OpcjaWartośćOpis
--patternźródło wyrażenia regularnegoSprawdza jeden wzorzec. Powtórz, aby sprawdzić kilka, po jednym werdykcie na wzorzec, w tej samej kolejności.
--flagsflagi wyrażenia regularnegoSprawdza każdy --pattern z tymi flagami, na przykład im. Dotyczy tylko trybu check.
--dirfolderOgranicza skanowanie do folderu. Można powtarzać i łączyć z --file.
--fileplikOgranicza skanowanie do jednego pliku. Można powtarzać i łączyć z --dir.
--limitnieujemna liczba całkowitaUstawia limit powtórzeń ReDoS (domyślnie 25). Dotyczy obu trybów. Im niższy limit, tym surowsza ocena.

Bez żadnej opcji hook przeszukuje cały projekt. Opcja --pattern uruchamia tryb check i nie można jej łączyć z --dir ani --file.

Wybierz, co hook przeszukuje​

Hook pomija to, co ignoruje Git. Aby pominąć więcej albo przeszukać to, co ignoruje Git, nadaj hookowi regex własne ustawienia:

npx lagune write add --ignore test/fixtures --checker regex
{
"checkers": {
"regex": { "gitignore": false, "ignore": ["test/fixtures"] }
}
}

Konfiguracja hooków opisuje każde ustawienie.

Obsługiwane języki​

Skanowanie czyta poniższe języki, rozpoznając je po rozszerzeniu pliku, każdy według jego własnych reguł, więc wzorca z jednego języka nigdy nie testuje według reguł innego. Wszystko inne pomija, zamiast skanować według niewłaściwych reguł.

#JęzykRozszerzenia
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
Staranny, ale niewyczerpujący

Hook czyta kod źródłowy jako tekst, więc nie oceni wzorca składanego w czasie działania, a wzorzec rozbity na kilka linii, ukryty za aliasem lub zapisany w formie, której nie rozpoznaje, może się prześlizgnąć. Traktuj sekcje jako solidny punkt wyjścia, a nie pełny spis, i nadal czytaj kod, aby wychwycić to, czego one nie obejmują.

Sprawdź pojedynczy wzorzec​

Przekaż źródło wzorca w opcji --pattern, aby go ocenić. Hook wypisuje jedno słowo: safe, unsafe, undetermined, gdy analiza osiągnie limit pracy, zanim rozstrzygnie wzorzec, albo invalid regex. Powtórz --pattern, aby ocenić kilka wzorców naraz, po jednym werdykcie na wzorzec, w tej samej kolejności.

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

npx lagune read regex --pattern '^[a-z0-9_]{3,20}$'
# => safe
Dlaczego argument w cudzysłowie

Każdy wzorzec trafia do hooka jako wartość flagi i nigdy nie jest wstawiany do polecenia. Wartość z cudzysłowami lub backtickami pozostaje nieszkodliwa i nie może niczego wstrzyknąć do powłoki. Zawsze ujmuj wzorzec w apostrofy, aby powłoka nie rozwinęła go wcześniej.

wskazówka

To ten sam silnik, którego używa specjalizacja regex: skanowanie otwiera przegląd pod kątem ReDoS, a sprawdzenie potwierdza wzorzec, który ten przegląd wychwyci.

Najczęściej zadawane pytania

Uruchom npx lagune read regex --pattern '<pattern>'. Polecenie zwraca safe, unsafe, undetermined lub invalid regex.

Uruchom hook regex w trybie scan na całej bazie kodu. Zgłasza wzorce podatne na ReDoS w 25 obsługiwanych językach.