Bezpieczny kod WordPressa — co sprawdzić na wejściu, co zakodować na wyjściu, kogo wpuścić.
WordPress nie wydaje dokumentu pod nazwą „Secure Coding Standard”. Standardem w praktyce są dwie rzeczy: rozdział Security podręcznika dla programistów (pięć zasad i funkcje rdzenia do walidacji, sanityzacji, escapowania, nonce i uprawnień) oraz WordPress Coding Standards — reguły, które te zasady sprawdzają w kodzie automatycznie. Kierunek jest jeden: dane wchodzące się waliduje albo sanityzuje, dane wychodzące na stronę się escapuje — w chwili wypisania i pod kontekst. Poniżej cały standard, próba tego, co automat łapie, a czego nie, i luki WordPressa rozłożone na reguły, których zabrakło.
Źródło: podręcznik Security (Common APIs, akt. 23.07.2026) z podstronami, $wpdb->prepare(), standard PHP, WPCS 3.4.1 (27.07.2026, MIT), Plugin Check, odczyt 26.09.2026. Opisy są naszym opracowaniem, nie tłumaczeniem. Dane WordPressa: feed Wordfence, stan 07.09.2026; przypisanie luk do reguł jest nasze. Pozostałe standardy serii: OWASP Top 10, ECS, CVSS (średnie wyniki w TAB. 11).
- Zasady
- 5+ 3 zasady postawy
- Reguły WPCS Security + DB
- 11WPCS 3.4.1
- Luki WP z regułą standardu
- 93,6 %37 221 z 39 748
- Bramka Creato Ping
- 0 / 0błędów / ostrzeżeń · 5 wyjątków z powodem
37 221 z 39 748 luk (93,6 %) to złamanie jednej z reguł tej strony. Na grupy bez reguły w automacie — uprawnienia, pliki i ścieżki, żądania wychodzące — przypada 11 432 luk (28,8 %); tam zostaje recenzja kodu. Przypisanie CWE do reguł jest nasze (TAB. 11).
| Zasada | Rodzaj | Co znaczy w kodzie |
|---|---|---|
| Nie ufaj żadnym danym | Postawa | Dane od użytkownika, z bazy, z innych wtyczek i z zewnętrznych API traktujesz jak obce, dopóki ich nie sprawdzisz. |
| Korzystaj z API WordPressa | Postawa | Funkcje rdzenia (esc_*, sanitize_*, $wpdb->prepare, nonce) są sprawdzone i poprawiane w wydaniach bezpieczeństwa; własne odpowiedniki nie. |
| Aktualizuj kod | Postawa | Standard zmienia się razem z rdzeniem (np. %i w prepare od 6.2). Kod pisany pod stare API gubi nowe zabezpieczenia. |
| Nigdy nie ufaj wejściu | Zasada 1 | Każda wartość z $_GET, $_POST, $_COOKIE, $_SERVER, REST i AJAX przechodzi walidację albo sanityzację przed użyciem. |
| Escapuj jak najpóźniej | Zasada 2 | W chwili wypisania, nie przy zapisie. Recenzent widzi zabezpieczenie w tej samej linii co echo; zmiana kontekstu nie gubi ochrony. |
| Escapuj wszystko z niezaufanych źródeł | Zasada 3 | Także to, co przyszło z własnej bazy — do bazy mogło trafić przez inną, dziurawą ścieżkę. |
| Niczego nie zakładaj | Zasada 4 | Ani że użytkownik jest zalogowany, ani że żądanie przyszło z formularza, ani że pole ma oczekiwany typ. |
| Sanityzacja jest OK, walidacja lepsza | Zasada 5 | Poprawianie danych zostawia coś, co przeszło. Odrzucenie spoza listy dozwolonych nie zostawia nic. |
| Krok | Kiedy | Wynik | Funkcje | Uwaga |
|---|---|---|---|---|
| Walidacja | wejście — jak najwcześniej, przed jakimkolwiek działaniem | tak / nie; nie zmienia danych | is_email · term_exists · username_exists · validate_file · in_array(…, true) · preg_match | Lista dozwolonych (safelist) ze ścisłym typem. Lista zakazanych — „bardzo rzadko dobry pomysł”. |
| Sanityzacja | wejście — gdy walidacja jest niemożliwa (dowolny tekst) | oczyszczona wartość | sanitize_text_field · sanitize_textarea_field · sanitize_key · sanitize_email · sanitize_file_name · absint · esc_url_raw | Przed sanityzacją wp_unslash() — WordPress dodaje ukośniki do superglobali (WPCS: MissingUnslash). |
| Escapowanie | wyjście — w chwili wypisania, pod kontekst (HTML, atrybut, URL, JS) | bezpieczny zapis dla danego kontekstu | esc_html · esc_attr · esc_url · esc_js · esc_textarea · esc_xml · wp_kses | Sanityzacja przy zapisie NIE zastępuje escapowania przy wypisaniu. WPCS: echo sanitize_text_field(…) = błąd. |
Najczęstsza pomyłka to zamiana ról: sanitize_text_field() nie jest escapowaniem, a esc_html() nie jest walidacją. sanitize_text_field() robi pięć rzeczy: sprawdza, czy tekst jest poprawnym UTF-8; pojedynczy < zamienia na encję; usuwa wszystkie znaczniki; usuwa podziały linii, tabulatory i nadmiarowe spacje; usuwa oktety (%xx) — ale nie wie, gdzie tekst zostanie wypisany.
| Funkcja | Kontekst | Co robi |
|---|---|---|
| esc_html() | Tekst między znacznikami HTML | Koduje znaki HTML jako tekst: < > & " ' → encje. |
| esc_attr() | Wartość atrybutu HTML | Wszystko, co trafia do atrybutu — poza src/href. |
| esc_url() | src, href, action | Każdy adres wypisywany na stronę; odrzuca niedozwolone protokoły (javascript:). |
| esc_url_raw() | Adres do bazy lub przekierowania | Bez kodowania encji — do zapisu, nie do wypisania. |
| esc_js() | JavaScript w linii | Tekst wklejany do skryptu w atrybucie zdarzenia. |
| esc_textarea() | Zawartość <textarea> | Koduje tekst do pola wieloliniowego. |
| esc_xml() | Blok XML | Kanały, mapy witryny. |
| wp_kses() | HTML z listą dozwolonych znaczników | Zostawia tylko wskazane elementy, atrybuty i wartości; normalizuje encje. |
| wp_kses_post() | Treść jak we wpisie | wp_kses z listą HTML dozwolonego w treści wpisu. |
| wp_kses_data() | Treść jak w komentarzu | wp_kses z listą HTML dozwolonego w komentarzach. |
| esc_html__() · esc_attr_e() … | Tekst tłumaczony | Tłumaczenie + escapowanie w jednym (tłumaczenie też jest niezaufane). |
„Escapuj późno”: najlepiej w tej samej linii co echo. Wtedy recenzja jednej linii wystarcza, żeby powiedzieć, czy wypisanie jest bezpieczne.
| Czym jest | Jednorazowy żeton „number used once” dołączany do formularza albo adresu. Dowodzi, że żądanie wyszło z ekranu, który WordPress wydał temu użytkownikowi. |
|---|---|
| Przed czym chroni | CSRF — cudza strona nie wyśle w imieniu zalogowanego administratora żądania z poprawnym nonce, bo go nie zna. |
| Przed czym NIE chroni | Nie jest sprawdzany jako jednorazowy (powtórzenie przechodzi) i „nigdy nie może służyć do uwierzytelniania, autoryzacji ani kontroli dostępu”. Nonce ≠ current_user_can(). |
| Czas życia | Dwa „tiki” po połowie okresu; przy domyślnych 24 h nonce żyje od 12 do 24 h, zależnie od godziny wydania. |
| Wydanie | wp_create_nonce() · wp_nonce_field() (formularz) · wp_nonce_url() (link). |
| Sprawdzenie | wp_verify_nonce() zwraca 1 (bieżący tik), 2 (poprzedni) albo false · check_admin_referer() (ekrany wp-admin) · check_ajax_referer() (AJAX). |
| Sprawdzaj uprawnienie, nie rolę | current_user_can('manage_options'), nie „czy rola = administrator”. Role to paczki uprawnień, które inna wtyczka może zmienić; uprawnienie jest tym, co faktycznie chronisz. |
|---|---|
| Hierarchia domyślna | Subscriber → Contributor → Author → Editor → Administrator; każda wyższa rola ma uprawnienia niższych. |
| AJAX | wp_ajax_{akcja} obsługuje zalogowanych — DOWOLNĄ rolę, także subskrybenta. wp_ajax_nopriv_{akcja} — gości (niezalogowanych). Samo zalogowanie nie jest uprawnieniem. |
| REST API | register_rest_route() z permission_callback; „__return_true” = trasa publiczna świadomie. |
| admin_init | Działa także dla admin-ajax.php i admin-post.php, więc odpala się dla każdego zalogowanego — i dla gości. Nie jest bramką uprawnień. |
| Kolejność | Uprawnienie, potem nonce, potem walidacja danych. Każde z nich osobno jest niewystarczające. |
To reguła, której automat nie sprawdza (TAB. 10), a w feedzie brak uprawnień to 7559 luk — w 2026 roku więcej niż XSS (TAB. 11).
| Najpierw API | „Unikaj bezpośredniego dotykania bazy” — get_posts, WP_Query, get_option, update_post_meta mają cache i własne zabezpieczenia. |
|---|---|
| $wpdb->prepare() | Każda zmienna w zapytaniu przez symbol zastępczy: %d liczba całkowita · %f zmiennoprzecinkowa · %s tekst · %i identyfikator (tabela, kolumna — od WP 6.2). |
| Bez cudzysłowów | Symbole zastępcze zostają NIEOTOCZONE cudzysłowem — prepare() sam cytuje. Każdemu symbolowi odpowiada argument. |
| Procent | Dosłowny % w zapytaniu zapisuje się jako %%. |
| LIKE | Wzorzec przez $wpdb->esc_like(), a gotowy ciąg z % przekazany jako argument, nie wklejony. |
| esc_sql() | Tylko gdy prepare() nie da się użyć; ucieka znaki, ale nie cytuje — łatwo o błąd. |
| Bez ukośników | Funkcje zapisu oczekują danych BEZ ukośników SQL; escapowanie jak najbliżej zapytania. |
| Konstrukcja | Dlaczego | Reguła WPCS |
|---|---|---|
| eval() | „Bardzo niebezpieczne i niemożliwe do zabezpieczenia. Nie wolno używać.” | Squiz.PHP.Eval — błąd (WordPress-Core) |
| create_function() | Wewnętrznie eval(); przestarzałe w PHP 7.2, usunięte w 8.0. Nie wolno używać. | WordPress.PHP.RestrictedPHPFunctions — błąd |
| Operator backtick | polecenie = shell_exec(); większość hostingów i tak go wyłącza. | Generic.PHP.BacktickOperator — błąd |
| extract() | „Okropna funkcja” — tworzy zmienne z kluczy tablicy, także z danych użytkownika. | WordPress.PHP.DontExtract — błąd |
| unserialize() na cudzych danych | Wstrzyknięcie obiektu PHP (CWE-502). JSON zamiast serialize. | WordPress.PHP.DiscouragedPHPFunctions — ostrzeżenie |
| exec · system · shell_exec · passthru · popen · proc_open | Wywołania systemu; hostingi często je blokują. | DiscouragedPHPFunctions — ostrzeżenie |
| base64_decode · str_rot13 … | Zaciemnianie kodu — zakazane też przez zasadę 4 katalogu wtyczek. | DiscouragedPHPFunctions — ostrzeżenie |
| Reguła (WordPress.) | Zestaw | Co sprawdza |
|---|---|---|
| Security.EscapeOutput | Extra | Każde echo/print/printf/wp_die musi przejść przez funkcję escapującą (lub autoescapującą). |
| Security.ValidatedSanitizedInput | pełny | Superglobal: czy indeks istnieje (isset), czy wp_unslash(), czy sanityzacja. Trzy osobne błędy na jedno użycie. |
| Security.NonceVerification | Extra | Odczyt $_POST bez nonce = błąd; $_GET/$_REQUEST = ostrzeżenie. |
| Security.SafeRedirect | Extra | wp_redirect() = ostrzeżenie: użyj wp_safe_redirect() i exit. |
| Security.PluginMenuSlug | Extra | __FILE__ jako slug strony menu = ujawnienie ścieżki na serwerze. |
| DB.PreparedSQL | Core | Zmienna wklejona w zapytanie bez prepare() = błąd. |
| DB.PreparedSQLPlaceholders | Core | Poprawność prepare(): obsługiwane symbole, %% zamiast %, brak cudzysłowów, liczba argumentów, LIKE. |
| DB.DirectDatabaseQuery | pełny | Bezpośrednie $wpdb->query/get_* = ostrzeżenie; bez cache = drugie ostrzeżenie. |
| DB.RestrictedFunctions | Core | mysql_*, mysqli_* — omijanie $wpdb zakazane. |
| DB.RestrictedClasses | Core | PDO, mysqli jako klasy — zakazane. |
| DB.SlowDBQuery | pełny | tax_query, meta_query, meta_key — ostrzeżenie o wydajności, nie o bezpieczeństwie. |
Core = WordPress-Core, Extra = WordPress-Extra (zawiera Core), pełny = tylko zestaw „WordPress” albo wskazanie reguły wprost — tak robi bramka LAB247, która włącza całe przestrzenie WordPress.Security i WordPress.DB niezależnie od zestawów.
| Element | Kto | Rola |
|---|---|---|
| Podręcznik Security (Common APIs) | WordPress.org, zespół dokumentacji | Zasady i funkcje — co robić. Nie sprawdza niczego sam. |
| WordPress Coding Standards (WPCS) | WordPress, na licencji MIT | Reguły PHP_CodeSniffera: WordPress-Core, -Docs, -Extra, WordPress (wszystko). Wersja 3.4.1 z 27.07.2026 to wydanie bezpieczeństwa samego narzędzia (reguła EnqueuedResourceParameters przy skanowaniu cudzego kodu). |
| Plugin Check (PCP) | WordPress.org, wtyczka 2.1.0 | „Większość testów używanych przy nowych zgłoszeniach” do katalogu; w środku PHPCS + WPCS. Nie zastępuje ręcznej recenzji. |
| Zasady katalogu wtyczek | Plugin Review Team, 18 zasad | Bezpieczeństwa dotyczą m.in.: 4 (czytelny kod, bez zaciemniania), 7 (bez kontaktu z serwerami bez zgody), 8 (bez wykonywania kodu z zewnątrz), 13 (biblioteki rdzenia zamiast własnych kopii). |
| WordPress Security Team | ponad 50 ekspertów | Poprawki rdzenia w wydaniach bugfix, przenoszone „grzecznościowo” na starsze gałęzie; luki wtyczek zgłasza się autorom i zespołowi wtyczek. |
| Plik | Błędy | Ostrzeżenia | Linie | Wniosek |
|---|---|---|---|---|
| zly.php | 21 | 8 | 7 | Każda z 7 linii z danymi oznaczona: brak isset/unslash/sanityzacji, brak nonce, brak escapowania, SQL bez prepare, wp_redirect, unserialize, eval. |
| dobry.php | 0 | 2 | 1 | Zostają dwa ostrzeżenia DirectDatabaseQuery (bezpośrednie zapytanie, bez cache) — wydajność, nie bezpieczeństwo. |
| luki.php | 1 | 0 | 1 | Złapane tylko echo sanitize_text_field() (OutputNotEscaped). Przeszły: kasowanie wpisów przez gościa (nopriv, bez current_user_can) i esc_html() w href. |
zly.php — wszystko naraz:
<?php
function zly_zapis() {
global $wpdb;
$id = $_GET['id'];
echo '<p>' . $_POST['imie'] . '</p>';
$wpdb->query( "DELETE FROM {$wpdb->posts} WHERE ID = $id" );
update_option( 'x', $_POST['x'] );
wp_redirect( $_GET['wroc'] );
$dane = unserialize( $_COOKIE['d'] );
eval( $_REQUEST['kod'] );
}dobry.php — ta sama robota według standardu (uprawnienie → nonce → isset/unslash/sanityzacja → escapowanie → prepare → bezpieczne przekierowanie):
<?php
function dobry_zapis() {
global $wpdb;
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
check_admin_referer( 'dobry_zapis' );
$id = isset( $_POST['id'] ) ? absint( $_POST['id'] ) : 0;
$imie = isset( $_POST['imie'] ) ? sanitize_text_field( wp_unslash( $_POST['imie'] ) ) : '';
echo '<p>' . esc_html( $imie ) . '</p>';
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->posts} WHERE ID = %d", $id ) );
wp_safe_redirect( admin_url() );
exit;
}luki.php — dwie prawdziwe luki, które przechodzą (gość kasuje wpisy; esc_html() w href), i jedna pomyłka ról, którą automat łapie:
<?php
add_action( 'wp_ajax_nopriv_usun', 'luki_usun' );
function luki_usun() {
check_ajax_referer( 'usun' );
$id = isset( $_POST['id'] ) ? absint( $_POST['id'] ) : 0;
wp_delete_post( $id, true );
}
function luki_link( $url ) {
echo '<a href="' . esc_html( $url ) . '">x</a>';
}
function luki_wyjscie() {
echo sanitize_text_field( get_option( 'x' ) );
}Zestaw reguł próby (plus nagłówek <ruleset>):
<rule ref="WordPress.Security"/> <rule ref="WordPress.DB"/> <rule ref="WordPress.PHP.DiscouragedPHPFunctions"/> <rule ref="Squiz.PHP.Eval"/>
| Reguła | CWE (luk) | Luk | Udział | Śr. CVSS | Bez logow. | Bez łatki | WPCS |
|---|---|---|---|---|---|---|---|
| Escapuj wyjście esc_html · esc_attr · esc_url · wp_kses | 79 (16 421) · 80 (41) | 16 462 | 41,4 % | 6,05 | 6583 | 4905 | częściowo EscapeOutput łapie brak escapowania. Nie łapie złego kontekstu: esc_html() w href przechodzi. |
| Sprawdź uprawnienia current_user_can · permission_callback | 862 (5923) · 639 (677) · 269 (340) · 284 (187) · 285 (183) · 266 (147) · 863 (102) | 7559 | 19 % | 5,65 | 3316 | 1415 | nie Brak reguły. Handler wp_ajax_nopriv_ kasujący wpisy bez current_user_can() przechodzi czysto. |
| Weryfikuj nonce wp_nonce_field · check_admin_referer · check_ajax_referer | 352 (4878) | 4878 | 12,3 % | 5,57 | 4841 | 1862 | częściowo NonceVerification — tylko gdy kod czyta $_POST/$_GET. Akcja bez danych wejściowych umyka. |
| Waliduj pliki i ścieżki validate_file · wp_check_filetype_and_ext · lista dozwolonych | 98 (1441) · 434 (1089) · 22 (828) · 73 (79) | 3437 | 8,6 % | 8,21 | 1991 | 1246 | nie Surowy $_GET w include oznaczy ValidatedSanitizedInput, ale oczyszczona ścieżka (sanitize_text_field) przejdzie — a to dalej LFI. |
| Przygotuj zapytanie $wpdb->prepare · esc_like | 89 (2859) | 2859 | 7,2 % | 7,64 | 1116 | 687 | tak PreparedSQL: zmienna wklejona w zapytanie = błąd; PreparedSQLPlaceholders pilnuje %d/%s/%i i %%. |
| Nie deserializuj cudzych danych json_decode zamiast unserialize | 502 (906) | 906 | 2,3 % | 8,32 | 505 | 246 | tak DiscouragedPHPFunctions (ostrzeżenie) — w zestawie WordPress-Extra, nie w Security. |
| Nie wykonuj kodu z danych bez eval · exec · backticku | 94 (476) · 78 (15) · 77 (14) | 505 | 1,3 % | 7,99 | 263 | 90 | tak eval() = błąd w WordPress-Core, backtick = błąd, exec/system/shell_exec = ostrzeżenie. Wstrzyknięcie bez eval (np. call_user_func z danych) umyka. |
| Bezpieczne żądania wychodzące wp_safe_remote_get · wp_safe_remote_post | 918 (436) | 436 | 1,1 % | 6,41 | 158 | 90 | nie Brak reguły. wp_remote_get() z adresem od użytkownika przechodzi czysto. |
| Bezpieczne przekierowanie wp_safe_redirect + exit | 601 (179) | 179 | 0,5 % | 5,71 | 166 | 22 | tak SafeRedirect: każde wp_redirect() = ostrzeżenie. |
| Inne | CWE-200 ujawnienie informacji 1180 · CWE-288 obejście logowania 184 · CWE-287 uwierzytelnianie 130 · CWE-20 walidacja 118 · 140 innych CWE | 2527 | 6,4 % | 6,26 | 1889 | 363 | poza tym standardem — m.in. uwierzytelnianie i ujawnianie informacji |
| Rok | Escapowanie | Uprawnienia | Nonce | Prepare | Pliki | Wszystkie luki |
|---|---|---|---|---|---|---|
| 2021 | 770 | 184 | 224 | 163 | 72 | 1514 |
| 2022 | 1118 | 328 | 383 | 204 | 113 | 2396 |
| 2023 | 1976 | 948 | 1095 | 282 | 171 | 4892 |
| 2024 | 4045 | 1462 | 959 | 419 | 512 | 8317 |
| 2025 | 4360 | 2113 | 1447 | 636 | 1120 | 10 833 |
| 2026* | 1985 | 2204 | 310 | 607 | 902 | 7104 |
Bez logow. = wektor CVSS z PR:N (atak bez konta). Bez łatki = przynajmniej jeden komponent wpisu bez wersji naprawiającej. * 2026 = od stycznia do 07.09.2026. W 2026 brak uprawnień (2204) pierwszy raz wyprzedził XSS (1985) — a to jedyna duża grupa, na którą WPCS nie ma reguły. Liczy się data publikacji wpisu w feedzie, nie data powstania luki.
| Co | Stan | Jak |
|---|---|---|
| Bramka PHPCS wtyczki Creato Ping | działa | wp-plugin/phpcs.xml.dist = WordPress.Security + WordPress.DB + PHPCompatibilityWP (PHP 7.2-). Wynik 0 błędów i 0 ostrzeżeń; test test_phpcs_wtyczki.py pilnuje tego przy każdym wydaniu. |
| Wyjątki od bramki | działa | 5 × phpcs:ignore — każdy z nazwą reguły i powodem (np. INSERT IGNORE jako atomowa blokada; ścieżka REQUEST_URI, której sanitize_text_field zniszczyłby %xx). phpcs:disable zakazane testem. |
| Wejście i wyjście wtyczki | działa | Ustawienia: current_user_can('manage_options') + check_admin_referer + register_setting z sanitize_callback; wypisania przez esc_html/esc_attr; adres IP tylko z REMOTE_ADDR przez filter_var(FILTER_VALIDATE_IP); skróty porównywane hash_equals. |
| eval · unserialize · backtick w bramce | dług | Te reguły są w WordPress-Core/-Extra, nie w Security. Wtyczka przechodzi je dziś czysto (sprawdzone 26.09), ale bramka ich nie pilnuje — do dopisania do phpcs.xml.dist. |
| Kod PHP zmieniany przez Agentów AI | dług | DEV z CREATO_TEAM zmienia pliki motywu u klienta z bramką zdrowia (health.py: HTTP, w trybie ssh --php-check). WPCS na zmienionym pliku nie przechodzi — do dołożenia przed zapisem. |
| Uprawnienia w cudzych wtyczkach | nie robimy | Skaner patrzy z zewnątrz i nie widzi kodu. Brak current_user_can wykrywa dopiero baza podatności (Wordfence) — dopasowanie wersji na stronie klienta to osobny standard. |
| Styl WordPressa | nie robimy | Pełny zestaw WordPress daje 4 306 naruszeń w 44 regułach (4 093 do automatycznej poprawki: taby, spacje w nawiasach, Yoda). Celowo poza bramką — nie wpływa na bezpieczeństwo. |
Wtyczka 0.13.0-alfa.2: jeden plik, 1558 linii PHP. Bramka chroni to, co wtyczka robi u klienta; luki cudzych wtyczek śledzimy w Podatnościach i w Rozszerzeniach.
| Brak reguły na autoryzację | WPCS nie wie, kto może wykonać dany kod. Brak uprawnień to 19 % luk WordPressa w feedzie, a w 2026 (do 07.09) — najczęstsza grupa. Tu działa tylko recenzja i test. |
| Kontekst escapowania | WPCS sprawdza, CZY coś jest escapowane, nie CZYM. esc_html() w href, esc_attr() w skrypcie przechodzą. |
| Sanityzacja ≠ escapowanie | Oczyszczone przy zapisie może być groźne przy wypisaniu w innym kontekście. Podręcznik: waliduj i sanityzuj wejście, escapuj wyjście. |
| Nonce ≠ uprawnienie | Poprawny nonce ma każdy, kto widział formularz — także subskrybent. Podręcznik mówi wprost: nie do autoryzacji. |
| Kod, nie konfiguracja | Standard dotyczy pisania wtyczek i motywów. Uprawnienia kont, wp-config, pliki — to hardening, osobny standard serii. |
- Nazwa
- „WordPress Core Secure Coding Standards” nie jest tytułem żadnego dokumentu WordPressa. Opisujemy rozdział Security podręcznika Common APIs i reguły Security/DB z WPCS — to one są tym standardem w praktyce.
- Grupowanie CWE
- Nasze, nie WordPressa: każdej luce z feedu przypisaliśmy regułę standardu, która ją zatrzymuje (lista CWE w TAB. 11). Uwierzytelnianie (CWE-287, 288, 306) celowo w „inne” — current_user_can() go nie naprawia.
- Feed
- Odpis feedu Wordfence Intelligence używany przez monitoring LAB247, 39 748 wpisów, ostatni z 07.09.2026. Rok = data publikacji wpisu; 2026 to niepełne 8 miesięcy.
- Próba bramki
- Trzy pliki z TAB. 10 sprawdzone PHPCS 3.13.6 + WPCS 3.4.1 z zestawem pokazanym obok; liczby to wynik raportu `--report=full`. Próba jest nasza — do powtórzenia jedną komendą.
- Wtyczka
- Creato Ping 0.13.0-alfa.2, jeden plik PHP (1 558 linii). Bramka i pełny zestaw WordPress uruchomione 26.09.2026.