Code Review и автоматизация
Чек-лист для Code Review
Ревьюер MUST убедиться, что:
XSS и рендеринг
- Не используется вставка контента без санитизации (
dangerouslySetInnerHTML,innerHTMLчерез ref) - При необходимости рендеринга HTML/markdown используется проверенная библиотека санитизации (
dompurify) - Данные из пользовательского ввода, client storage считаются недоверенными
- Применяется whitelist подход для разрешенных тегов
Client-side Storage
- В client-side storage отсутствуют:
- Access tokens / Refresh tokens
- PII (Personally Identifiable Information): email, телефон, адрес
- Секретные ключи / API keys
- Данные платежных карт
- Данные, читаемые из client storage, валидируются (через
zod,yup) - Cookies для токенов имеют флаги:
HttpOnly,Secure,SameSite
Environment Variables
- Клиентские env-переменные (например,
NEXT_PUBLIC_*) не содержат секретов - Секретные ключи используются только на сервере
- Проведена валидация env-переменных при старте приложения
- Не передаются серверные переменные в клиентские компоненты
CSP (Content Security Policy)
- CSP настроен для приложений с пользовательским контентом
- Нет использования
unsafe-inlineилиunsafe-eval - Inline-скрипты используют nonces
-
frame-ancestorsнастроен корректно
Browser APIs
-
postMessageпроверяет origin отправителя - Нет использования wildcard (
*) в targetOrigin - Данные от
postMessageвалидируются через схему - Используется whitelist разрешенных origins
Логирование
- Debug-логи отключены в production
- Токены и PII не логируются
- Source maps не публикуются на production сервере (
productionBrowserSourceMaps: false) - Используется санитизация логов
Зависимости
- Lock-файлы в репозитории и актуальны
-
npm auditне показывает критических уязвимостей - Проверены новые зависимости (активность, размер, лицензия)
- Нет подозрительных lifecycle scripts (
postinstall,preinstall) - Настроены автоматические проверки в CI/CD
Автоматизация проверок
ESLint конфигурация
// .eslintrc.js
module.exports = {
extends: ['next/core-web-vitals'],
rules: {
// ❌ FORBIDDEN: dangerouslySetInnerHTML без явного исключения
'react/no-danger': 'error',
// ❌ FORBIDDEN: eval и new Function
'no-eval': 'error',
'no-implied-eval': 'error',
'no-new-func': 'error',
// ⚠️ Предупреждение о console.log в production
'no-console': ['warn', { allow: ['warn', 'error'] }],
// ❌ FORBIDDEN: небезопасные регулярные выражения
'no-unsafe-regex': 'error',
// ⚠️ SHOULD: Проверка типов
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-unsafe-assignment': 'warn',
},
overrides: [
{
// Более строгие правила для production кода
files: ['src/**/*.ts', 'src/**/*.tsx'],
excludedFiles: ['**/*.test.ts', '**/*.test.tsx', '**/*.stories.tsx'],
rules: {
'no-console': 'error', // Строгий запрет в production
'@typescript-eslint/no-explicit-any': 'error',
},
},
],
};
TypeScript конфигурация
// tsconfig.json
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"alwaysStrict": true,
// Дополнительные проверки
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
}
}
Pre-commit хуки
# Установка husky и lint-staged
npm install -D husky lint-staged
npx husky init
// .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
npm audit --audit-level=high
// package.json
{
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix --max-warnings=0",
"prettier --write"
],
"*.{js,jsx}": [
"eslint --fix --max-warnings=0",
"prettier --write"
],
"package.json": [
"npm audit --audit-level=high"
]
}
}
GitHub Actions
# .github/workflows/security-checks.yml
name: Security Checks
on:
pull_request:
push:
branches: [main, develop]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci --ignore-scripts
- name: Lint check
run: npm run lint
- name: Type check
run: npm run type-check
- name: Security audit
run: npm audit --audit-level=moderate
- name: Check for secrets in code
uses: trufflesecurity/trufflehog@main
with:
path: ./
base: ${{ github.event.repository.default_branch }}
head: HEAD
- name: Run tests
run: npm test
# .github/workflows/dependency-review.yml
name: Dependency Review
on: [pull_request]
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Dependency Review
uses: actions/dependency-review-action@v3
with:
fail-on-severity: moderate
Дополнительные инструменты
Проверка секретов
# .github/workflows/secret-scan.yml
name: Secret Scanning
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: TruffleHog
uses: trufflesecurity/trufflehog@main
with:
path: ./
base: ${{ github.event.repository.default_branch }}
head: HEAD
- name: GitLeaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Проверка бандла
// package.json
{
"scripts": {
"analyze": "ANALYZE=true next build",
"analyze:bundle": "npx bundle-analyzer .next/analyze/client.html"
}
}
// next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
module.exports = withBundleAnalyzer({
// Next.js config
});
SonarQube/SonarCloud
# .github/workflows/sonar.yml
name: SonarCloud Scan
on:
push:
branches: [main]
pull_request:
types: [opened, synchronize, reopened]
jobs:
sonarcloud:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
Контрольный список перед деплоем
Безопасность
- Все токены и секреты только на сервере
- CSP настроен и активен
- Source maps отключены в production
- Debug-логи отключены
-
npm auditне показывает критическ их уязвимостей - HTTPS включен (Secure cookies)
- Rate limiting настроен для API endpoints
Конфигурация
- Environment variables проверены
-
productionBrowserSourceMaps: false - Error boundaries настроены
- Мониторинг ошибок настроен (Sentry)
- Analytics не логирует PII
Производительность
- Bundle size проверен (
npx bundlephobia) - Lazy loading для больших компонентов
- Images оптимизированы (Next.js Image)
- Lighthouse score > 90
Тестирование
- Unit tests покрывают критичную логику
- Integration tests для основных флоу
- E2E tests для критичных путей
- Security headers тестированы
Примеры проверки PR
Комментарии ревьюера
## Security Review
### ✅ Approved:
- Environment variables properly separated
- Input validation added for user data
- CSRF tokens implemented
### ⚠️ Issues Found:
1. **Line 45**: `dangerouslySetInnerHTML` without sanitization
- Recommendation: Use `dompurify` to sanitize HTML before rendering
- Severity: High
2. **Line 78**: Token stored in localStorage
- Recommendation: Move to HttpOnly cookie
- Severity: Critical
3. **Line 120**: Missing origin validation in postMessage
- Recommendation: Add whitelist of allowed origins
- Severity: High
### 📋 Checklist:
- [x] No secrets in code
- [x] Dependencies audited
- [ ] CSP configured (missing)
- [x] Logging sanitized
### 🔧 Action Required:
Please address the critical issues before merge.
Автоматические комментарии
# .github/workflows/pr-comment.yml
name: PR Security Comment
on: pull_request
jobs:
comment:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run audit
id: audit
run: |
npm audit --json > audit-results.json || true
- name: Comment PR
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const audit = JSON.parse(fs.readFileSync('audit-results.json'));
const vulnerabilities = audit.metadata?.vulnerabilities;
if (vulnerabilities?.high > 0 || vulnerabilities?.critical > 0) {
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `⚠️ **Security Alert**: Found ${vulnerabilities.critical} critical and ${vulnerabilities.high} high severity vulnerabilities. Please run \`npm audit fix\` before merging.`
});
}
📌 Ключевые моменты:
- MUST: Code Review обязателен для всех изменений
- MUST: Автоматические проверки в CI/CD
- MUST: ESLint правила для безопасности
- MUST: Pre-commit хуки для ранней проверки
- Блокировка merge при найденных уязвимостях