Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python Enhancement Proposals

PEP 763 – Begrenzung von Löschungen auf PyPI

Autor:
William Woodruff <william at yossarian.net>, Alexis Challande <alexis.challande at trailofbits.com>
Sponsor:
Donald Stufft <donald at stufft.io>
PEP-Delegate:
Donald Stufft <donald at stufft.io>
Discussions-To:
Discourse thread
Status:
Zurückgezogen
Typ:
Standards Track
Thema:
Packaging
Erstellt:
24-Okt-2024
Post-History:
09-Jul-2022, 01-Okt-2024, 28-Okt-2024
Resolution:
21-Sep-2025

Inhaltsverzeichnis

Rücknahme eines PEP

Dieses PEP wurde mit Wirkung vom 22. September 2025 zurückgezogen.

Während der Diskussion des PEP wurde deutlich, dass ein PEP nicht unbedingt der richtige Ort für Änderungen an der Löschrichtlinie von PyPI ist, da die Nutzungsrichtlinien von PyPI derzeit nicht (und notwendigerweise auch nicht) Teil des PEP-Prozesses sein sollten.

Zusammenfassung

Wir schlagen vor, die Möglichkeit für Benutzer, Dateien, Releases und Projekte von PyPI zu löschen, einzuschränken. Ein Projekt, Release oder eine Datei kann nur innerhalb von 72 Stunden nach dem Hochladen in den Index gelöscht werden. Von diesem Zeitpunkt an können Benutzer nur noch den Mechanismus „yank“ verwenden, wie in PEP 592 spezifiziert.

Eine Ausnahme von dieser Einschränkung gilt für Releases und Dateien, die mit Pre-Release-Spezifikatoren gekennzeichnet sind, die jederzeit gelöscht werden können. Die PyPI-Administratoren behalten sich das Recht vor, Dateien, Releases und Projekte jederzeit zu löschen, beispielsweise zu Moderations- oder Sicherheitszwecken.

Rationale und Motivation

Wie in PEP 592 festgestellt, ermöglicht die löschungsbasierte Entfernung von Projekten durch Benutzer auf PyPI eine Zwickmühlen-Situation durchbrochener Abhängigkeiten

Immer wenn ein Projekt feststellt, dass eine bestimmte Version auf PyPI fehlerhaft sein könnte, möchten die Maintainer oft verhindern, dass weitere Benutzer diese Version versehentlich verwenden. Die naheliegende Lösung, die Datei aus einem Repository zu löschen, würde jedoch Benutzer brechen, die eine bestimmte Version des Projekts angepinnt haben.

Dies hinterlässt Projekte in einer Zwickmühle, in der neue Projekte möglicherweise diese bekannte fehlerhafte Version herunterladen, aber wenn sie etwas dagegen tun, brechen sie Projekte, die sie bereits verwenden.

Auf technischer Ebene wird das Problem der Löschung durch „Yanking“ gemildert, ebenfalls spezifiziert in PEP 592. Löschungen sind jedoch weiterhin auf PyPI erlaubt und haben in den dazwischen liegenden Jahren zu mehreren bemerkenswerten Störungen des Python-Ökosystems geführt.

  • Juli 2022: atomicwrites wurde von seinem Maintainer gelöscht, um die „kritische“ Kennzeichnung des Projekts zu entfernen, ohne dass der Maintainer erkannte, dass die Projektlöschung auch alle zuvor hochgeladenen Releases löschen würde.

    Das Projekt wurde anschließend mit Zustimmung des Maintainers wiederhergestellt, jedoch auf Kosten manueller Administratormaßnahmen und umfangreicher nachgelagerter Brüche für Projekte wie pytest. Stand Oktober 2024 ist atomicwrites archiviert, hat aber immer noch etwa 4,5 Millionen monatliche Downloads von PyPI.

  • April 2023: codecov wurde von seinen Maintainern nach einer langen Depikationsfrist gelöscht. Dies führte zu erheblichen Problemen für viele CI/CD-Benutzer von Codecov, die von der Depikationsfrist nichts wussten, da die Beobachtbarkeit von Depikationswarnungen in CI/CD-Protokollen begrenzt war.

    Das Projekt wurde anschließend von seinen Maintainern wiedererstellt, wobei eine neue Version veröffentlicht wurde, um die gelöschten Versionen zu kompensieren (die nicht wiederhergestellt wurden), was bedeutet, dass alle angepinnten Installationen weiterhin fehlerhaft waren. Stand Oktober 2024 ist diese einzelne Version die einzige Version auf PyPI und hat etwa 1,5 Millionen monatliche Downloads.

  • Juni 2023: python-sonarqube-api löschte alle vor 2.0.2 veröffentlichten Releases.

    Der Maintainer des Projekts löschte anschließend Konversationen und führte einen Force-Push über den Tag-Verlauf des Quellcode-Repositorys von python-sonarqube-api durch, was die Bemühungen der Benutzer, Änderungen zwischen Releases zu vergleichen, behinderte.

  • Juni 2024: PySimpleGUI änderte die Lizenz und löschte nahezu alle vorherigen Releases. Dies führte zu weit verbreiteten Störungen bei den Benutzern, die (vor der Neulizenzierung) PySimpleGUI etwa 25.000 Mal pro Tag herunterluden.

Zusätzlich zu ihren störenden Auswirkungen auf nachgelagerte Abhängigkeiten haben Löschungen auch nachteilige Auswirkungen auf die Nachhaltigkeit von PyPI sowie auf die allgemeine Sicherheit des Ökosystems.

  • Löschungen erhöhen die Support-Auslastung für die Administratoren und Moderatoren von PyPI, da Benutzer fälschlicherweise Supportanfragen stellen, in dem Glauben, dass PyPI fehlerhaft ist oder die Administratoren das Projekt selbst entfernt haben.
  • Löschungen beeinträchtigen die externe (d.h. Endbenutzer-)Vorfallreaktion und -analyse, was es schwierig macht, „gutgläubiges“ Maintainer-Verhalten von einem böswilligen Akteur, der versucht, seine Spuren zu verwischen, zu unterscheiden.

Das Python-Ökosystem wächst weiter, was bedeutet, dass zukünftige Löschungen von Projekten vernünftigerweise als *genauso, wenn nicht sogar noch mehr*, störend als die oben aufgeführten Löschungen angenommen werden können.

Angesichts all dessen kommt dieses PEP zu dem Schluss, dass Löschungen nun ein größeres Risiko und einen größeren Nachteil für das Python-Ökosystem darstellen als einen Vorteil.

Zusätzlich zu diesen technischen Argumenten gibt es auch Präzedenzfälle aus anderen Packaging-Ökosystemen für die Einschränkung der Möglichkeit für Benutzer, Projekte und ihre Bestandteile zu löschen. Dieser Präzedenzfall ist in Anhang A dokumentiert.

Spezifikation

Es gibt drei verschiedene Arten von löschbaren Objekten

  1. Dateien, die einzelne Projektverteilungen sind (z.B. Quellcode-Distributionen oder Wheels).

    Beispiel: requests-2.32.3-py3-none-any.whl.

  2. Releases, die eine oder mehrere Dateien mit derselben Versionsnummer enthalten.

    Beispiel: requests v2.32.3.

  3. Projekte, die ein oder mehrere Releases enthalten.

    Beispiel: requests.

Regeln für die Löschberechtigung

Dieses PEP schlägt die folgenden *Regeln für die Löschberechtigung* vor

  • Eine **Datei** ist löschbar, wenn und nur wenn sie weniger als 72 Stunden vor der aktuellen Zeit auf PyPI hochgeladen wurde, **oder** wenn sie einen Pre-Release-Spezifikator hat.
  • Ein **Release** ist löschbar, wenn und nur wenn alle seine enthaltenen Dateien löschbar sind.
  • Ein **Projekt** ist löschbar, wenn und nur wenn alle seine Releases löschbar sind.

Diese Regeln erlauben die vollständige Löschung neuer Projekte und die Löschung neuer Dateien oder Releases durch alte Projekte, aber nicht die Löschung alter Dateien oder Releases durch alte Projekte.

Implementierung

Die Implementierung dieses PEP betrifft hauptsächlich Aspekte von PyPI, die nicht standardisiert oder standardisierbar sind, wie z.B. die Weboberfläche und Operationen für eingeloggte Benutzer. Infolgedessen beschreibt dieser Abschnitt die Implementierung in Form von Verhalten.

Änderungen

  • Gemäß den oben genannten Berechtigungsregeln wird PyPI Web-Interface-Anfragen (mit einem geeigneten HTTP-Antwortcode seiner Wahl) für die Löschung von Dateien, Releases oder Projekten ablehnen, wenn das jeweilige Objekt nicht zur Löschung berechtigt ist.
  • PyPI wird seine Weboberfläche anpassen, um die Nicht-Löschberechtigung einer Datei/eines Releases/eines Projekts anzuzeigen, z.B. indem die relevanten UI-Elemente als „inaktiv“ formatiert und relevante Schaltflächen/Formulare deaktiviert werden.

Sicherheitsimplikationen

Dieses PEP identifiziert keine negativen Sicherheitsimplikationen im Zusammenhang mit dem vorgeschlagenen Ansatz.

Dieses PEP identifiziert eine geringfügige positive Sicherheitsimplikation: Durch die Einschränkung benutzergesteuerter Löschungen wird es für einen böswilligen Akteur schwieriger, seine Spuren zu verwischen, indem er Malware aus dem Index löscht. Dies ist besonders nützlich für die externe (d. h. nicht-PyPI-Administrator-) Triage und Incident Response, bei der die verteidigende Partei einfachen Zugang zu Malware-Samples benötigt, um Indikatoren für eine Kompromittierung zu entwickeln.

Wie man das lehrt

Dieses PEP schlägt mindestens zwei öffentlich zugängliche Materialien vor, um der größeren Python-Packaging-Community (und ihren nachgelagerten Verbrauchern) seine Änderungen näher zu bringen

  • Ein Ankündigungspost auf dem PyPI-Blog, der die Natur des PEP, seine Motivationen und seine Verhaltensimplikationen für PyPI erklärt.
  • Ein Ankündigungsbanner auf PyPI selbst, das auf das Obige verlinkt.
  • Aktualisierungen der PyPI-Benutzerdokumentation, die den Unterschied zwischen Löschen und Yanking erklären und die begrenzten Bedingungen, unter denen ersteres weiterhin von Paketbesitzern initiiert werden kann.

Abgelehnte Ideen

Konditionierung der Löschung auf Abhängigkeitsbeziehungen

Eine Alternative zu zeitbasierten Löschfenstern ist die Löschberechtigung basierend auf nachgelagerten Abhängigkeiten. Beispielsweise könnte ein Release als löschbar gelten, wenn und nur wenn es weniger als N nachgelagerte Abhängigkeiten auf PyPI hat, wobei N so niedrig wie 1 sein könnte.

Diese Idee ist attraktiv, da sie die Löschberechtigung direkt mit der Störungswirkung verknüpft. npm nutzt sie und knüpft die Projektentfernung an die Abwesenheit jeglicher nachgelagerter Abhängigkeiten, die dem Index bekannt sind.

Trotz ihrer Attraktivität identifiziert dieses PEP mehrere Nachteile und technische Einschränkungen, die die abhängigkeitsbedingte Löschung für PyPI ungeeignet machen

  1. PyPI kennt keine Abhängigkeitsbeziehungen. In Python-Packaging sind sowohl Projekt-Builds *als auch* Metadatengenerierung häufig dynamische Operationen, die willkürlichen projektspezifizierten Code beinhalten. Dies wird durch Quellcode-Distributionen typisiert, die setup.py-Skripte enthalten, wobei die Ausführung von setup.py für die Berechnung der im Metadaten des Projekts kodierten Abhängigkeiten verantwortlich ist.

    Dies steht in deutlichem Kontrast zu Ökosystemen wie npm und Rusts crates, bei denen Projekt-Builds dynamisch sein können, aber die Metadaten des Projekts selbst statisch sind.

    Als Ergebnis davon weiß PyPI Ihre Projektabhängigkeiten nicht, und ist architektonisch nicht in der Lage, sie zu kennen, ohne entweder beliebigen Code auszuführen (ein erhebliches Sicherheitsrisiko) oder eine Langzeit-Depikation von setup.py-basierten Builds zugunsten von PEP 517 und PEP 621-ähnlichen statischen Metadaten durchzuführen.

  2. Führt zu einem unintuitiven Berechtigungsmodell. Die abhängigkeitsbedingte Löschung führt zu einem „umgekehrten“ Machtverhältnis, bei dem jeder, der eine Abhängigkeit von einem Projekt einführt, verhindern kann, dass dieses Projekt gelöscht wird.

    Dies ist auf den ersten Blick vernünftig, kann aber missbraucht werden, um unerwartete und unerwünschte Ergebnisse (im Kontext der Ermöglichung einiger Löschungen) zu erzielen. Ein bemerkenswertes Beispiel dafür ist npm’s everything-Paket, das von jedem öffentlichen Paket auf npm abhängt (Stand 30. Dez. 2023) und dadurch deren Löschung verhindert.

Konditionierung der Löschung auf Download-Anzahl

Eine weitere Alternative zu zeitbasierten Löschfenstern ist die Löschung basierend auf der Anzahl der Downloads. Zum Beispiel könnte ein Release als löschbar gelten, wenn und nur wenn es weniger als N Downloads im letzten Zeitraum hatte.

Obwohl dies Vorteile bietet, indem es die Möglichkeit der Projektlöschung mit seiner Nutzung verknüpft, identifiziert dieses PEP mehrere Einschränkungen für diesen Ansatz

  1. Vielfalt des Ökosystems. Das Python-Ökosystem umfasst Projekte mit sehr unterschiedlichen Nutzungsmustern. Ein fester Download-Schwellenwert würde Nischen-, aber kritische Projekte mit naturgemäß geringen Download-Zahlen nicht angemessen berücksichtigen.
  2. Zeitsensitivität. Download-Zahlen spiegeln nicht unbedingt den aktuellen Status oder die Bedeutung eines Projekts wider. Ein früher beliebtes Projekt könnte wenige aktuelle Downloads haben, aber für die Wartung älterer Systeme unerlässlich sein.
  3. Technische Komplexität. Der Zugriff auf die Download-Anzahl eines Projekts innerhalb von PyPI ist nicht einfach und es gibt nur begrenzte Möglichkeiten, die Download-Statistiken eines Projekts von Mirrors oder anderen Distributionssystemen zu sammeln.

Anhang A: Präzedenzfälle in anderen Ökosystemen

Die folgende Tabelle zeigt die Unterstützung für Löschungen in verschiedenen Packaging-Ökosystemen. Ein Ökosystem gilt als **nicht** löschunterstützend, wenn es die Fähigkeit eines Benutzers zur Durchführung von Löschungen in einer Weise einschränkt, die diesem PEP ähnelt.

Eine frühere Version dieser Tabelle, die nur die Löschung zeigte, wurde im Juli 2022 von Donald Stufft und anderen im Python-Diskussionsforum zusammengestellt. Juli 2022.

Ökosystem (Index) Löschung Yanking Anmerkungen
Python (PyPI) [1] [2] Die Löschung ist derzeit völlig uneingeschränkt.
Rust (crates.io) [3] Löschung durch Benutzer ist überhaupt nicht erlaubt.
JavaScript (npm) [4] [5] Die Löschung ist durch Kriterien ähnlich diesem PEP begrenzt.
Ruby (RubyGems) [6] RubyGems nennt Löschung „Yanking“. Yanking im Sinne von PyPI wird überhaupt nicht unterstützt.
Java (Maven Central) [7] Löschung durch Benutzer ist überhaupt nicht erlaubt.
PHP (Packagist) [8] Löschung wird nach einer undokumentierten Anzahl von Installationen eingeschränkt.
.NET (NuGet) [9] [10] NuGet nennt Yanking „Unlisting“.
Elixir (Hex) [11] [11] Hex nennt Yanking „Retiring“.
R (CRAN) [12] [12] Die Löschung ist auf 24 Stunden nach der Erstveröffentlichung oder 60 Minuten für nachfolgende Versionen beschränkt. CRAN nennt Yanking „Archiving“.
Perl (CPAN) Yanking wird überhaupt nicht unterstützt. Löschung wird scheinbar gefördert, zumindest Stand 2021. [13].
Lua (LuaRocks) [14] [14] LuaRocks nennt Yanking „Archiving“.
Haskell (Hackage) [15] [16] Hackage nennt Yanking „Deprecating“.
OCaml (OPAM) [17] [17] Die Löschung ist erlaubt, wenn sie „angemessen bald“ nach der Aufnahme erfolgt. Yanking wird *de facto* durch den Marker available: false unterstützt, der die Auflösung effektiv deaktiviert.

Die folgenden Trends sind vorhanden

  • Eine deutliche Mehrheit der Indizes unterstützt **keine** Löschung (9 vs. 4)
  • Eine deutliche Mehrheit der Indizes unterstützt Yanking (9 vs. 4)
  • Eine überwältigende Mehrheit der Indizes unterstützt eine der beiden oder keine von beiden, aber **nicht beide** (11 vs. 2)
    • PyPI und LuaRocks sind bemerkenswerte Ausreißer, die **sowohl** Löschung als auch Yanking unterstützen.

Fußnoten


Source: https://github.com/python/peps/blob/main/peps/pep-0763.rst

Zuletzt geändert: 2025-09-29 13:35:57 GMT