WordPress.org Plugin-Einreichungs-Fertigkeit
Bringen Sie jedes Plugin durch den automatischen Scan und die manuelle Überprüfung von wp.org, ohne fünfmal neu hochladen zu müssen. Destilliert aus echten Review-Zyklen (der Art, bei der eine einzelne .gitkeep-Datei den gesamten Scan zum Scheitern bringt).
Betreuer: moksa · moksaweb.com · Lizenz: MIT
Wann verwenden
Diese Fertigkeit auslösen, wenn der Benutzer darum bittet:
- Ein bereinigtes Installations-ZIP für wordpress.org zu paketieren / zu bauen
- Ein Plugin im wp.org-Verzeichnis einzureichen oder erneut einzureichen
- Feedback des wp.org-Review-Teams zu beheben (die 4 klassischen Kategorien)
- Eine Ablehnung durch den automatischen Scan zu diagnostizieren (versteckte Dateien, Präfixe, DB-Aufrufe …)
- Eine Plugin-Version konsistent zu erhöhen (Header + Readme + Konstanten)
- Ein Plugin vor dem Upload vorzuprüfen
NICHT verwenden für:
- Nicht-WordPress-Projekte
- Private/interne Plugins, die nie an wp.org gehen (Review-Regeln gelten nicht, auch wenn die Sicherheitspraktiken dennoch hilfreich sind)
Die zwei Hürden
- Automatischer Scan (Plugin Check, wird beim Hochladen ausgeführt) — harte Blockaden. Muss bestanden werden, um überhaupt zu einem Menschen zu gelangen. Siehe
references/automated-scan.md. - Manuelle Überprüfung (ein Mensch, nach bestandenem Scan) — sendet Ihnen Probleme per E-Mail, Sie beheben und antworten. Fast immer eine von 4 Code-Kategorien (
references/review-categories.md) plus Richtlinien, die kein Linter abfängt – Lizenzierung, Remote-Code, Tracking, Admin-Hinweise, Marken, Offenlegung externer Dienste (references/guidelines.md).
Referenzkarte
| Thema | Datei |
|---|---|
| Plugin Check (PCP)-Runbook – UI/CLI, alle 31 Prüfungen → Fehlerbehebungsübersicht, Fehler vs. Warnungen | references/plugin-check.md |
| Harte Blockaden des automatischen Scans (versteckte Dateien, DB, unerlaubte Aufrufe) | references/automated-scan.md |
| Die 4 Kategorien der manuellen Überprüfung + Antwortformulierungen | references/review-categories.md |
| Erfahrungen aus echten Reviews (Beispiel→Suche, 3-Fall-Nonce, phpcs:ignore≠Escape, Cast≠Sanieren, Pfade, Fork-Präfixe) | references/real-review-lessons.md |
| Präfix für jede globale Variable (Funktionen/Optionen/Hooks/Handles/CPT/Meta …) | references/prefixing.md |
Sanieren · Validieren · Escapen + $wpdb->prepare + Webhook-Signaturen | references/sanitization-escaping.md |
| Einreihen von JS/CSS (Abhängigkeiten/Version, Inline, Sperren, Blöcke, keine rohen Tags) | references/enqueue.md |
| i18n (Textdomain==Slug, Literal-Strings, Übersetzer-Kommentare, JS) | references/i18n.md |
| Berechtigungen & Permission-Callbacks (Autorisierung, REST, priv/nopriv) | references/capabilities.md |
| Richtlinien (Lizenz, Remote-Code, Tracking, Hinweise, Marken, Offenlegung) | references/guidelines.md |
| readme.txt-Format (Header, Tags≤5, Kurzbeschreibung≤150, Screenshots, Externe Dienste) | references/readme-txt.md |
| Abilities API · AI Client · MCP (pro-Fähigkeit-Autorisierung, Datengrenze, Bestätigung bei zerstörerischen Aktionen, Anbieteroffenlegung) | references/abilities-ai-mcp.md |
| Sicherheitsextras (Dateien/WP_Filesystem, Uploads, SSRF, unerlaubte/verschleierte Aufrufe) | references/security-extras.md |
| Deinstallation & Lebenszyklus (Datenbereinigung, keine Benutzerinhalte löschen, Multisite) | references/uninstall.md |
| Paketieren des ZIP + Version/Header/Readme-Konsistenz + .mo | references/packaging.md |
| Scan/PHPCS-Code → Fehler-Nachschlagewerk | data/plugin-check-errors.csv |
Kurze Checkliste vor dem Upload (kopieren-einfügen-prüfen)
AUTOMATISCHER SCAN (harte Blockaden)
[ ] Keine versteckten Dateien im ZIP: `find . -name '.*' -not -name '.' -not -name '..'` ist LEER
(.gitkeep / .gitignore / .DS_Store / .editorconfig führen alle zu "hidden_files"-Fehler)
[ ] Keine node_modules/, .git/, tests/, scripts/, phpcs.xml, webpack.config.js im ZIP
[ ] Alle plugin-eigenen globalen Variablen verwenden ein eindeutiges Präfix mit >=4 Zeichen (kein wp_ / __ / einzelnes _ )
[ ] Keine direkten $wpdb-Abfragen ohne prepare(); keine Remote-Code-Ausführung; kein Telefonieren nach Hause
MANUELLE ÜBERPRÜFUNG (die 4 Kategorien)
[ ] Einreihen: kein rohes echo '<script>'/'<style>'; wp_enqueue_* + wp_add_inline_*
[ ] Nonce + current_user_can bei jedem zustandsändernden AJAX/admin_post; Webhooks prüfen die
Anbieter-Signatur mit hash_equals vor Verwendung (kein WP-Nonce möglich)
[ ] Jedes $_POST/$_GET ist saniert (wp_unslash + sanitize_*); json_decode -> map_deep;
Ausgabe spät escapen (esc_html/esc_attr/esc_url/wp_kses)
[ ] textdomain == slug; __()-Argumente sind Literal-Strings; /* translators: */ vor %s
RICHTLINIEN (manuelle Überprüfung, kein Linter fängt dies ab — references/guidelines.md)
[ ] GPL-kompatible Lizenz angegeben + LICENSE-Datei; jede gebündelte Bibliothek/Asset ist GPL-kompatibel
[ ] Keine Remote-Code-Ausführung / kein Laden von ausführbarem JS von einem CDN; Assets lokal bündeln
[ ] Jeder Drittanbieter-API-Aufruf in readme unter "== External services ==" offengelegt (welche Daten, wann, URLs)
[ ] Keine Datensammlung/Tracking ohne explizites Opt-in (standardmäßig AUS); kein Frontend-Credit-
Link außer bei Opt-in; Admin-Hinweise schließbar + bildschirmbezogen (keine Hinweisflut)
[ ] Slug/Name beginnt nicht mit einer Marke, die Sie nicht besitzen (woocommerce-… / google-…)
README.TXT (references/readme-txt.md — im wp.org-Readme-Validator prüfen)
[ ] Header wird korrekt geparst: Contributors=wp.org-Benutzernamen, Tags<=5, Stable tag = tatsächlich ausgelieferte Version
[ ] Kurzbeschreibung <=150 Zeichen, Klartext; Changelog hat einen Eintrag für den Stable tag
[ ] Screenshots/Banner/Icon kommen in SVN /assets/, NICHT im ZIP
KI / ABILITIES / MCP (falls das Plugin Fähigkeiten registriert, ein LLM aufruft oder MCP bereitstellt)
[ ] Jede wp_register_ability hat einen echten permission_callback (objektbezogene Berechtigung), nicht __return_true
[ ] Datengrenze: eine Ability/MCP-Tool gibt nur das zurück, was die Berechtigungen des aktuellen Benutzers erlauben
[ ] Modell/Agent-Eingabe als nicht vertrauenswürdig behandeln; zerstörerische Abilities durch Bestätigung geschützt
[ ] LLM/AI-SDK gebündelt (GPL); Anbieter in == External services == offengelegt; Schlüssel niemals protokollieren
[ ] MCP-Endpunkt authentifiziert (App Password/OAuth) UND führt den permission_callback jeder Ability aus
ZUSÄTZLICHE SICHERHEIT + LEBENSZYKLUS
[ ] Kein eval/shell/obfuscation/extract; kein var_dump/print_r/error_log hinterlassen
[ ] Dateien nur über WP_Filesystem in Uploads; Uploads über wp_handle_upload + MIME-Whitelist
[ ] Remote-Aufrufe über wp_safe_remote_* (SSRF: interne Bereiche blockieren) + Timeout + Antwortprüfung
[ ] uninstall.php durch WP_UNINSTALL_PLUGIN geschützt; entfernt nur Ihre präfixierten Daten; niemals Benutzerinhalte
PAKET + METADATEN
[ ] Version synchronisiert: Hauptdatei-Header Version, Versionskonstante, Readme-Stable tag, Changelog
[ ] Requires-Header stimmen in BEIDEN Dateien (Hauptdatei UND readme.txt) überein (WP / PHP / WC) — sowie jede
Laufzeit-MIN_*-Konstante, die die Aktivierung sperrt
[ ] vendor/ ist `composer install --no-dev` (kein squizlabs/phpunit/phpcompatibility)
[ ] ZIP-Wurzelordnername == Plugin-Slug
Arbeitsablauf
- Lesen Sie die Regeln für die Aufgabe (siehe Referenzkarte oben) — beginnen Sie mit
references/automated-scan.md+references/review-categories.md, dann das ausführliche Dokument, das zum Befund passt (prefixing.md/sanitization-escaping.md/enqueue.md/i18n.md) undreferences/packaging.mdfür den Build. - Erstellen Sie das bereinigte ZIP — führen Sie
scripts/build-zip.shaus (erledigt Git-Archiv, entfernt Entwicklungs- dateien + ALLE Punktdateien, installiertvendor/--no-dev, erstellt ZIP mit Slug als Stammverzeichnis). Niemals den Arbeitsbaum von Hand zippen; so gelangen Entwicklungsmüll und Punktdateien hinein. - Vorprüfung — führen Sie
scripts/preflight.sh <pfad-zum-zip-oder-verzeichnis>aus: scannt auf versteckte Dateien, prüft Version-Sync + Header/Readme-Konsistenz, führt PHPCS aus, falls konfiguriert. Beheben, bis alles sauber ist. - Plugin Check (PCP) ausführen — das offizielle Tool, das die automatischen Prüfungen des Verzeichnisses lokal
durchführt.
wp plugin check <slug> --require=./wp-content/plugins/plugin-check/cli.php(oder Tools → Plugin Check). Beheben Sie jeden FEHLER, überprüfen Sie jede WARNUNG. Siehereferences/plugin-check.mdfür alle 31 Prüfungen, Flags und welches Skill-Kapitel welche behebt. - Hochladen. Wenn der automatische Scan ablehnt → lesen Sie den genauen Code, ordnen Sie ihn über
data/plugin-check-errors.csvzu, beheben, neu bauen, erneut hochladen. - Antwort auf die manuelle Überprüfung — wenn der Prüfer per E-Mail Probleme meldet, beheben Sie jedes überall (die
Beispiele sind ein Anhaltspunkt — durchsuchen Sie den gesamten Baum, führen Sie Plugin Check + PHPCS über das gesamte
Plugin aus; dieselbe Kategorie wiederholt = sofortige erneute Ablehnung). Antworten Sie dann Punkt für Punkt unter
Bezugnahme auf die Änderungen. Siehe
references/review-categories.mdfür kanonische Korrekturen + Antwort- formulierungen undreferences/real-review-lessons.mdfür die pro-Kategorie-Suchbefehle und die Fallstricke, die eine erste Korrektur überleben.
Hart erkämpfte Fallstricke (die teuren)
.gitkeepführt zum Fehlschlag des automatischen Scans. Es ist eine versteckte Datei. Entfernen Sie jede Punktdatei aus dem Paket; entfernen Sie.gitkeepaus Git, damitgit archivesie nie wieder hinzufügt.- Versionsanforderungs-Drift. wp.org liest den Header der Hauptdatei UND readme.txt; eine Laufzeit-
MIN_WC/MIN_PHP-Konstante kann die Aktivierung separat sperren. Alle drei müssen übereinstimmen, sonst installiert ein Benutzer mit einer zu niedrigen Version erfolgreich und trifft dann auf defekte Funktionen. - Webhooks können keine WP-Nonces verwenden. Prüfer beanstanden "kein Nonce" bei IPN-Handlern — das ist ein
falsch positiver Befund; die richtige Antwort ist die Überprüfung der Anbieter-Signatur mit
hash_equals(). Dokumentieren Sie es mit einem zeilenweisenphpcs:ignore+ Begründung. json_decodeist keine Sanierung. Wenden Sie immermap_deep(sanitize_text_field)auf das Ergebnis an.composer install(ohne--no-dev) lässt phpcs/phpunit in vendor/ eindringen → aufgeblähtes, beanstandetes Paket. Für das ausgelieferte ZIP immer--no-devverwenden.