
Имя пакета в реестре часто оказывается первым сигналом того, что компоненту можно доверять. Разработчик видит название вроде google-cloud-storage, opentelemetry-sdk или apache-airflow-providers-slack раньше, чем открывает исходный код, и ожидает, что знакомый префикс указывает на известный проект. В PyPI это ожидание пока ничем не подтверждено: реестр формально не связывает общее начало имени с его владельцем, поэтому любой свободный вариант может зарегистрировать посторонний пользователь.
В конце июня 2026 года в Python‑сообществе приняли PEP 752 (мы писали об этом здесь). Он предлагает закреплять за организацией не отдельные имена, а префикс и все будущие проекты, которые ему соответствуют. Если PyPI реализует этот механизм, то пакет с именем вроде «google‑cloud‑new‑service» сможет опубликовать только та организация, которой принадлежит право на этот префикс или которой разрешили пользоваться этим правом. На первый взгляд, решение очевидное. Однако общий префикс не всегда означает, что все пакеты принадлежат одному издателю. Иногда он обозначает семейство официальных библиотек, а иногда экосистему сторонних дополнений.
Меня зовут Артем Максимов, я отвечаю за аналитику продуктов в CodeScoring. Вместе с дата‑инженером Артемом Ивановым в этой статье мы разбираемся, какую проблему решает PEP 752, где проходит его граница и что нам показывает база данных CodeScoring.
Почему знакомый префикс не подтверждает издателя
В PyPI есть организации (как тип учетной записи), но они не входят в имя пакета и не резервируют его часть. Сами имена лежат в плоском пространстве, то есть название либо свободно, либо занято. В npm область входит в имя пакета, например @scope/package. Поэтому google-cloud-storage и google-cloud-new-service для реестра остаются двумя независимыми проектами. Общее начало имени пока ничего нам не доказывает.
Некоторые компании уже публикуют пакеты‑заглушки, чтобы заранее занять внутренние названия в PyPI. Аккаунту yandex-bot принадлежат более 300 таких пакетов с префиксом yandex‑, а seznam‑bot управляет более чем 400 пакетами с префиксом szn‑. В описании пакета Яндекса и пакета Seznam прямо сказано, что они нужны для защиты от dependency confusion. Вместо одного правила для префикса компаниям приходится публиковать сотни отдельных пакетов.
Никакого отдельного согласования публикация заглушек не требует. Это удобно для публикации, но одновременно создает простор для атак на имена пакетов. Злоумышленнику не нужно подделывать существующий проект, если он может выпустить новый с узнаваемым началом и рассчитывать на доверие пользователя, документации или автоматизированной подсказки. В PEP 752 среди уязвимых семейств названы google-cloud-, opentelemetry-, apache-airflow-providers- и types-.
Такой сценарий не сводится только к опечаткам. Разработчик может правильно прочитать имя google-cloud-foo, но ошибочно решить, что оно относится к официальной линейке Google. В нашей статье об атаках на цепочку поставки ПО этот класс рисков мы относили к неймсквоттингу и подмене доверия через имя пакета.
Что именно меняет PEP 752
В PEP закрепление за организацией префикса и всех связанных с ним имен называют «неявным пространством имен» (implicit namespaces). Далее в статье мы будем называть такой префикс «защищенным», потому что это точнее передает практическую механику.
Право на префикс google-cloud распространяется на сам проект с этим именем и на названия, которые начинаются с google-cloud-. При этом google-cloudstorage под правило не попадает. Сопоставление идет по нормализованному имени пакета, поэтому точки и подчеркивания также учитываются. Например, google.cloud.storage будет приведен к виду google-cloud-storage и окажется в том же семействе. Правила нормализации описаны в спецификации имен проектов Python.
Имя проекта |
Попадает под право на google‑cloud |
Почему |
google‑cloud |
Да |
Совпадает с именем префикса |
google‑cloud‑storage |
Да |
После префикса стоит дефис |
google.cloud.storage |
Да |
После нормализации это google‑cloud‑storage |
google‑cloudstorage |
Нет |
Дефиса после префикса нет |
gooogle‑cloud‑storage |
Нет |
Это другое имя, даже если оно похоже на исходное |
Если проект совпадает с защищенным префиксом, а издатель не получил на него право, реестр должен отклонить публикацию с ошибкой 409 Conflict. Для уже существующих проектов PEP рекомендует предусмотреть исключение, чтобы их владельцы могли продолжать выпускать новые версии. Тем самым PEP защищает будущие названия, не ломая уже опубликованные пакеты. Менеджерам пакетов вроде pip не придется менять синтаксис зависимостей, поскольку имена пакетов для пользователя останутся прежними. Все эти правила можно изучить в разделах Semantics, Uploads и Backwards Compatibility PEP 752.
У реестра появятся и новые метаданные. Ответ API проекта сможет сообщать, к какому защищенному префиксу он относится и принадлежит ли проект владельцу этого префикса. PEP прямо предусматривает политику на стороне установщика. Корпоративный прокси тоже сможет использовать этот сигнал, если в него добавят поддержку новых метаданных. Например, разрешать пакеты с google-cloud- только при подтвержденной связи с владельцем префикса. Сам PEP описывает эту возможность как будущую политику клиента, а не как поведение, которое автоматически появится во всех инструментах.
Почему префикс не всегда указывает на одного владельца
Самая интересная часть нововведений не в проверке дефиса — с этим всё достаточно просто. Сложнее отличить группу пакетов одного издателя от общего соглашения, которым пользуется сообщество.
В первом случае префикс работает как название продуктовой линейки. У Google есть google-cloud-*, у Apache Airflow — apache-airflow-providers-* и так далее. Если кто‑то публикует новую библиотеку с таким началом, то пользователь ожидает связь с соответствующим проектом. В этом случае ограничение новых публикаций действительно снижает риск.
Во втором случае общий префикс служит соглашением внутри экосистемы расширений. Например, официальный каталог pytest собирает плагины из PyPI прежде всего по префиксам pytest‑ и pytest_, хотя сам pytest обнаруживает установленные дополнения через entry point pytest11, а не по имени пакета. Такой префикс помогает найти дополнение, но не означает, что у всех пакетов один владелец. Запрет публикаций под таким префиксом может защитить имя, но одновременно перекрыть привычный путь для новых дополнений. В проекте PEP 755 предусмотрено, что владелец права сможет разрешать публикации другим организациям, но окончательный порядок еще не принят.
Что показал срез PyPI
Мы хотели понять, часто ли пакетами с одинаковым началом имени управляет один владелец. Для этого сопоставили более 800 тысяч действующих проектов из базы CodeScoring с данными ownership PyPI. Владельцем считали организацию PyPI или аккаунт с ролью Owner. Поле author не учитывали, потому что оно не дает права управлять проектом. Если владельцев несколько, то проект учитывали у каждого.
Для сравнения мы взяли шесть знакомых префиксов, упомянутых в PEP 752. В этот набор вошли aws-, google-, azure-, apache-, opentelemetry- и types-. Ни один из них не принадлежит одному владельцу. Пакетами с aws- управляют 743 учетные записи и организации. У google- владельцев 484, у types- их 68.

Часть названий выпускают сторонние разработчики. Но и крупнейший аккаунт не обязательно представляет ожидаемый проект. У types‑ около 71% пакетов принадлежат vemel, автору генератора mypy-boto3-builder, а не Typeshed. В группе aws- крупнейший аккаунт называется CoreOxide, а не Amazon. Знакомое начало помогает понять, к какой экосистеме относится пакет, но не подтверждает издателя.
Даже если одному владельцу принадлежит большинство пакетов, это не значит, что публикации под этим префиксом стоит разрешить только ему. Саймон Уиллисон управляет 187 из 318 пакетов с префиксом datasette-, но еще 131 пакет принадлежит 47 другим владельцам. Datasette позволяет выпускать расширения отдельными Python‑пакетами, и в экосистеме есть каталог таких плагинов. Если смотреть только на долю крупнейшего владельца, префикс выглядит централизованным. На практике резервирование без разрешений для внешних авторов закрыло бы уже работающий канал расширений.
Здесь важна не сама длина префикса, а то, насколько точно он описывает конкретную экосистему. Для Google переход от google- к google-cloud- отделяет проекты Google от большей части соседних пакетов. У Azure похожий эффект дает azure-mgmt-. В случае OpenTelemetry уточнение до opentelemetry-instrumentation- почти не меняет распределение владельцев. Поэтому одинаковое правило по числу фрагментов не сработает. Это значит, что границу нужно выбирать по устройству конкретной экосистемы.

Срез помогает выбрать разумную границу префикса, но не доказывает право на имя. PEP 752 задает общий механизм, а порядок выдачи прав для PyPI пока остается в черновике PEP 755.
Кому PyPI собирается выдавать права
В текущем проекте PEP 755 подать заявку можно только от учетных записей организаций. Префикс должен быть длиннее трех символов, ясно указывать на заявителя и уже использоваться им. Для слишком общих слов вроде tool или apps заявку предполагается отклонять. От заявителя также ждут объяснения, почему отсутствие резервирования создает путаницу или иной риск для сообщества.
Документ отдельно перечисляет большие открытые проекты, университеты, государственные и некоммерческие организации как возможных заявителей без платной учетной записи. При этом заявки платных организаций планируется рассматривать быстрее — как способ справиться с ограниченным числом людей, которые будут проверять заявки. В финальной политике PyPI этот пункт еще может измениться.
Почему PyPI не копирует npm
В npm для подобных кейсов давно есть явные области имен. Пакет @google-cloud/storage сразу содержит имя организации в синтаксисе зависимости. PEP 752 выбрал другой путь и сохраняет привычный для Python плоский формат имени, добавляя право на часть уже существующего названия.
У такого решения есть очевидный плюс — не нужно менять pip, файлы зависимостей, IDE и инструменты анализа, а старые пакеты не приходится переименовывать. В обосновании PEP 752 авторы отдельно отмечают, что попытка ввести npm‑подобный синтаксис поверх плоского пространства имен создала бы путаницу между foo-bar и условным @foo/bar, а также затронула бы всю цепочку инструментов.
Но за совместимость приходится платить менее строгой моделью. Префикс остается частью обычного имени проекта, а не отдельным элементом синтаксиса зависимости. Поэтому контроль включается при публикации, а новые метаданные смогут использовать только те клиенты, которые добавят соответствующую проверку.
От каких атак префикс действительно защищает
PEP 752 хорошо закрывает один конкретный случай. Злоумышленник не сможет первым занять новое правдоподобное имя внутри уже защищенной официальной линейки. В сценарии google‑cloud‑<название будущей интеграции> реестр заблокирует пакет до публикации, и до поиска проблем после установки дело не дойдет.
Однако из этого не следует, что все атаки на имена исчезнут. Пакет gooogle-cloud-storage не совпадет с защищенным google-cloud и по‑прежнему останется предметом проверки на опечатку. Не поможет PEP и в ситуации, когда скомпрометирована учетная запись владельца префикса. Реестр увидит авторизованную публикацию, хотя право на имя не доказывает безопасность кода, происхождение каждого артефакта или отсутствие вредоносной логики.
Вдобавок к этому права на префиксы действуют внутри одного пакетного репозитория. Если компания использует несколько источников зависимостей, факт резервирования acme- в PyPI сам по себе ничего не говорит о пакете с тем же именем в другом индексе или частном зеркале. PEP 752 прямо фиксирует, что права между репозиториями не переносятся. Конфигурация источников, фиксация версий и правила для корпоративного прокси остаются отдельной задачей.
Что это меняет для команд сейчас
Сам PEP не требует менять ни pip, ни зависимости в ваших манифестах. PEP 752 уже принят, а реализация механизма вошла в код Warehouse, на котором работает PyPI. Но порядок выдачи прав и интерфейс зависят от PEP 755, который пока остается черновиком.
Тем не менее, у команд есть повод посмотреть на эту тему заранее. Если организация выпускает несколько библиотек с общим началом имени, стоит составить их список и отделить официальный набор от пакетов, которые создают внешние участники. Это поможет понять, нужен ли будущий защищенный префикс и есть ли старые проекты с таким началом имени, для которых может потребоваться исключение.
Для потребителей Python‑пакетов PEP не отменяет обычную гигиену зависимостей. Новые прямые зависимости по‑прежнему стоит проверять до добавления в проект, версии фиксировать, а источники пакетов задавать явно. Когда PyPI начнет публиковать сведения о правах на префиксы, их можно будет добавить к этим сигналам. Они будут особенно полезны для пакетов, которые выглядят частью известного семейства, но ранее не встречались в проекте.
Вместо вывода
PEP 752 меняет не сам принцип открытого реестра, а его точку контроля. До сих пор PyPI мог проверить, свободно ли полное имя пакета. В предлагаемой модели он сможет проверить еще и право на узнаваемое семейство имен.
Срез PyPI показывает, что граница префикса важнее самого знакомого названия. Поэтому перед внедрением важно не только согласовать процедуру выдачи прав, но и решить, какой уровень имени относится к продуктовой линейке, а какой должен оставаться открытым для сообщества.
PEP 752 дает для этого механизм. Правильное применение будет зависеть от того, насколько аккуратно PyPI и сами проекты проведут границу между этими двумя случаями.
Подписывайтесь на Codescoring в Telegram, VK, YouTube и Макс.