Security-by-design — это не разовая «галочка» в чек-листе, а управляемый жизненный цикл безопасности: от контроля зависимостей до защиты среды исполнения. В реальных проектах на PHP и Python риски чаще всего рождаются не в собственном коде, а в цепочках поставки (supply chain): уязвимые библиотеки, подмены артефактов, устаревшие версии и незафиксированные зависимости.
Ниже — практическая архитектура для проектов с Composer (PHP) и Poetry (Python), где в CI/PR включены Dependabot и Snyk, а также добавлено runtime-hardening контейнеров. Подход построен так, чтобы обеспечивать управляемость, трассируемость решений и соответствовать актуальным требованиям РФ к защите информации и безопасной разработке.
Правовые ориентиры РФ и как перевести их в технические требования
В РФ требования к защите информации закрепляются несколькими уровнями нормативных актов и практик. На практике компании обычно ориентируются на:
- общие требования к обеспечению безопасности информации при обработке данных;
- требования к управлению доступами, журналированию, контролю целостности и обновлениям;
- организационно-технические меры безопасной разработки и эксплуатации.
Технически это переводится в конкретные инженерные контролы:
- Контроль компонентов: фиксация версий, проверка зависимостей на уязвимости до попадания в релиз.
- Трассируемость: ведение истории изменений (PR), валидация на CI, отчеты сканеров.
- Минимизация привилегий: runtime-hardening контейнеров, запрет небезопасных возможностей.
- Наблюдаемость: логи сборки/сканирования, контроль артефактов.
Отдельно важно: автоматизация не отменяет необходимости внутренней политики безопасной разработки. Сканирование и принудительные правила (fail/allow) должны быть оформлены как часть процессов команды (например, через правила в репозиториях и требования к PR).
Целевая архитектура: supply chain от PR до релиза
Рекомендуемый конвейер:
- Dependabot генерирует PR на обновление зависимостей для Composer/Poetry.
- CI валидирует сборку и запускает сканирование уязвимостей зависимостей (Snyk) + проверяет SBOM/целостность.
- Policy gate: правила блокируют мердж, если обнаружены уязвимости выше допустимого порога или нет сопровождения (например, нет обоснования).
- Артефакт: собирается неизменяемый образ/пакет. Желательно хранить SBOM и результаты сканирования вместе с артефактами релиза.
- Runtime-hardening: контейнер запускается с ограничениями, минимальными правами и безопасными настройками.
Composer: автоматическая проверка зависимостей
Для PHP-проектов используйте зафиксированные зависимости и надежную структуру репозитория:
- composer.json и composer.lock должны быть в Git.
- в CI выполнять composer install строго по lock-файлу (обычно это --no-interaction --prefer-dist + режим без обновлений).
Сканирование уязвимостей Composer-экосистемы удобнее держать в одном месте — через Snyk, а Dependabot использовать для своевременного создания PR.
Poetry: автоматическая проверка зависимостей
Для Python-проектов аналогично фиксируйте зависимости:
- pyproject.toml и poetry.lock должны быть в репозитории.
- в CI устанавливать зависимости из lock-файла (не разрешая обновления на лету).
Dependabot с Poetry-проектами создает PR при обновлениях, а Snyk выполняет проверку уязвимостей по lock-файлу/проекту.
Dependabot: настройка для Composer и Poetry
Dependabot нацелен на поддержание актуальности зависимостей и снижение «технического долга» по безопасности. Его задача — создавать PR, а не принимать решения об исправлениях.
Пример .github/dependabot.yml (универсально, под нужды репозитория):
version: 2
updates:
- package-ecosystem: "composer"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
target-branch: "master"
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
target-branch: "master"Комментарий по Poetry: Dependabot формально опирается на стандартные манифесты. Если в репозитории используется poetry.lock, на практике часто применяют экосистему, соответствующую Python-пакетам (pip) и проверяют, что Dependabot корректно читает lock/манифесты. В ряде случаев целесообразно дополнить настройку запуском Poetry-проверок в CI и сканированием в Snyk, чтобы гарантировать, что фактические зависимости будут оценены независимо от поведения Dependabot.
Snyk: сканирование зависимостей в CI
Ключевой принцип: сканируйте не «теоретический список библиотек», а то, что реально фиксировано в lock-файлах и может быть установлено в build-среде.
Общие требования к CI-gating
- Fail build при критичных/высоких уязвимостях (порог задается политикой).
- Отчетность: публикуйте отчеты сканирования как артефакты CI.
- Проверка только для PR + повтор в релизном пайплайне.
Ниже — пример для GitHub Actions. Аналогично адаптируется под GitLab CI/другие системы.
CI: пример workflow для PHP (Composer + Snyk)
# .github/workflows/security-composer.yml
name: Security Composer
on:
pull_request:
push:
branches: [ "master" ]
jobs:
composer-security:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
tools: composer
- name: Install dependencies
run: composer install --no-interaction --prefer-dist
- name: Snyk test (Composer)
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
run: |
snyk auth $SNYK_TOKEN
snyk test --file=composer.lock --all-projects --severity-threshold=high --fail-on=upgradableПояснения:
- --file=composer.lock: сканируем точную картину зависимостей.
- --severity-threshold: порог блокировки.
- --fail-on — поведение на обнаружениях, требует подстройки под вашу политику.
CI: пример workflow для Python (Poetry + Snyk)
# .github/workflows/security-poetry.yml
name: Security Poetry
on:
pull_request:
push:
branches: [ "master" ]
jobs:
poetry-security:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install Poetry
run: pip install --no-cache-dir poetry
- name: Install dependencies (from lock)
run: |
poetry config virtualenvs.create false
poetry install --no-interaction --no-root
- name: Snyk test (Python)
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
run: |
pip install --no-cache-dir snyk
snyk auth $SNYK_TOKEN
# Snyk CLI для Python-проектов часто использует pyproject/lock.
# Если потребуется уточнение под вашу структуру — закрепите конкретный манифест:
snyk test --file=requirements.txt || true
# Вариант для строгой картины: экспортируйте requirements из Poetry:
poetry export -f requirements.txt --without-hashes -o requirements.txt
snyk test --file=requirements.txt --severity-threshold=high --fail-on=upgradableЗаметка по практике: чтобы гарантировать единообразие, полезно экспортировать зависимости из Poetry в requirements.txt и сканировать именно его в Snyk. Тогда результат будет предсказуем даже если у Snyk есть нюансы интерпретации lock/pyproject.
SBOM: формирование и встраивание в контроль релизов
Для усиления контроля цепочки поставки полезно генерировать SBOM (Software Bill of Materials). На уровне политики это помогает доказуемо ответить на вопросы:
- какие компоненты были в релизе;
- какие версии использовались;
- какие сканы применялись и когда.
Один из практичных вариантов — использовать CycloneDX генерацию в CI. Пример (идея, под конкретные инструменты адаптируйте под ваши технологии):
# SBOM (идея): генерация CycloneDX
# Для Python: можно использовать cyclonedx-bom
pip install --no-cache-dir cyclonedx-bom
cyclonedx-bom -o sbom-python.json -r requirements.txt
# Для PHP: можно подключить соответствующий генератор SBOM в CI
# (выбор зависит от вашего стека инструментов)Важное требование для зрелой безопасности: SBOM должен связываться с артефактами релиза и храниться с результатами Snyk/CI-сканирования.
Управление обновлениями: как правильно разрешать уязвимости
В реальных проектах встречаются ситуации, когда обновление зависимостей невозможно немедленно (несовместимость API, регрессии, требования заказчика). Поэтому заранее определите правила исключений:
- Разрешения на мердж только при наличии описания риска (issue ссылка, план миграции).
- Тайм-бокс для исключений (например, максимум N дней для критичных уязвимостей).
- Повторная проверка при изменениях релевантных файлов (lock-файлы/манифесты).
Технически это реализуется через настройки Snyk (политики severity, suppression) и через требования к PR (шаблоны, mandatory checks).
Runtime-hardening контейнеров: защита среды исполнения
Даже при хорошей защите зависимостей остается риск эксплуатации через уязвимости в runtime-коде, неверные настройки сервиса, утечки секретов или escalation привилегий. Поэтому контейнеры должны быть защищены по принципу наименьших привилегий.
Практики Docker/Kubernetes hardening
- Непривилегированный пользователь: не запускать контейнер от root.
- read-only root filesystem + отдельные writable директории.
- drop capabilities, не добавлять лишние привилегии.
- Запрет privilege escalation (например, allowPrivilegeEscalation=false).
- Ограничение ресурсов (CPU/memory limits) для снижения impact при отказе.
- Секреты — через secrets manager/встроенные механизмы, исключить из образа.
- Сетевая сегментация: минимальные порты/ingress, ограничение egress при возможности.
Пример Dockerfile: минимизация поверхностной атаки
# Пример для PHP (идея; адаптируйте под ваш проект)
FROM php:8.2-fpm-alpine
# Создаем non-root пользователя
RUN addgroup -S app && adduser -S app -G app
WORKDIR /var/www/app
# Копирование без лишних прав
COPY --chown=app:app . /var/www/app
# Убираем возможность записи в корень (в Docker это частично, лучше на уровне runtime)
USER app
# Минимизируем зависимости базового образа — выбирайте slim/alpine обоснованно
# CMD остается стандартным
CMD ["php-fpm", "-F"]Для Python аналогично: использовать slim-образы, создавать non-root пользователя и избегать установки лишних build-утилит в финальном stage (multi-stage build).
Пример Kubernetes SecurityContext
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: myapp
image: myapp:1.0.0
securityContext:
runAsNonRoot: true
runAsUser: 10001
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
volumeMounts:
- name: tmp
mountPath: /tmp
readOnly: false
volumes:
- name: tmp
emptyDir: {}Дополнительно (в зависимости от кластера):
- PodSecurity admission (baseline/restricted);
- NetworkPolicy;
- ограничение serviceAccount, RBAC по принципу минимально необходимых прав.
Связь CI-сканирования и runtime-hardening в единую систему
На практике зрелая система безопасности выглядит так:
- Dependabot делает обновления зависимостей и инициирует PR.
- Snyk в CI оценивает уязвимости и блокирует рискованные мерджи.
- SBOM сохраняется и привязывается к релизному артефакту.
- Контейнеры запускаются с ограничениями, которые исключают типовые сценарии компрометации.
- Все решения документируются в репозитории (PR, отчеты CI), что повышает управляемость и аудитопригодность.
Рекомендуемая матрица контроля (коротко)
| Уровень | Что делаем | Чем подтверждаем |
|---|---|---|
| PR | Dependabot обновляет зависимости | PR в GitHub/GitLab |
| CI | Сборка + Snyk сканирование по lock/requirements | Логи CI, отчеты Snyk, статус checks |
| Релиз | Формирование SBOM, сохранение артефактов | SBOM-файл + результат сканов в хранилище релиза |
| Runtime | Non-root, readOnly FS, drop capabilities, limits | Kubernetes/Docker конфигурация, admission policies |
Типовые ошибки и как их избежать
- Сканирование не того файла: например, требования без фиксации. Решение — сканировать lock/экспорт из lock.
- Разрешение мерджей “по зеленому билду” без checks. Решение — mandatory CI checks и fail on severity.
- Отсутствие исключений в политике: “можно ли пропустить?” — должно быть регламентировано.
- Runtime не защищен: даже идеальные зависимости не исключают неверные настройки контейнеров.
Заключение
Security-by-design для Composer/Poetry — это связка автоматизации обновлений (Dependabot), проверки уязвимостей (Snyk), доказуемого контроля поставки (SBOM) и технической защиты среды исполнения (runtime-hardening контейнеров). Такой подход снижает риски компрометации, ускоряет исправления и делает процесс аудита и управления безопасностью существенно проще.
Если вы хотите внедрить это в действующий CI/CD пайплайн и контейнерный контур — команда РыбинскЛАБ поможет спроектировать архитектуру, настроить политики безопасности, интегрировать Snyk/Dependabot и выполнить hardening контейнеров под ваш инфраструктурный ландшафт.
Обратитесь в РыбинскЛАБ — предлагаем услуги по разработке и внедрению безопасных CI/CD практик.