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

Безопасность и эксплуатация сборщика backport

Инструменты сборки — НЕ зависимость времени выполнения. На этой странице описано, как эксплуатировать конвейер сборки и оценивать доверие к нему. Модель безопасности самого движка Portable Document Format (PDF) описана вместе с движком, а не здесь.

Сборщик преобразует исходный код, который не создаёт сам, и выпускает дистрибутив, разработкой которого не занимается. Его модель безопасности следует из этой границы. Граница доверия проходит по извлечённому исходному коду и набору инструментов. Выпускаемый артефакт доступен только для чтения и создаётся машиной. Разделение лицензий между публичным пакетом и пакетом Pro зафиксировано в коде.

Сборщик принимает исходные репозитории и зафиксированный набор инструментов. Он создаёт производный артефакт. Выполняются три свойства:

  • Сгенерированный дистрибутив доступен только для чтения и создаётся машиной. Он публикуется в виде тегов версий, а не веток этого репозитория. Разработку, отчёты об ошибках и запросы на новые возможности направляйте в исходные репозитории nextpdf/*, но никогда — в сгенерированное дерево. Проверено по блоку предупреждения в README.md проекта и по .github/workflows/build.yml (выпуск фиксирует и помечает тегом сгенерированное дерево с нуля).
  • Область действия токена выпуска узкая. secrets.BACKPORT_TRIGGER_TOKEN разрешает клонирование исходных репозиториев на теге выпуска. Он упоминается только в шагах извлечения исходного кода. Проверено по build.yml (использование GH_TOKEN).
  • Разделение раннеров непрерывной интеграции (CI) сделано намеренно. Доверенные события выполняются на собственных раннерах PHP; запросы на включение из форков и запуски Dependabot принудительно переводятся на раннеры, размещённые в GitHub. Недоверенный код никогда не выполняется в пуле доверенных раннеров. Проверено по .github/workflows/0-ci.yml (условию runs-on).
  • Набор инструментов ограничен в composer.json. Он использует Rector ^2.0, PHPStan ^2.1, PHPUnit ^13.0 и набор symfony/polyfill-*. У сборщика нет зависимости времени выполнения от NextPDF, поэтому скомпрометированный пакет времени выполнения NextPDF не может затронуть сборщик. Проверено по composer.json.
  • Обновления зависимостей выполняются ботом и проходят через контрольные проверки. Присутствуют конфигурация Dependabot и рабочий процесс автослияния. Запуски Dependabot закреплены за раннерами, размещёнными в GitHub, и перед слиянием всё равно проходят полный контроль CI (PHPStan, тесты, пробный прогон). Проверено по .github/dependabot.yml и .github/workflows/0-ci.yml, 9-dependabot-auto-merge.yml.
  • Вывод не содержит состояния сборки. Архив выпуска упаковывается в zip с исключением vendor/ и .git/. Опубликованный артефакт содержит исходный код и сгенерированный манифест, а не собственное дерево зависимостей сборщика. Проверено по build.yml (zip ... -x '*/vendor/*' '*/.git/*').
  • Статический анализ служит контролем для кода сборки. composer analyse запускает PHPStan на уровне 10 для rector/rules и scripts при каждом push и запросе на включение в любую из постоянных веток. Он выполняется перед любым пробным прогоном. Проверено по composer.json и 0-ci.yml.

Сценарий сборки не проверяет синтаксис вывода локально, потому что на хосте сборки работает более новый PHP, чем целевой. Авторитетная проверка находится в рабочем процессе выпуска. После сборки раннер переключается на целевой PHP и запускает php -l по всему output/src, отклоняя выпуск при любой ошибке разбора или фатальной ошибке. Затем артефакт устанавливается и прогоняется по матрице проверки — с PHP 8.1 по 8.4 для линии PHP 8.1 и PHP 7.4 и 8.0 для линии PHP 7.4. Дистрибутив, который целевая среда выполнения отвергла бы, не доходит до выпуска. Проверено по scripts/build.php (validateOutput()) и .github/workflows/build.yml (задания проверки синтаксиса и validate-*).

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

Два создаваемых пакета имеют разные лицензии, зафиксированные в scripts/adjust-composer.php:

ПакетПоле лицензииУстанавливается
nextpdf/backportApache-2.0generatePublicComposer()
nextpdf/backport-proproprietarygenerateProComposer()

Сам репозиторий сборщика распространяется под Apache-2.0 (composer.jsonlicense). Его CHANGELOG.md фиксирует прежнюю смену лицензии с LGPL-3.0-or-later на Apache-2.0. Версии, опубликованные до этого изменения, остаются под прежней лицензией и доступны для загрузки, а каждая новая версия выпускается под Apache-2.0. Дистрибутив Pro является проприетарным, создаётся только для целевой версии PHP 8.1 и требует phpseclib/phpseclib ^3.0. Проверено по CHANGELOG.md, composer.json и scripts/adjust-composer.php.

Что гарантирует конвейер в пределах того, что обеспечивает код:

  • Остановка при первом сбое. Сборка прерывается на первом сбойном этапе с именованной ошибкой. Неполный дистрибутив никогда не выпускается, потому что задания выпуска зависят от успешной сборки и проверки. Проверено по scripts/build.php (step()) и заданию build.yml (needs).
  • Последовательные сборки. Группа параллелизма backport-build с cancel-in-progress: false не позволяет двум выпускам исходного кода конкурировать за один и тот же тег выпуска. Проверено по build.yml.
  • Воспроизводимые входные данные. Перед сборкой конвейер клонирует каждый исходный репозиторий на точном теге выпуска. Проверено по build.yml (--branch "${TAG}").

Что он не заявляет:

  • Он не удостоверяет соответствие стандартам, полную совместимость версий PHP или корректность преобразованной программы за пределами принятия синтаксиса и набора тестов.
  • Понижение версии убирает неизменяемость, обеспечиваемую средой выполнения (удаление readonly). Код, который полагался на то, что среда выполнения отклоняет запись в свойство readonly, теряет эту защиту в выводе с пониженной версией. Это задокументированный, намеренный компромисс ради безопасности clone-with — см. /integrations/backport/troubleshooting/.

Проблемы безопасности в сборщике обрабатываются по SECURITY.md репозитория: сообщайте о них через GitHub Security Advisory или контакт по безопасности, а не через публичную задачу. Задачи по сгенерированному коду заводите в исходных репозиториях, потому что сгенерированное дерево создаётся машиной и разработка под него не ведётся. Проверено по SECURITY.md и README.md проекта.

  • /integrations/backport/overview/ — что такое сборщик и что он создаёт.
  • /integrations/backport/production-usage/ — как эксплуатировать конвейер выпуска.