Перейти к содержанию

Использование несуществующей группы захвата в регулярном выражении

Идентификатор проверки Gixy: invalid_regex

При использовании регулярных выражений с группами захвата в директивах NGINX, таких как rewrite или в условиях if, вы можете ссылаться на захваченные группы с помощью $1, $2 и т.д. в строках замены или последующих директивах. Однако если вы ссылаетесь на группу захвата, которая не существует в шаблоне regex, NGINX обработает её как пустую строку, что может привести к неожиданному поведению.

Как это найти?

Следует проверить: - Директивы rewrite, где строка замены ссылается на группы захвата (например, $1, $2), которые не существуют в шаблоне regex - Директивы set внутри блоков if, которые ссылаются на группы захвата из шаблона regex условия if - Не захватывающие группы, такие как (?:...), или встроенные модификаторы, такие как (?i), которые не создают нумерованные группы захвата

Примеры

Пример 1: Не захватывающий встроенный модификатор

Проблемная конфигурация:

server {
    location / {
        # (?i) — это флаг регистронезависимости, НЕ группа захвата
        rewrite "(?i)/" $1 break;
    }
}

Проблема: Шаблон (?i)/ использует (?i) для включения регистронезависимого сопоставления, но он не создаёт группу захвата. Ссылка $1 будет пустой.

Исправление:

server {
    location / {
        # Добавьте скобки для создания группы захвата
        rewrite "(?i)/(.*)" /$1 break;
    }
}

Пример 2: Отсутствующие группы захвата

Проблемная конфигурация:

server {
    location / {
        rewrite "^/path" $1 redirect;
    }
}

Проблема: Шаблон ^/path не содержит групп захвата, поэтому $1 будет пустым.

Исправление:

server {
    location / {
        # Либо удалите ненужную ссылку $1
        rewrite "^/path" /newpath redirect;
        # Либо добавьте группу захвата, если необходимо
        rewrite "^/path/(.*)$" /newpath/$1 redirect;
    }
}

Пример 3: Ссылка на неправильный номер группы

Проблемная конфигурация:

server {
    location / {
        # Шаблон имеет только 1 группу захвата, но ссылается на $2
        rewrite "^/(.*)$" /$1/$2 break;
    }
}

Проблема: Шаблон содержит только одну группу захвата (.*), но замена ссылается и на $1, и на $2. Значение $2 будет пустым.

Исправление:

server {
    location / {
        # Добавьте вторую группу захвата, если необходимо
        rewrite "^/([^/]+)/(.*)$" /$2/$1 break;
        # Или удалите некорректную ссылку
        rewrite "^/(.*)$" /prefix/$1 break;
    }
}

Пример 4: Set в блоке if

Проблемная конфигурация:

server {
    location / {
        if ($uri ~ "^/path") {
            set $x $1;  # $1 не существует
        }
    }
}

Проблема: Шаблон regex в условии if не содержит групп захвата, поэтому $1 не определена.

Исправление:

server {
    location / {
        if ($uri ~ "^/path/(.*)$") {
            set $x $1;  # Теперь $1 содержит захваченное значение
        }
    }
}

Что можно сделать?

  1. Добавьте группы захвата в ваш шаблон regex, если вам нужно ссылаться на части совпавшей строки
  2. Удалите ненужные ссылки на группы захвата, если они вам не требуются
  3. Используйте правильные номера групп — помните, что нумерация групп начинается с 1, и $0 недоступен в NGINX
  4. Помните, что не захватывающие группы не создают ссылок — шаблоны типа (?:...), (?i), (?=...) не создают нумерованные группы
  5. Тестируйте ваши шаблоны regex, чтобы убедиться, что они захватывают то, что вы ожидаете

Ловите такие ошибки до продакшена

GetPageSpeed Amplify запускает Gixy по расписанию на каждом сервере NGINX и оповещает о новых находках и CVE, показывая их рядом с метриками. Настроить непрерывный мониторинг.