Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Введение:
В публикации речь идет о warnings и vulnerabilities при установке библиотек с помощью yarn и о том, как от них избавиться. Я рассмотрел несколько случаев, приведенных ниже, но решения можно применять и к другим, схожим ситуациям:
Warnings типа:
has incorrect peer dependency
has unmet peer dependency
Vulnerabilities:
Prototype pollution in webpack loader-utils
loader-utils is vulnerable to Regular Expression Denial of Service (ReDoS)
Crash in HeaderParser in dicer·
Если лень читать, то есть ВИДЕО.
Основная идея
Хочу поделится шпаргалкой по работе с package.json, в частности, как бороться с уязвимостями (vulnerabilities) и сообщениями типа «has unmet peer dependency» и «has incorrect peer dependency» при использовании yarn.
Проблема, чаще всего, связанна зависимостями устанавливаемых библиотек, которые используются в приложении. Для их установки, в моем текущем проекте, используется yarn. Соответственно, детальную информацию, о том какие установлены библиотеки и о том какие есть зависимости между ними можно найти в yarn.lock.
Если его просмотреть, то можно увидеть, что разные версии одной и той же библиотеки могут использоваться во множестве других и все эти версии качаются как отдельные сущности этой библиотеки. Эти версии можно объединить в одну, но при этом стоит проверить, не сломает ли такое объединение работу зависимых библиотек.
Для того, чтобы это сделать, в package.json можно добавить поле resolutions, в котором прописать какие версии библиотек нужно использовать и в каких случаях. Причем, есть возможность указать номер версии, отличный от того, который требует зависимая библиотека.
Это позволяет избавиться от уязвимостей. Например, если одна библиотека зависит от какой-то версии другой библиотеки и в этой версии есть уязвимость, которая исправлена в более поздней версии, то можно «подсунуть» вместо версии с уязвимостью, версию с исправлением этой уязвимости.
Как это работает
Для примера я взял проект максимально близкий к тому, с которым я сейчас работаю, чтобы быть уверенным в том, что манипуляции с версиями пакетов ничего в нем не сломают. Поэтому пример будет с angular, но в данном случае это не принципиально:
Шаг 1:
npx -p @angular/cli@15.0.0 ng new simple-config-prj --skip-git
Откроем simple-config-prj в редакторе (например в VS Code), удалим package-lock.json и выполним команду
yarn install
Шаг 2:
Добавим библиотеку ngx-build-plus@15.0.0:
yarn add ngx-build-plus@15.0.0 -D
В процессе установки библиотеки yarn выдает 6 предупреждений:
Список предупреждений
warning "ngx-build-plus > @angular-devkit/build-angular@16.0.3" has incorrect peer dependency "@angular/compiler-cli@^16.0.0
warning "ngx-build-plus > @angular-devkit/build-angular@16.0.3" has incorrect peer dependency "typescript@>=4.9.3 <5.1".
warning "ngx-build-plus > @angular-devkit/build-angular > @ngtools/webpack@16.0.3" has incorrect peer dependency "@angular/compiler-cli@^16.0.0".
warning "ngx-build-plus > @angular-devkit/build-angular > @ngtools/webpack@16.0.3" has incorrect peer dependency "typescript@>=4.9.3 <5.1".
warning "ngx-build-plus > @angular-devkit/build-angular > postcss-loader > cosmiconfig-typescript-loader@4.3.0" has unmet peer dependency "@types/node@*".
warning "ngx-build-plus > @angular-devkit/build-angular > postcss-loader > cosmiconfig-typescript-loader@4.3.0" has unmet peer dependency "ts-node@>=10
В yarn.lock можно увидеть, что ngx-build-plus содержит такую зависимость:
"@angular-devkit/build-angular" ">=15.0.0"
Yarn почему-то решил, что ему мало уже установленной библиотеки @angular-devkit/build-angular@15.0.0 и скачал последнюю доступную @angular-devkit/build-angular@16.0.3, а у нас Αngular 15, а не 16. Чтобы это исправить можно добавить в блок resolutions следующее:
resolutions
"resolutions": {
"@angular-devkit/build-angular": "^15.0.0"
}
После установки мы видим, как в yarn.lock версии ">=15.0.0" и "^15.0.0" объединились в одну, в данный момент в версию «15.2.8»
Далее запустив команду yarn upgrade ngx-build-plus, можно увидеть, что все предупреждения пропали.
Шаг 3:
Установим библиотеку @ephesoft/webpack.istanbul.loader:
yarn add @ephesoft/webpack.istanbul.loader -D
При установке появится предупреждение:
Предупреждение
warning " > /webpack.istanbul.loader@2.2.0" has unmet peer dependency webpack@>=5.74.0
Как я понял, если yarn встречает знак больше либо равно «>=...», то он предпочитает устанавливать последнюю версию.
В yarn.lock видно, что библиотека @angular-devkit/build-angular уже установила webpack@5.76.1.
Есть 3 способа избавиться от данного предупреждения (warning):
Способ 1:
yarn add webpack -D
Самый простой и быстрый способ. Просто добавится последняя версия webpack, к уже существующей. Таким образом, в текущей сборке, у нас будут присутствовать 2 версии webpack.
Способ 2:
"resolutions": {
"@angular-devkit/build-angular": "^15.0.0",
"@angular-devkit/build-angular/webpack": "5.76.1"
}
Тут мы говорим, что для @ephesoft/webpack.istanbul.loader используй всегда версию "5.76.1", что, теоретически, может в будущем привести к конфликту при устаноке новой версии @ephesoft/webpack.istanbul.loader. Но, с другой стороны, у нас в приложении будет только одна версия пакета webpack.
Способ 3:
"resolutions": {
"@angular-devkit/build-angular": "^15.0.0",
"webpack": "5.76.1"
}
В этом случае мы говорим, что наше приложение использует только webpack версии "5.76.1", что так же, возможно, может привести к конфликтам в будущем.
Шаг 4:
Если теперь набрать команду
yarn audit
, то появится сообщение о наличие 3 уязвимостей:
Уязвимости
Prototype pollution in webpack loader-utils
loader-utils is vulnerable to Regular Expression Denial of Service (ReDoS)
loader-utils is vulnerable to Regular Expression Denial of Service (ReDoS) via url variable
Причина в библиотеке loader-utils версии "1.4.0", которую использует @ephesoft/webpack.istanbul.loader. Если почитать про данные уязвимости, то пишут что они были исправлены в версии 1.4.2. Но при анализе yarn.lock видно, что библиотека loader-utils встречается 3-жды и если её явно прописать с последней версией, то это может сломать работу других библиотек. Чтобы минимизировать вмешательство можно подменить версию только для @ephesoft/webpack.istanbul.loader:
"resolutions": {
"@angular-devkit/build-angular": "^15.0.0",
"@ephesoft/webpack.istanbul.loader/loader-utils": "^2.0.0"
}
В идеале лучше установить 1.4.2, но c версией "2.0.4" @ephesoft/webpack.istanbul.loader работает без ошибок, поэтому я решил оставить "^2.0.0", чтобы минимизировать количество используемых библиотек loader-utils. Не всегда подмена версий проходит гладко, бывают ситуации, когда новая версия несовместима с предыдущей и в этом случае зависимый пакет перестанет работать, либо будет работать с ошибками. Поэтому надо оценивать риски и проверят функционал после таких подмен.
Шаг 5:
Ставим пакет hads:
yarn add hads – D
При установке выскакивает предупреждение:
warning hads > multer@1.4.4: Multer 1.x is affected by CVE-2022-24434. This is fixed in v1.4.4-lts.1 which drops support for versions of Node.js before 6. Please upgrade to at least Node.js 6 and version 1.4.4-lts.1 of Multer. If you need support for older versions of Node.js, we are open to accepting patches that would fix the CVE on the main 1.x release line, whilst maintaining compatibility with Node.js 0.10.
А если после установки набрать
yarn audit
, то увидим уязвимость c dicer - Crash in HeaderParser in dicer:
Воспользовавшись советом из предупреждения я подменил версию библиотеки multer:
"resolutions": {
"@angular-devkit/build-angular": "^15.0.0",
"@ephesoft/webpack.istanbul.loader/loader-utils": "^2.0.0",
"multer": "1.4.4-lts.1"
}
Обновляем hads:
yarn upgrade hads
При обновлении выдается предупреждение:
warning
warning Resolution field "multer@1.4.4-lts.1" is incompatible with requested version multer@^1.4.2
После установки убеждаемся, что hads работает без ошибок и проверяем отсутствие уязвимостей командой
yarn audit
Заключение:
Предупреждения и уязвимости не всегда ведут к некорректной работе приложения. Они могут относиться к части development dependencies и не попадать в production сборку. Но их отсутствие гораздо лучше, чем их присутствие.