Пользователям n8n стоит обновиться до версий 1.123.76, 2.37.7 или 2.38.2. Все более ранние сборки зависят от библиотеки browserslist, в которой закрыли две уязвимости, влияющие на доступность. Первая обрушивает процесс при первом же обращении к библиотеке, вторая постепенно забивает память и заканчивается аварийным завершением. Речь о CVE-2026-73088 и CVE-2026-73089.
Детали уязвимостей
browserslist - небольшая библиотека на JavaScript. Она определяет, какие браузеры учитывать при сборке, и её вызывают внутри себя другие инструменты. Именно поэтому проблема выходит за пределы одного продукта: вместе с n8n её получают все проекты, где библиотека попадает в конвейер сборки.
Первая уязвимость кроется в разборе файла со статистикой использования браузеров. Такой файл библиотека ищет сама, поднимаясь по дереву каталогов от корня проекта, и просматривает его при каждом обращении, независимо от того, упоминается статистика в запросе или нет. Если в файле оказывается ключ, совпадающий со служебным свойством, которое JavaScript наследует каждому объекту, код принимает наследника за обычные данные. Вместо ожидаемого списка версий он получает функцию и падает с необработанной ошибкой. Хватает одной такой записи, чтобы первое же обращение к библиотеке закончилось сбоем.
Поскольку проверка идёт на каждом вызове, файл ломает все последующие обращения в проекте, а не только то, которого он касается. В результате останавливаются Autoprefixer, Babel preset-env, Stylelint и PostCSS, причём для совершенно посторонних запросов. Добавить файл можно через pull request от внешнего участника или через скомпрометированную зависимость. Аутентификация не нужна: достаточно возможности положить файл в дерево каталогов проекта.
Кроме обрушения процесса, та же ошибка позволяет записать значение в прототип внутреннего объекта. Исследователь, нашедший уязвимость, отмечает, что обычный объект в этом месте меняет прототип, вместо того чтобы обзавестись новым свойством. На практике это усиливает ту же проблему с обработкой недоверенных ключей. Отдельная защита от подобных случаев в библиотеке уже существовала, но её не применили к разбору статистики.
Вторая уязвимость связана с кэшем результатов. Библиотека запоминает каждый уникальный запрос навсегда: без ограничения размера, без срока жизни и без вытеснения записей. Штатная очистка кэша этих структур не затрагивает. Некоторые короткие и вполне допустимые запросы дают почти неограниченный простор для вариантов, поскольку дата в них принимает любое сочетание цифр. Замеры показали, что двадцать тысяч разных запросов удерживают в памяти больше пятидесяти мегабайт, а сорок тысяч - уже больше пятидесяти двух. Рост линейный, потолка не видно.
Страдают в первую очередь конвейеры сборки и системы непрерывной интеграции, куда попадают файлы от внешних участников, а также длительно работающие сервисы, которые передают в библиотеку значения, зависящие от пользовательского ввода. Вторая уязвимость требует объёма, то есть потока дешёвых и разных запросов, поэтому её оценивают ниже первой. Обе ведут к отказу в обслуживании: процесс либо падает сразу, либо исчерпывает память со временем. По данным бюллетеня, конфиденциальность и целостность не затронуты, тогда как доступность страдает. Обе проблемы нашли в ходе одного исследования библиотеки, вместе с несколькими родственными отказами в обслуживании, для которых хватало единственного запроса.
Исправление вышло в browserslist 4.28.7. Внутренние структуры теперь создают без унаследованных свойств, а ключи проверяют на принадлежность самому объекту. Так запись в прототип превращается в обычное свойство, и наследники больше не подменяют данные. Кэши стали ограниченными: хранится не больше пятисот записей, самые старые вытесняются по мере появления новых. Набор тестов после правки проходит полностью, а повторные замеры памяти показывают ровно тот же объём на сорока тысячах запросов, что и в начале. Разработчики n8n подтянули исправленную версию библиотеки в релизе 1.123.76.
Пользователям n8n достаточно обновиться. Тем, кто собирает проекты с чужими правками, стоит проверять содержимое файлов, которые приходят вместе с pull request, и следить за составом зависимостей. Там, где во внешнюю библиотеку попадает пользовательский ввод, помогает ограничение на число различных значений, принимаемых за раз. Кэш можно отключить переменной окружения BROWSERSLIST_DISABLE_CACHE, однако это снимает только вторую проблему и не защищает от подложенного файла статистики.
Для сборочной экосистемы такие уязвимости стали регулярным риском. Небольшая вспомогательная библиотека встроена в десятки инструментов, и одна лишняя строка в чужом файле способна остановить конвейер целиком. Защита здесь сводится к двум вещам: своевременно обновлять зависимости и относиться к файлам из внешних источников так же настороженно, как к исполняемому коду.
Ссылки
- https://github.com/n8n-io/n8n/releases/tag/n8n@2.38.2
- https://github.com/n8n-io/n8n/releases/tag/n8n@2.37.7
- https://github.com/n8n-io/n8n/releases/tag/n8n@1.123.76
- https://github.com/advisories/GHSA-73wf-gq98-2v4g
- https://github.com/advisories/GHSA-c83g-rgw3-j3cx