В эталонной реализации языка Python, CPython, нашлась уязвимость в механизме очистки временных каталогов. Проблему описали в бюллетене Python Software Foundation, организации, которая развивает язык. Состояние гонки в классе TemporaryDirectory из модуля tempfile позволяет подменить вложенный каталог символической ссылкой. Подмена происходит в тот момент, когда библиотека удаляет каталог. После этого очистка выходит за пределы временной области. Файлы в других местах диска удаляются, а их права доступа и файловые атрибуты сбрасываются. Операции идут с правами того процесса, который запустил очистку. Оценка уязвимости по шкале CVSS 4.0 - 5.9. Это средний уровень угрозы. Затронуты выпуски CPython до 3.15.0.
Уязвимость CVE-2026-12345
Временный каталог нужен, чтобы складывать промежуточные файлы и убирать их автоматически. Класс TemporaryDirectory создаёт такой каталог на время работы участка кода. Затем он удаляет каталог вместе со всем содержимым. Удаление идёт рекурсивно: сначала исчезают файлы, потом вложенные каталоги, в конце - сам временный каталог. Между проверкой того, что перед библиотекой обычный каталог, и действием над ним остаётся короткая пауза. В неё и попадает атакующий. Ему достаточно заменить каталог символической ссылкой, ведущей в другое место. Тогда процедура удаления пойдёт по ссылке и примет чужие файлы за своё содержимое. Помимо удаления, очистка умеет сбрасывать права и специальные флаги файлов. Один из таких флагов запрещает изменение или удаление данных. После его сброса защиту файла можно снять и испортить содержимое.
Состояние гонки - это ошибка, при которой результат зависит от порядка выполнения параллельных операций. Здесь всё решает окно между проверкой и действием. Точное совпадение по времени нужно, однако сложность атаки в векторе оценили как низкую. Уязвимость локальная. Злоумышленник должен уже иметь доступ к системе и право менять содержимое дерева каталогов, которое очищается. Удалённо такую атаку не провести. Наибольший риск возникает там, где временные каталоги лежат в общих местах вроде /tmp и доступны разным пользователям или процессам. Второй сценарий - служба с повышенными привилегиями, которая создаёт временное дерево и работает с данными из недоверенного источника. Если процесс удаляет файлы от имени суперпользователя, ущерб выходит за рамки одной учётной записи.
Оценка 5.9 складывается из нескольких параметров. Атака локальная, сложность низкая, участие пользователя не нужно. Влияние на целостность и доступность высокое, на конфиденциальность - нулевое. Данные злоумышленник не читает, зато меняет и уничтожает. Отдельная характеристика требует присутствия атакующего в момент эксплуатации. Это объясняет средний, а не высокий балл. Вслепую атака не сработает: нужно угадать или подгадать момент очистки.
Разработчики указали важную деталь. На платформах, где штатная функция рекурсивного удаления не распознаёт символические ссылки, уязвимость сохраняется. Сброс файловых флагов за пределами временного дерева возможен на всех платформах без исключения. Поведение кода зависит от операционной системы. В бюллетене конкретные системы не перечислены. Сведений о том, что уязвимость уже используют в реальных атаках, нет. Публикация бюллетеня PSF-2026-42 датирована 29 сентября 2026 года. Тогда же обновили запись CVE-2026-12345.
Исправление внесли в основную ветку CPython. Коммит 5c20517a4fc56683efe63a7751020db9573f538d закрывает окно гонки и меняет порядок работы с вложенными объектами. Исправленная версия - 3.15.0. Все более ранние выпуски остаются уязвимыми. Это касается и промежуточных сборок, которые уже используют в работе. Тем, кто ставит Python из дистрибутива, стоит дождаться обновления пакета от сопровождающих. Тем, кто собирает интерпретатор из исходного кода, нужно перейти на версию с правкой. Пока обновление не установлено, полезно ограничить права на запись в каталоги, которые очищает привилегированный код. Размещение временных каталогов в отдельных местах и запрет на доступ посторонних процессов уменьшают возможности злоумышленника. Стоит проверить, какие части приложения удаляют временные деревья и от чьего имени они это делают.
Подобные ошибки лечат, сводя проверку и действие в одну неделимую операцию. Если между ними нельзя встроить свою операцию, подмена не сработает. Для прикладного кода это означает простую вещь: чем меньше прав у процесса, который чистит временные каталоги, тем меньше урона. Отдельная учётная запись для службы, отказ от запуска от имени суперпользователя и закрытые права на каталог сокращают число сценариев атаки.
Стандартная библиотека Python используется в огромном числе приложений. Поэтому ошибка в её коде затрагивает много проектов. Речь не о захвате системы и не об удалённой атаке. Уязвимость портит данные и права доступа, причём незаметно. Потеря файла или сброшенный флаг обнаруживаются не сразу. Последствия зависят от того, что именно удалил процесс. Средний рейтинг CVSS отражает эту двойственность: нужен локальный доступ и совпадение по времени, зато ущерб может быть необратимым. Проблемы с символическими ссылками встречаются в системном коде регулярно. Обновление до 3.15.0 закрывает конкретный случай. Привычка проверять права на временные каталоги остаётся полезной и после установки правки.
Ссылки
- https://www.cve.org/CVERecord?id=CVE-2026-12345
- https://github.com/python/cpython/pull/157580
- https://github.com/python/cpython/issues/157579
- https://github.com/python/cpython/commit/5c20517a4fc56683efe63a7751020db9573f538d
- https://raw.githubusercontent.com/psf/advisory-database/main/advisories/python/PSF-2026-42.json