
Регулярное выражение для сопоставления URL. Поддерживаемая, безопасная и совместимая с браузерами версия url-regex. Устраняет CVE-2020-7661 для серверов Node.js.
Регулярное выражение для сопоставления URL. Поддерживаемая, безопасная и совместимая с браузерами версия url-regex. Устраняет CVE-2020-7661 для серверов Node.js. Работает в Node v14+ и браузерах. Поддерживается для Spam Scanner и Forward Email.
Обнаружив CVE-2020-7661 и раскрыв его публично (в рамках моей работы над Spam Scanner и Forward Email) – я использовал реализацию url-regex с дополнительной «обвязкой» поверх неё для отсеивания нежелательных совпадений URL.
Однако, используя его в продакшене на Forward Email (который обрабатывает сотни тысяч писем в неделю), я нашёл и задокументировал ещё несколько ключевых проблем в url-regex.
Осознав, что url-regex больше не поддерживается активно, на момент написания имеет 9 открытых pull request'ов, а также не поддерживает браузеры, я решил написать этот пакет для всех и объединить все открытые pull request'ы.
Этот пакет, надеюсь, должен более точно соответствовать реальному предполагаемому использованию регулярного выражения для URL, а также позволять пользователю настраивать его по своему усмотрению. Пожалуйста, загляните в Forward Email, если этот пакет вам помог, и изучите наш исходный код на GitHub, где показано, как мы используем этот пакет.
ПРИМЕЧАНИЕ: По умолчанию этот пакет пытается загрузить re2 (это опциональная peer-зависимость, используемая для предотвращения отказа в обслуживании с помощью регулярных выражений и многого другого). Если вы хотите использовать это поведение, у вас должен быть установлен re2 через npm install re2 – в противном случае будет использоваться обычный RegExp. Начиная с версии v4.0.0 мы добавили опцию, если вы хотите заставить пакет даже не пытаться загружать re2 (например, он есть в вашем node_modules, но вы не хотите его использовать) – просто передайте re2: false в качестве опции.
npm:
npm install url-regex-safe
Мы устранили CVE-2020-7661, включив RE2 для использования с Node.js. Вам больше не придётся вручную оборачивать регулярные выражения для URL с помощью new RE2(urlRegex()) через url-regex-safe (мы делаем это автоматически).
const urlRegexSafe = require('url-regex-safe');
const str = 'some long string with url.com in it';
const matches = str.match(urlRegexSafe());
for (const match of matches) {
console.log('match', match);
}
console.log(urlRegexSafe({ exact: true }).test('github.com'));
Поскольку RE2 не предназначен для браузера, он не будет использоваться, и поэтому CVE-2020-7661 по-прежнему является проблемой на стороне клиента. Однако это не критично, поскольку максимум, что может произойти, — это падение вкладки браузера (в то время как на стороне Node.js это привело бы к падению всего процесса и исключению нехватки памяти).
Это решение для вас, если вы просто используете теги <script> повсюду!
<script src="https://unpkg.com/url-regex-safe"></script>
<script type="text/javascript">
(function() {
var str = 'some long string with url.com in it';
var matches = str.match(urlRegexSafe());
for (var i=0; i<matches.length; i++) {
console.log('match', matches[i]);
}
console.log(urlRegexSafe({ exact: true }).test('github.com'));
})();
</script>
Если вы используете browserify, webpack, rollup или другой сборщик модулей, вы можете просто следовать инструкциям по использованию из раздела Node выше.
Чтобы использовать этот пакет с TypeScript, вы можете установить пакет @types/url-regex-safe для определения типов.
npm install --save-dev @types/url-regex-safe
Вы должны переопределить значение по умолчанию и установить strict: true, если не хотите сопоставлять github.com отдельно (хотя www.github.com будет работать, если strict: false).
В отличие от устаревшего и неподдерживаемого пакета url-regex, мы делаем несколько вещей иначе:
strict в false (в url-regex это было установлено в true)auth, которая по умолчанию установлена в false (url-regex сопоставляется с базовой аутентификацией; там это было установлено в true — однако это устаревшее поведение в Chromium).parens и ipv6, которые по умолчанию установлены в false и true соответственно (в url-regex parens было установлено в true, а ipv6 либо отсутствовала, либо была установлена в ).Это ограничение действует только при использовании re2: Поскольку мы не можем использовать функциональность «отрицательных ретроспективных проверок» (negative lookbehinds) в регулярных выражениях (из-за ограничений RE2), мы не смогли объединить логику из этого pull request. Это позволило бы нам сделать так, чтобы example.jpeg сопоставлялось только в том случае, если это было example.jp, однако сейчас при передаче example.jpeg из него будет извлечено example.jp (поскольку .jp является TLD). Возможно, существует альтернативное решение, и мы приветствуем вклад сообщества в решение этого вопроса.
| Имя | Сайт |
|---|---|
| Forward Email LLC | https://forwardemail.net |
| Kevin Mårtensson | |
| Diego Perini |
| Property | Type | Default Value | Description |
|---|
re2 | Boolean | true | Пытаться загрузить re2 для использования вместо RegExp при создании новых экземпляров регулярных выражений. Если передать re2: false, то загрузка re2 даже не будет предпринята. | |
exact | Boolean | false | Сопоставлять только точную строку. Полезно с regex.test(str) для проверки, является ли строка URL. По умолчанию мы установили значение false, чтобы сопоставлять строки вида github.com (в отличие от требования протокола или поддомена www). Мы считаем, что это больше соответствует реальному предполагаемому использованию этого пакета. | |
strict | Boolean | false | Требовать, чтобы URL начинался с допустимого протокола или www, если установлено значение true. Если true, то будет разрешён любой TLD при условии, что он содержит минимум 2 допустимых символа. Если false, то TLD будет сопоставляться со списком допустимых TLD с помощью tlds. | |
auth | Boolean | false | Сопоставлять с заголовками базовой аутентификации. По умолчанию мы установили значение false, поскольку это было объявлено устаревшим в Chromium, и в противном случае пользователь получает нежелательные совпадения URL (кроме того, значение false по умолчанию больше соответствует реальному предполагаемому использованию этого пакета). | |
localhost | Boolean | true | Разрешает localhost в части hostname URL. Смотрите test/test.js для более подробного понимания теста localhost и того, как он может вернуть значение, которое может быть нежелательным. Для решения проблемы "pic.jp" против "pic.jpg" будет рассмотрен pull request. | |
parens | Boolean | false | Сопоставлять с закрывающей скобкой в стиле Markdown. Мы установили значение false, потому что разбор URL в Markdown должен оставаться на усмотрение пользователя. | |
apostrophes | Boolean | false | Сопоставлять с апострофами. Мы установили значение false, потому что не хотим, чтобы строка background: url('http://example.com/pic.jpg'); приводила к результату http://example.com/pic.jpg'. Подробнее см. в этом issue. | |
trailingPeriod | Boolean | false | Сопоставлять с завершающими точками. По умолчанию мы установили значение false, поскольку в реальных сценариях ожидается совпадение example.com, а не example.com. (в отличие от url-regex, где в этом пакете сопоставляется завершающая точка). | |
ipv4 | Boolean | true | Сопоставлять с IPv4 URL. | |
ipv6 | Boolean | true | Сопоставлять с IPv6 URL. | |
tlds | Array | tlds | Сопоставлять с конкретным списком TLD или со списком по умолчанию, предоставляемым tlds. | |
returnString | Boolean | false | Возвращать RegExp в виде строки вместо RegExp (полезно для пользовательской логики, как мы сделали в Spam Scanner). |
falseapostrophe, которая по умолчанию установлена в false (в url-regex это было установлено в true).trailingPeriod, которая по умолчанию установлена в false (это означает, что совпадения не будут содержать завершающих точек, тогда как в url-regex это было установлено в true).