Вы подозреваете, что в файле setup.cfg появился чужой код, или просто хотите убедиться, что проект чист. Файл конфигурации сборки — не самое очевидное место для атаки, но именно поэтому его используют: он запускается при установке пакета, и никто особо не смотрит внутрь. Разберёмся, как найти вредоносный скрипт, не переустанавливая весь проект с нуля.
- Почему именно setup.cfg становится мишенью
- Где искать подозрительное: анатомия файла
- Секция [options] и параметры установки
- Секция [options.entry_points]
- Секции сторонних инструментов
- Пошаговый алгоритм проверки
- Инструменты для автоматизированного анализа
- Красные флаги: что должно насторожить
- Частые ошибки при проверке
- Что делать, если нашли подозрительное
- Сценарии действий в зависимости от ситуации
- Как предотвратить проблему в будущем
- Итог
Почему именно setup.cfg становится мишенью
В типичном Python-проекте setup.cfg управляет метаданными пакета, зависимостями и параметрами сборки. Он читается инструментами вроде setuptools, pytest, mypy и десятками других. Проблема в том, что некоторые из этих инструментов позволяют выполнять произвольные команды при чтении конфигурации. Злоумышленник, получивший доступ к репозиторию или к пакету в прокси-зеркале, может вставить секцию, которая при установке пакета запустит код на машине жертвы.
Реальные векторы атак через setup.cfg:
- Инъекция в секцию
[options]с подменой скриптов установки - Внедрение в секции плагинов (
[tool:pytest],[mypy]и т.п.) с выполнением кода при запуске утилит - Подмена путей к entry points, чтобы при установке пакета регистрировался вредоносный консольный скрипт
- Использование директив
setup_requiresдля загрузки и выполнения кода до начала установки
Где искать подозрительное: анатомия файла
Прежде чем искать «вирус», нужно понимать, как выглядит нормальный setup.cfg. Вот типичная структура без вредоносных вставок:
[metadata]
name = my-project
version = 1.2.3
description = A useful library
author = Developer Name
[options]
packages = find:
python_requires = >=3.8
install_requires =
requests>=2.28
click>=8.0
[options.entry_points]
console_scripts =
mytool = mypackage.cli:main
Теперь разберём, какие именно места файла чаще всего модифицируют и на что смотреть.
Секция [options] и параметры установки
Обратите внимание на параметры, которые могут запускать код:
setup_requires— список пакетов, которые pip попытается установить перед чтением остальной конфигурации. Если здесь появился незнакомый пакет — это красный флаг.install_requires— зависимости при установке. Подозрительны пакеты с опечатками в названиях популярных библиотек (например,reqeustsвместоrequests).scripts— пути к исполняемым скриптам. Если указан файл, которого нет в репозитории, или путь ведёт в неожиданное место — проверьте.
Секция [options.entry_points]
Entry points — это то, что превращает Python-пакет в консольную команду. Злоумышленник может добавить новую точку входа, которая запускает вредоносный скрипт при установке пакета:
[options.entry_points]
console_scripts =
mytool = mypackage.cli:main
hidden_backdoor = malicious_pkg.runner:execute
Вторая строка — пример того, как выглядит инъекция. Незнакомое имя команды и подозрительный модуль — повод разобраться.
Секции сторонних инструментов
Многие инструменты читают собственные секции из setup.cfg. Вредоносный код может быть спрятан в секциях для:
[tool:pytest]— выполнение при запуске тестов[mypy]— запуск при проверке типов[flake8],[pylint]— при статическом анализе[isort],[black]— при форматировании
Любая секция, которая запускает код при чтении конфигурации, потенциально опасна. Ищите в таких секциях параметры, принимающие строки с кодом или пути к скриптам.
Пошаговый алгоритм проверки
Вот конкретная последовательность действий, которую можно выполнить даже без специальных инструментов безопасности.
- Сравните с эталоном. Если проект открытый — скачайте официальный
setup.cfgиз репозитория и выполнитеdiff. Если закрытый — сравните с последней известной версией из системы контроля версий. - Проверьте все entry points. Откройте секцию
[options.entry_points]и для каждой точки входа убедитесь, что модуль существует в проекте и содержит ожидаемую функцию. - Просмотрите зависимости. Пройдитесь по списку
install_requiresиsetup_requires. Для каждого пакета проверьте, что он действительно нужен проекту и что название не содержит опечаток. - Ищите скрытые секции. В
setup.cfgмогут быть секции, которые вы не добавляли. Просмотрите весь файл и проверьте каждую секцию квадратных скобок. - Проверьте наличие исполняемых файлов. Если в
setup.cfgуказаны скрипты (scriptsилиentry_points), найдите эти файлы в проекте и проверьте их содержимое. - Запустите в изолированной среде. Установите пакет в чистое виртуальное окружение и посмотрите, какие файлы были созданы, какие команды запущены.
Инструменты для автоматизированного анализа
Ручной просмотр работает для маленьких проектов, но в реальности нужны инструменты. Вот что действительно помогает:
| Инструмент | Что проверяет | Как использовать | Уровень сложности |
|---|---|---|---|
pip-audit |
Известные уязвимости в зависимостях | pip-audit -r requirements.txt |
Простой |
safety |
Уязвимости в установленных пакетах | safety check |
Простой |
bandit |
Небезопасные конструкции в Python-коде | bandit -r ./src |
Средний |
pyroma |
Корректность метаданных пакета | pyroma . |
Простой |
check-python-version |
Соответствие заявленных и реальных версий | Ручная проверка по выводу pip install |
Простой |
diff против эталона |
Любые изменения в файле | diff setup.cfg reference_setup.cfg |
Простой |
Отдельно стоит упомянуть pip install --dry-run (доступен в pip 22.2+). Он показывает, что будет установлено, без реальной установки. Полезно для быстрой проверки зависимостей.
Красные флаги: что должно насторожить
Вот конкретные признаки, при которых стоит остановиться и разобраться глубже:
- В файле появились секции, которые вы не создавали, особенно с названиями вроде
[tool:unknown]или[custom] - В
install_requiresесть пакеты, не упомянутые в документации проекта - Entry points ведут к модулям, которых нет в исходном коде
- В секциях инструментов указаны пути к файлам вне проекта (
/tmp/,C:\Users\) - Файл содержит строки с вызовами
eval(),exec(),os.system(),subprocess— вsetup.cfgэто не имеет смысла - Размер файла неожиданно вырос по сравнению с предыдущей версией
- В файле есть закомментированные строки с подозрительным кодом — иногда злоумышленники оставляют «спящие» вставки
Частые ошибки при проверке
Даже опытные разработчики допускают одни и те же промахи при аудите setup.cfg:
- Проверяют только секцию [metadata]. Метаданные относительно безопасны — основная атака идёт через
[options]и entry points. - Игнорируют секции сторонних инструментов. Если вы не используете mypy, секция
[mypy]в файле не должна быть. Любая незнакомая секция — подозрительна. - Не проверяют транзитивные зависимости. Вредоносный код может быть не в основном пакете, а в одном из его зависимых пакетов. Проверяйте всю цепочку.
- Слепо доверяют файлам из форков. Если вы форкнули чужой проект, его
setup.cfgмог быть модифицирован до вашего форка. - Не изолируют при тестировании. Установка подозрительного пакета в системный Python — плохая идея. Используйте virtualenv или контейнер.
Что делать, если нашли подозрительное
Нашли что-то странное в setup.cfg? Не паникуйте, но действуйте методично:
- Не запускайте
pip installдля этого пакета в текущем окружении. - Сохраните копию файла для анализа — зафиксируйте контрольную сумму.
- Проверьте остальные файлы проекта — если модифицировали
setup.cfg, могли затронуть иsetup.py,pyproject.toml, скрипты вbin/. - Сообщите maintainer проекта или в службу безопасности вашей организации.
- Заблокируйте установку пакета в вашей системе сборки, пока не разберётесь.
Сценарии действий в зависимости от ситуации
Если вы — разработчик проекта и нашли подозрительное в своём файле: Откатите изменения через git, проверьте историю коммитов на предмет несанкционированных изменений, обновите зависимости, опубликуйте чистую версию. Если проект публичный — уведомите пользователей о компрометации.
Если вы — пользователь чужого пакета и чтото выглядит странным: Не устанавливайте пакет. Сообщите автору проекта. Если пакет критичен — установите в изолированную среду и проанализируйте поведение (сетевые соединения, файловые операции).
Если вы — DevOps/SRE и пакет уже установлен в production: Проверьте логи на предмет необычных действий в момент установки. Запустите проверку целостности файлов. При подтверждении компрометации — откатитесь на чистую версию и заблокируйте установку скомпрометированного пакета.
Как предотвратить проблему в будущем
Лучшее лечение — профилактика. Вот что реально работает:
- Фиксируйте зависимости с контрольными суммами. Используйте
pip-compileиз pip-tools с хешами илиpoetry lock— это не даст подменить пакет незаметно. - Проверяйте файлы перед коммитом. Настройте pre-commit хук, который проверяет
setup.cfgна наличие подозрительных секций. - Используйте изолированные окружения для сборки. Docker-контейнер или чистый virtualenv — не дадут вредоносному коду повлиять на систему.
- Регулярно аудитируйте зависимости. Запускайте
pip-auditилиsafetyпо расписанию, хотя бы раз в неделю. - Ограничьте источники пакетов. Используйте только проверенные индексы и прокси-серверы с подписью пакетов.
Итог
Вредоносный скрипт в setup.cfg — это не теория, а реальный вектор атак, который эксплуатирует доверие к процессу установки пакетов. Чтобы обнаружить проблему:
- Сравнивайте текущий файл с эталоном
- Проверяйте все entry points и зависимости
- Ищите незнакомые секции и подозрительные пути
- Используйте
pip-audit,banditиdiffдля автоматизации - Никогда не устанавливайте подозрительные пакеты без изоляции
Если нашли подозрительное — не устанавливайте пакет, сохраните доказательства и сообщите ответственному за проект. Предотвратить проще, чем чинить: фиксируйте зависимостей с хешами, изолируйте сборку и регулярно аудитируйте проект.
