Лучшие практики безопасности npm
Экосистема npm является крупнейшим реестром пакетов в мире, и этот масштаб делает её высокоценной целью. Атаки вроде Shai-Hulud, event-stream и eslint-scope продемонстрировали одну и ту же неприятную истину: установка пакета может выполнить произвольный код на вашей машине ещё до того, как вы прочитаете хотя бы одну строку его исходного кода. Эти лучшие практики безопасности npm помогут вам снизить этот риск на каждом этапе — установке, разработке и публикации.
Ключевые выводы
- Отключите post-install скрипты глобально и добавьте в белый список только те пакеты, которым они действительно необходимы.
- Установите период ожидания для новых релизов, чтобы совершенно новые (и потенциально вредоносные) версии никогда не попадали в ваши сборки автоматически.
- Всегда фиксируйте lockfile в системе контроля версий и используйте
npm ciв CI-конвейерах для воспроизводимых, защищённых от подмены установок. - Защитите учётные записи мейнтейнеров с помощью 2FA на основе WebAuthn и публикуйте через OIDC trusted publishing, чтобы исключить долгоживущие токены.
Почему безопасность цепочки поставок npm важна сейчас
Атаки на цепочку поставок эксплуатируют не ваш код. Они эксплуатируют ваше доверие к чужому коду. Когда скомпрометированный пакет попадает в ваш node_modules, он может украсть учётные данные, извлечь переменные окружения или распространиться дальше. Один только червь Shai-Hulud привёл к удалению более 500 пакетов из реестра в рамках одного инцидента. Сканирование уязвимостей само по себе не поймает этот класс атак — вам нужна эшелонированная защита.
Безопасное управление зависимостями: укрепите свои установки
Отключите post-install скрипты
Post-install скрипты — наиболее распространённый вектор атак в цепочке поставок npm. Отключите их глобально:
npm config set ignore-scripts true
npm config set allow-git none # npm CLI 11.10.0+
Настройка allow-git=none важна, потому что зависимость на основе git может поставляться со своим собственным .npmrc, который незаметно повторно включает lifecycle-скрипты, полностью обходя ignore-scripts.
Если вы используете pnpm, версия 10+ отключает post-install скрипты по умолчанию. Используйте pnpm-workspace.yaml для явного добавления в белый список пакетов, которым они действительно необходимы:
allowBuilds:
esbuild: true
core-js: false
Включите strictDepBuilds: true, чтобы превратить любой непроверенный build-скрипт в блокирующую CI ошибку, а не в тихое предупреждение. Bun также блокирует post-install скрипты по умолчанию, с возможностью включения через trustedDependencies в package.json.
Когда вам действительно нужны lifecycle-скрипты, используйте @lavamoat/allow-scripts для создания проверяемого белого списка вместо глобального включения скриптов.
Добавьте период ожидания для новых релизов
Вредоносные пакеты часто обнаруживаются и удаляются в течение нескольких часов или дней. Пропуск совершенно новых версий даёт сообществу время обнаружить проблемы до того, как они дойдут до вас:
npm config set min-release-age 3
Это указывает npm игнорировать любую версию пакета, опубликованную менее трёх дней назад. Для автоматизированных обновлений зависимостей такие инструменты, как Renovate и Dependabot, поддерживают эквивалентные настройки minimumReleaseAge.
Фиксируйте lockfile и используйте npm ci
Всегда фиксируйте package-lock.json в системе контроля версий. В CI-окружениях замените npm install на:
npm ci
npm ci устанавливает исключительно из lockfile, завершается с ошибкой при любом несоответствии и никогда не разрешает другую версию незаметно. Это основа воспроизводимых, безопасных сборок в автоматизированных конвейерах.
Не обновляйте вслепую
npm audit и npm outdated — полезные сигналы, но рассматривайте их как один из источников информации, а не как полное решение. Перед обновлением любой зависимости просмотрите changelog. Избегайте массовых обновлений, которые пропускают этот шаг — каждое обновление версии является потенциальным изменением поверхности атаки.
Discover how at OpenReplay.com.
Безопасные рабочие процессы npm для мейнтейнеров пакетов
Включите 2FA — и перейдите на WebAuthn
Захват учётных записей — основной механизм атак на цепочку поставок в реестре. Включите 2FA для вашей учётной записи npm с защитой в режиме записи:
npm profile enable-2fa auth-and-writes
GitHub всё больше поощряет использование passkeys и аутентификации на основе WebAuthn, которые значительно более устойчивы к фишингу, чем традиционная 2FA на основе TOTP. Аппаратный ключ или passkey гораздо сложнее украсть с помощью фишинга, чем TOTP-код, поэтому переход на них стоит сделать как можно раньше.
Публикуйте с помощью Trusted Publishing (OIDC)
Долгоживущие npm-токены — это уязвимость. Trusted publishing через OIDC позволяет GitHub Actions или GitLab CI аутентифицироваться напрямую в npm, используя краткосрочные учётные данные с ограниченной областью действия — без необходимости хранить токен. Это также автоматически генерирует attestations provenance (подтверждения происхождения), предоставляя потребителям криптографическое доказательство того, где и как был собран пакет.
Это направление, в котором движется экосистема. GitHub сигнализировал о планах постепенно отказаться от устаревших токенов и сделать trusted publishing путём по умолчанию для автоматизации.
Проверяйте то, что устанавливаете
Не предполагайте, что официальный реестр безопасен. Используйте Socket или npq для проверки пакетов на подозрительное поведение перед установкой. Проверяйте количество загрузок, активность репозитория и историю мейнтейнеров — особенно для пакетов, предложенных AI-ассистентами для программирования, которые могут галлюцинировать названия пакетов, которые затем регистрируют атакующие (техника, называемая slopsquatting).
Заключение
Ни один инструмент не предотвращает все атаки на цепочку поставок npm. Наиболее важные практики являются многоуровневыми: отключайте lifecycle-скрипты, обеспечивайте использование lockfile, добавляйте период ожидания для новых версий, используйте npm ci в CI и переходите на публикацию через OIDC с 2FA. Каждый уровень независимо снижает риск. Вместе они делают ваш рабочий процесс значительно более устойчивым к компрометации.
Часто задаваемые вопросы
Да, некоторым пакетам, таким как esbuild или sharp, требуются post-install скрипты для загрузки платформо-специфичных бинарных файлов. Вместо повторного глобального включения скриптов используйте подход с белым списком через конфигурацию allowBuilds в pnpm или allow-scripts от LavaMoat, чтобы предоставить разрешение только конкретным, доверенным пакетам, которым действительно нужны этапы сборки.
Нет. npm audit проверяет известные уязвимости в опубликованных advisory, но не может обнаружить новые атаки на цепочку поставок, такие как typosquatting, захват учётных записей или вредоносный код, внедрённый в иначе легитимные пакеты. Рассматривайте audit как один полезный сигнал в рамках более широкой стратегии многоуровневой защиты, которая включает обеспечение использования lockfile, ограничения скриптов и инструменты предварительной проверки перед установкой.
npm install читает package.json, разрешает диапазоны зависимостей и может изменять lockfile. npm ci читает только из package-lock.json, устанавливает точные версии и немедленно завершается с ошибкой, если lockfile отсутствует или несовместим с package.json. Всегда используйте npm ci в конвейерах непрерывной интеграции для гарантии воспроизводимых и защищённых от подмены сборок.
Традиционные npm-токены — это долгоживущие секреты, хранящиеся в CI-окружениях, что делает их привлекательными целями для кражи. OIDC trusted publishing генерирует краткосрочные учётные данные с ограниченной областью действия, привязанные к конкретному репозиторию и запуску действия. Никакой секрет нигде не хранится, и каждая операция публикации криптографически связана с её источником, автоматически создавая проверяемые attestations provenance.
Understand every bug
Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.