В следующей таблице рекомендаций по npm мы сосредоточимся на 10 рекомендациях по обеспечению безопасности npm и советах по повышению производительности, полезных для разработчиков JavaScript и Node.js.
Независимо от того, используете ли вы API-ключи, пароли или другие секреты, они могут очень легко просочиться в систему управления версиями или даже в опубликованный пакет в общедоступном реестре npm. У вас могут быть секреты в вашем рабочем каталоге в определенных файлах, таких как .env
, которые следует добавить в .gitignore
, чтобы избежать привязки к SCM, но что произойдет, когда вы опубликуете пакет npm из каталога проекта?
Командная строка npm упаковывает проект в tar-архив (tarball), чтобы поместить его в реестр. Следующие критерии определяют, какие файлы и каталоги будут добавлены в tarball:
- Если имеется файл
.gitignore
или.npmignore
, содержимое файла используется в качестве шаблона игнорирования при подготовке пакета к публикации. - Если существуют оба файла игнорирования, все, что не находится в файле ".npmignore", публикуется в реестре. Это условие часто приводит к путанице и является проблемой, которая может привести к утечке секретных данных.
Разработчики могут в конечном итоге обновить файл .gitignore
, но забыть также обновить .npmignore
, что может привести к тому, что потенциально конфиденциальный файл не будет передан в систему управления версиями, но все равно будет включен в пакет npm.
Другой полезной практикой является использование свойства files
в package.json, которое работает как allowlist и определяет массив файлов, которые должны быть включены в пакет, который должен быть создан и установлен (в то время как игнорируемый файл функционирует как denylist). Свойство files
и игнорируемый файл могут использоваться вместе для определения того, какие файлы следует явно включать, а какие исключать из пакета. При использовании обоих свойств свойство files
в package.json имеет приоритет над игнорируемым файлом.
Когда пакет публикуется, командная строка npm CLI подробно отображает создаваемый архив. Чтобы быть особенно осторожным, добавьте аргумент командной строки --dry-run
в вашу команду публикации, чтобы сначала просмотреть, как создается архиватор, не публикуя его в реестре.
В январе 2019 года npm опубликовали в своем блоге информацию о том, что они добавили механизм, который автоматически отзывает токен, если они обнаруживают, что токен был опубликован вместе с пакетом.
Мы с распростертыми объятиями восприняли появление файлов блокировки пакетов, которые привнесли: детерминированные установки в различных средах и принудительные ожидания в отношении зависимостей при совместной работе в команде. Жизнь прекрасна! По крайней мере, я так думал… что бы произошло, если бы я внес изменения в файл проекта package.json
, но забыл зафиксировать файл блокировки вместе с ним?
Как Yarn, так и npm действуют одинаково во время установки зависимостей. Когда они обнаруживают несоответствие между package.json
проекта и файлом блокировки, они компенсируют такое изменение на основе манифеста package.json
, устанавливая версии, отличные от тех, которые были записаны в файле блокировки.
Такая ситуация может быть опасной для сред сборки и производства, поскольку они могут привести к появлению непреднамеренных версий пакетов и свести на нет все преимущества файла блокировки.
К счастью, есть способ указать Yarn и npm, что они должны придерживаться указанного набора зависимостей и их версий, указав их в файле блокировки. Любое несоответствие приведет к прерыванию установки. Командная строка должна выглядеть следующим образом:
- Если вы используете Yarn, запустите
yarn install --frozen-lockfile
. - Если вы используете npm, запустите
npm ci
.
Интерфейс CLI npm работает со сценариями запуска пакетов. Если вы когда-либо запускали npm start
или npm test
, то вы тоже использовали сценарии запуска пакетов. Интерфейс CLI npm основан на сценариях, которые может объявлять пакет, и позволяет пакетам определять сценарии для запуска в определенных точках входа во время установки пакета в проекте. Например, некоторые из этих записей script hook могут быть скриптами после установки
, которые будут выполняться устанавливаемым пакетом для выполнения домашней работы.
Обладая этой возможностью, злоумышленники могут создавать или изменять пакеты для выполнения вредоносных действий, выполняя любую произвольную команду при установке своего пакета. Несколько случаев, когда мы уже видели, как это происходило, - это популярный инцидент с eslint-scope, который привел к сбору токенов npm, и инцидент с crossenv, а также 36 других пакетов, которые подверглись атаке с использованием опечаток в реестре npm.
Применяйте эти рекомендации по обеспечению безопасности npm, чтобы свести к минимуму вероятность атаки вредоносного модуля:
- Всегда проверяйте и выполняйте комплексную проверку устанавливаемых вами модулей сторонних производителей, чтобы убедиться в их работоспособности и надежности.
- Воздержитесь от немедленного обновления до новых версий; дайте новым версиям пакетов некоторое время распространиться, прежде чем опробовать их.
- Перед обновлением обязательно ознакомьтесь с журналом изменений и примечаниями к выпуску обновленной версии.
- При установке пакетов обязательно добавьте суффикс
--ignore-scripts
, чтобы отключить выполнение любых скриптов сторонними пакетами. - Подумайте о том, чтобы добавить
ignore-scripts
в ваш файл проекта.npmrc
или в вашу глобальную конфигурацию npm.
Стремление постоянно обновлять зависимости до их последних версий не обязательно является хорошей практикой, если это делается без ознакомления с примечаниями к выпуску, изменениями в коде и, как правило, всестороннего тестирования новых обновлений. С учетом сказанного, устаревание и отсутствие обновления вообще или по прошествии длительного времени также является источником проблем.
Интерфейс командной строки npm может предоставлять информацию о свежести используемых вами зависимостей с учетом их семантического смещения при управлении версиями. Запустив npm устарел
, вы сможете увидеть, какие пакеты устарели. Зависимости, выделенные желтым цветом, соответствуют семантическому управлению версиями, указанному в манифесте package.json, а зависимости, выделенные красным цветом, означают, что доступно обновление. Кроме того, в выходных данных также отображается последняя версия для каждой зависимости.
Учитывая разнообразие Node.js менеджеров пакетов и различных версий Node.js, которые вы, возможно, установили в своем path, как вы проверяете работоспособность установки npm и рабочей среды? Независимо от того, работаете ли вы с npm CLI в среде разработки или в рамках CI, важно убедиться, что все работает так, как ожидалось.
Вызовите врача! Интерфейс командной строки npm включает в себя инструмент оценки работоспособности, позволяющий диагностировать вашу среду для обеспечения эффективного взаимодействия с npm. Запустите "npm doctor", чтобы просмотреть настройки npm:
- Проверьте, доступен ли официальный реестр npm, и отобразите текущий настроенный реестр.
- Проверьте, доступен ли Git.
- Просмотрите установленные версии npm и Node.js.
- Запустите проверку прав доступа к различным папкам, таким как локальная и глобальная
node_modules
, а также к папке, используемой для кэширования пакетов. - Проверьте локальный кэш модуля npm на корректность контрольной суммы.
Экосистема npm является единственным крупнейшим хранилищем библиотек приложений среди всех других языковых экосистем. Реестр и библиотеки в нем являются ключевыми для разработчиков JavaScript, поскольку они могут использовать работу, которую уже создали другие, и включать ее в свою кодовую базу. С учетом сказанного, растущее внедрение библиотек с открытым исходным кодом в приложения влечет за собой повышенный риск появления уязвимостей в системе безопасности.
Было обнаружено, что многие популярные пакеты npm уязвимы и могут представлять значительный риск без надлежащего аудита безопасности зависимостей вашего проекта. Вот некоторые примеры: npm запрос, суперагент, mongoose и даже пакеты, связанные с безопасностью, такие как jsonwebtoken и [validator](https://snyk.io/vuln/search?q=валидатор иtype=npm).
Обеспечение безопасности не сводится к простому сканированию на наличие уязвимостей в системе безопасности при установке пакета, но также должно быть оптимизировано с помощью рабочих процессов разработчиков для эффективного внедрения на протяжении всего жизненного цикла разработки программного обеспечения и постоянного мониторинга при развертывании кода:
- Сканирование на наличие уязвимостей в сторонних проектах с открытым исходным кодом
- Отслеживайте моментальные снимки манифестов вашего проекта, чтобы вы могли получать оповещения, когда на них влияют новые CVE
Реестр npm - это самая большая коллекция пакетов, доступная всем разработчикам JavaScript, а также база для большинства проектов с открытым исходным кодом для веб-разработчиков. Но иногда у вас могут возникнуть другие потребности в плане безопасности, развертывания или производительности. Если это так, npm позволяет вам переключиться на другой реестр:
Когда вы запускаете npm install
, он автоматически устанавливает связь с основным реестром для устранения всех ваших зависимостей; если вы хотите использовать другой реестр, это тоже довольно просто:
- Установите
npm set registry
для настройки реестра по умолчанию. - Используйте аргумент
--registry
для одного реестра.
Verdaccio это простой облегченный частный реестр, не требующий настройки, и установить его так же просто, как и следующее: $ npm install --global verdaccio
.
Создать свой собственный реестр еще никогда не было так просто! Давайте ознакомимся с наиболее важными функциями этого инструмента:
- Он поддерживает формат реестра npm, включая функции частного пакета, поддержку области применения, контроль доступа к пакетам и аутентификацию пользователей в веб-интерфейсе.
- Он предоставляет возможности для подключения удаленных реестров и возможность перенаправлять каждую зависимость в разные реестры и кэшировать архивные файлы. Чтобы уменьшить количество повторяющихся загрузок и сэкономить трафик на локальных серверах разработки и CI, вы должны проксировать все зависимости.
- В качестве поставщика аутентификации по умолчанию используется htpasswd, но также поддерживаются Gitlab, Bitbucket, LDAP. Вы также можете использовать свой собственный.
- Его легко масштабировать, используя другого поставщика хранилища.
- Если ваш проект основан на Docker, лучшим выбором будет использование официального образа.
- Он обеспечивает действительно быструю загрузку в тестовых средах и удобен для тестирования больших проектов с монорепозиториями.
При обнаружении уязвимостей в системе безопасности они представляют потенциально серьезную угрозу, если становятся достоянием общественности без предварительного предупреждения или соответствующих мер по исправлению положения для пользователей, которые не могут защитить себя.
Исследователям безопасности рекомендуется следовать программе ответственного раскрытия информации, которая представляет собой набор процессов и руководящих принципов, направленных на установление связи между исследователями и поставщиком или сопровождающим уязвимого актива, чтобы донести информацию об уязвимости, ее влиянии и применимости. После правильной сортировки уязвимости поставщик и исследователь согласовывают исправление и дату публикации уязвимости, чтобы обеспечить возможность обновления или устранения уязвимости для затронутых пользователей до того, как проблема безопасности станет достоянием общественности.
В октябре 2017 года npm официально объявила о поддержке двухфакторной аутентификации (2FA) для разработчиков, использующих реестр npm для размещения своих пакетов с закрытым и открытым исходным кодом.
Несмотря на то, что 2FA поддерживается в реестре npm уже некоторое время, его, похоже, медленно внедряют. Одним из примеров является инцидент с eslint-scope в середине 2018 года, когда украденный аккаунт разработчика в команде ESLint привел к публикации malicious version of eslint-scope плохими субъектами.
Включение 2FA - это простой и существенный шаг в пользу лучших практик обеспечения безопасности npm. Реестр поддерживает два режима включения 2FA в учетной записи пользователя:
- Только авторизация - когда пользователь входит в npm через веб—сайт или интерфейс командной строки или выполняет другие действия, такие как изменение информации профиля.
- Авторизация и режим записи - действия с профилем и входом в систему, а также действия с записью, такие как управление токенами и пакетами, и незначительная поддержка информации о команде и видимости пакетов.
Подготовьте приложение для проверки подлинности, такое как Google Authentication, которое вы можете установить на мобильное устройство, и вы готовы приступить к работе. Один из простых способов начать использовать расширенную защиту 2FA для своей учетной записи - это воспользоваться пользовательским интерфейсом npm, который позволяет очень легко ее включить. Если вы работаете с командной строкой, также легко включить 2FA при использовании поддерживаемой версии клиента npm (>=5.5.1).:
npm profile enable-2fa auth-and-writes
Следуйте инструкциям командной строки, чтобы включить 2FA и сохранить коды экстренной аутентификации. Если вы хотите включить режим 2FA только для входа в систему и изменения профиля, вы можете заменить авторизация и запись
на только для авторизации
в приведенном выше коде.
Каждый раз, когда вы входите в систему с помощью npm CLI, для вашего пользователя генерируется токен, который аутентифицирует вас в реестре npm. Токены упрощают выполнение действий, связанных с реестром npm, во время CI и автоматизированных процедур, таких как доступ к закрытым модулям в реестре или публикация новых версий на этапе сборки.
Токенами можно управлять через веб-сайт реестра npm, а также с помощью клиента командной строки npm. Ниже приведен пример использования интерфейса командной строки для создания токена только для чтения, который ограничен определенным диапазоном IPv4-адресов:
npm token create --read-only --cidr=192.0.2.0/24
Чтобы проверить, какие токены созданы для вашего пользователя, или отозвать токены в экстренных случаях, вы можете использовать npm token list
или отзыв токена npm
соответственно.
Убедитесь, что вы следуете рекомендациям по безопасности npm, защищая и сводя к минимуму риск использования ваших токенов npm.
Присвоение имени модулю - это первое, что вы можете сделать при создании пакета, но перед определением окончательного имени npm определяет некоторые правила, которым должно соответствовать имя пакета:
- Оно должно содержать не более 214 символов
- Оно не может начинаться с точки или подчеркивания
- В названии не должно быть заглавных букв
- В конце не должно быть пробелов
- Только строчные буквы
- Некоторые специальные символы недопустимы: “~\’!()*”)’
- Не может начинаться с . или _
- Не удается использовать node_modules или значок.сроки проведения ico запрещены
- Даже если вы соблюдаете эти правила, имейте в виду, что npm использует механизм обнаружения нежелательной почты при публикации новых пакетов на основе оценки и того, нарушает ли название пакета условия предоставления услуги. В случае нарушения условий реестр может отклонить запрос.
Тайпосквоттинг - это атака, основанная на ошибках пользователей, таких как опечатки. С помощью тайпсквоттинга злоумышленники могут публиковать вредоносные модули в реестре npm с именами, которые очень похожи на существующие популярные модули.
Мы отслеживали десятки вредоносных пакетов в экосистеме npm; они также были обнаружены в реестре PyPI на Python. Возможно, некоторые из наиболее популярных инцидентов были связаны с перекрестной обработкой, потоком событий и eslint-областью видимости.
Одной из основных целей для атак с использованием опечаток являются учетные данные пользователя, поскольку любой пакет имеет доступ к переменным среды через глобальную переменную process.env. Другие примеры, которые мы видели в прошлом, включают случай с event-stream, когда атака была нацелена на разработчиков в надежде на внедрение вредоносного кода в исходный код приложения.
Завершают наш список десяти рекомендаций по обеспечению безопасности npm следующие советы по снижению риска подобных атак:
- Будьте особенно осторожны при копировании инструкций по установке пакета в терминал. Обязательно проверьте в репозитории исходного кода, а также в реестре npm, что это действительно тот пакет, который вы собираетесь установить. Вы можете проверить метаданные пакета с помощью
npm info
, чтобы получить больше информации об авторах и последних версиях. - По умолчанию в вашей повседневной работе используется пользователь npm, вышедший из системы, чтобы ваши учетные данные не были слабым местом, которое может легко привести к компрометации вашей учетной записи.
- При установке пакетов добавляйте
--ignore-scripts
, чтобы снизить риск выполнения произвольных команд. Например:npm install my-malicious-package --ignore-scripts