Krótka odpowiedź: nie, nie musisz wyrzucać ps_facetedsearch
W czerwcu 2026 przez społeczność PrestaShop przetoczył się tekst z tezą „porzuć ps_facetedsearch tak szybko, jak się da”. Powodem była krytyczna podatność w module. Tekst porusza kilka realnych problemów, ale wniosek jest moim zdaniem za szeroki. Podatność w module nie jest argumentem za jego usunięciem, tak samo jak krytyczne CVE w WordPressie nie jest argumentem za porzuceniem WordPressa.
Poniżej rozkładam sprawę na części: co dokładnie się stało od strony kodu, co jest prawdą w zarzutach o SEO i wydajność, a co jest przesadą. I najważniejsze: kiedy naprawdę warto zmienić silnik filtrów, a kiedy to strata budżetu klienta.
CVE-2026-54159, czyli co poszło nie tak w kodzie
To była poważna sprawa i nie ma sensu tego łagodzić. Podatność dostała CVSS 10.0, czyli maksimum. Zdalne wykonanie kodu, bez logowania, jedno spreparowane żądanie do front office. Dotyczy wszystkich wersji od 3.0.0 do 4.0.3 włącznie, na sklepach od PrestaShop 1.7.1.0 wzwyż. Poprawka jest w 4.0.4.
Mechanizm jest podręcznikowy i dlatego warto go znać:
- Moduł odtwarza wybrane filtry na podstawie URL-a.
- Wartość filtra suwakowego (cena lub waga) trafia z URL-a do wewnętrznego cache bloku filtrów bez wystarczającej walidacji, w postaci zserializowanej.
- Później ta wartość jest odczytywana z cache surowym, natywnym
unserialize()w metodziegetFromCache()w plikusrc/Filters/Block.php. - Odpowiednio spreparowany obiekt PHP w tym miejscu uruchamia gadget chain, który zapisuje plik PHP kontrolowany przez atakującego.
Klasyczny PHP Object Injection. Nic egzotycznego, po prostu unserialize() na danych, które pochodzą z zewnątrz.
Kto był faktycznie podatny
Warunkiem jest wystawiony na froncie filtr suwakowy: cena albo waga. To domyślne ustawienie na większości sklepów, więc w praktyce podatna była ogromna część instalacji. Ale jeśli w szablonie filtrów nie było suwaka, ścieżka była nieosiągalna. To nie jest wymówka, tylko informacja przydatna przy ocenie ryzyka po fakcie.
Co zrobić dzisiaj
Jeśli nie sprawdzałeś, sprawdź teraz. Wersję modułu odczytasz z bazy:
SELECT name, version FROM ps_module WHERE name = 'ps_facetedsearch';
Warto porównać to z właściwością $this->version w pliku modules/ps_facetedsearch/ps_facetedsearch.php, bo wpis w bazie potrafi się rozjechać po ręcznych wgrywkach przez FTP.
Plan działania:
- Aktualizacja do 4.0.4 lub nowszej. To jedyna rzecz, która faktycznie zamyka problem.
- Jeśli aktualizacja musi poczekać (konflikt z motywem, przesłonięcia szablonów, zamrożony deploy), zastosuj tymczasową łatę z oficjalnego advisory: w
getFromCache()zamieńunserialize()naTools::unSerialize(). Traktuj to jako most, nie jako rozwiązanie, bo zostajesz na starej wersji bez pozostałych poprawek. - Wyczyść cache bloku filtrów. Zatruty wpis może nadal siedzieć w tabeli
ps_layered_filter_block. Sama aktualizacja pliku nie usuwa danych, które już tam są. - Zrób audyt katalogu
modules/ps_facetedsearch/. Szukasz plików PHP, których tam być nie powinno. Moduł ma znany zestaw plików, każdy nadmiarowy.phpto czerwona lampka. - Przejrzyj logi serwera pod kątem żądań do kategorii z dziwnymi wartościami suwaków. W ładunkach serializacji PHP szukasz wzorców w stylu
O:oraz;i:. - Jeśli coś znalazłeś, sam update nie wystarczy. Wtedy pełne dochodzenie, zmiana haseł administratorów i kluczy API po potwierdzeniu, że sklep jest czysty.
Jedna rzecz, którą widzę u klientów notorycznie: rdzeń PrestaShop jest w miarę aktualny, bo o tym się pamięta, a moduły natywne dryfują latami. Suwak ceny, który działa od 2019 roku, nie zachęca nikogo do sprawdzania jego wersji. To jest prawdziwa przyczyna skali tego incydentu, a nie sam moduł.
SEO: tutaj krytyka jest w dużej mierze słuszna
Nawigacja fasetowa generuje kombinacje URL-i i to jest matematyka, nie opinia. Przy sześciu filtrach po pięć wartości każdy liczba możliwych kombinacji idzie w dziesiątki tysięcy na jedną kategorię. Przy dużym katalogu i rozbudowanych cechach dochodzisz do setek tysięcy adresów, z których większość jest bezwartościowa dla użytkownika i dla Google.
Konsekwencje są znane od lat:
- przepalony crawl budget na kombinacjach, których nikt nie szuka,
- indeksowanie stron z jednym produktem albo z pustym wynikiem,
- duplikacja i kanibalizacja treści, jeśli canonical i noindex nie są ustawione świadomie,
- rozjeżdżający się Search Console, w którym „Wykryto, obecnie bez indeksu” liczy się w setkach tysięcy.
Tylko że to nie jest wada ps_facetedsearch. To wada każdej nawigacji fasetowej w e-commerce, niezależnie od tego, czy pod spodem siedzi SQL, Elasticsearch czy zewnętrzny SaaS. Zamiana silnika bez zamiany strategii indeksowania da ci dokładnie ten sam problem, tylko szybciej.
Co realnie działa:
- canonical z kombinacji filtrów na czystą kategorię,
- noindex dla wszystkiego poza kilkoma świadomie wybranymi zestawami,
- promowanie do indeksu tylko tych kombinacji, które mają wolumen wyszukiwań i sensowną liczbę produktów, np. „buty trekkingowe męskie”, i budowanie z nich pełnoprawnych landing page z opisem,
- ograniczenie liczby filtrów w szablonie do tych, których klienci faktycznie używają. Sprawdź to w analityce, zanim zaczniesz ciąć.
Wydajność: prawda, ale zależna od skali
ps_facetedsearch buduje własny indeks i generuje pod filtry ciężkie zapytania. Na sklepie z 500 produktami tego nie zauważysz. Na sklepie z 300 tysiącami produktów, kilkudziesięcioma cechami i pełnym drzewem kategorii moduł potrafi być najcięższym elementem całej instalacji.
Typowe objawy, które widziałem na produkcji:
- przebudowa indeksu trwająca godzinami i wywalająca się na timeoucie,
- tabele
ps_layered_price_indexips_layered_product_attributepuchnące do setek megabajtów, - skok CPU przy zapisie produktu, bo reindeks cen odpala się w hooku
actionProductSave, co przy imporcie kilku tysięcy pozycji kładzie bazę, - filtry „wariujące” po zmianie cech, dopóki nie przebudujesz indeksu.
Szybki sanity check rozmiaru indeksów:
SELECT table_name,
ROUND((data_length + index_length) / 1024 / 1024, 2) AS mb
FROM information_schema.TABLES
WHERE table_schema = DATABASE()
AND table_name LIKE '%layered%'
ORDER BY mb DESC;
Jeśli suma idzie w setki MB, a katalog masz mały, to zwykle znaczy, że indeks nie jest czyszczony albo masz wielosklepowość z powielonymi wpisami. Zanim zaczniesz migrację na inny silnik, sprawdź to.
Czy ps_facetedsearch jest źle napisany?
Nie powiedziałbym. Powiedziałbym, że jest napisany zgodnie z architekturą sprzed kilku lat. Powstawał, gdy Elasticsearch nie był standardem w małym e-commerce, wyszukiwarki wektorowe nie istniały, a katalogi były mniejsze. Stąd oparcie o SQL i własne indeksowanie.
Warto też zauważyć, że moduł nie stoi w miejscu. W 3.16.0 przepisano listowanie produktów tak, żeby szło jednym dużym zapytaniem zamiast wielu, w 3.15.0 wycofano samodzielne endpointy indeksujące pod nową politykę bezpieczeństwa PrestaShop 9, a w 4.0.0 doszła zgodność z PHP 8.4. Doszły też hooki pozwalające rozszerzać filtry bez dotykania kodu modułu. To nie wygląda na porzucony projekt.
Uwaga przy migracji na PrestaShop 9
Jeśli masz na sklepie crona odpalającego stare, samodzielne pliki indeksujące modułu, sprawdź to przed upgradem. Ta ścieżka jest wycofana i po przejściu na 9.x cicho przestaje działać. Objaw: indeks przestaje się odświeżać, a nikt tego nie zauważa przez tydzień, bo front działa.
Czy AI Search zastąpi filtry?
Tu autor krytycznego tekstu przesadza. Teza brzmi mniej więcej tak: ludzie zaczną wpisywać „czarne buty trekkingowe 43” zamiast klikać filtry, więc nawigacja fasetowa umrze.
Częściowo to prawda i wyszukiwarka semantyczna faktycznie skraca drogę do produktu. Ale to są dwie różne funkcje w innych momentach ścieżki zakupowej. Wyszukiwarka pomaga znaleźć, filtry pomagają zawęzić i porównać. Amazon, Allegro i Zalando mają jedne z najlepszych wyszukiwarek na rynku i nadal inwestują w rozbudowane filtry, bo klient po wpisaniu frazy i tak chce potem odciąć rozmiar, kolor i przedział cenowy.
AI będzie dodatkiem, nie zamiennikiem. Planowanie architektury sklepu pod założenie, że filtry zaraz znikną, to podejmowanie ryzyka bez potrzeby.
Kiedy zostać przy ps_facetedsearch
Zostawiam moduł i nie mam z tym problemu, jeśli sklep spełnia te warunki:
- katalog do mniej więcej 20 tysięcy produktów,
- moduł w wersji 4.0.4 lub nowszej,
- rozsądna liczba filtrów w szablonie, dobrana pod realne zachowanie klientów,
- poprawne canonical i noindex na kombinacjach,
- indeksowanie, które faktycznie się odświeża i mieści się w oknie czasowym,
- czasy odpowiedzi na kategoriach w normie, sprawdzone pomiarem, nie na oko.
W takim układzie migracja na Elasticsearch czy OpenSearch nie zwróci się biznesowo. Dokładasz kolejny serwis do utrzymania, kolejny punkt awarii i kolejny koszt hostingu, żeby rozwiązać problem, którego nie masz.
Kiedy naprawdę warto zmienić silnik
Rozmowę o zmianie zaczynam, gdy pojawia się kilka z poniższych:
- katalog powyżej 100 tysięcy produktów albo bardzo duża liczba kombinacji atrybutów,
- kategorie ładujące się wolno mimo cache i zoptymalizowanej bazy,
- reindeks, który nie mieści się w oknie nocnym,
- import produktów kilka razy dziennie, który każdorazowo dobija bazę reindeksowaniem,
- potrzeba wyszukiwania z literówkami, synonimami i rankingiem biznesowym, czyli tego, czego SQL po prostu nie da,
- rozbudowana strategia landing page pod frazy long tail, wymagająca kontroli nad tym, co trafia do indeksu Google.
Wtedy silnik wyszukiwania (Elasticsearch, OpenSearch, Meilisearch, Typesense) ma sens, bo przenosisz ciężar z MySQL na system stworzony do tego zadania. Ale to jest projekt, a nie podmiana modułu. Musisz zaplanować synchronizację katalogu, obsługę wielosklepowości, ceny per grupa klienta, stany magazynowe i zachowanie po awarii silnika. Sklep nie może przestać sprzedawać dlatego, że padł kontener z wyszukiwarką.
Co bym zrobił na Twoim miejscu
Konkretna kolejność działań, od najpilniejszego:
- Sprawdź wersję modułu na wszystkich swoich sklepach. Dziś, nie w przyszłym tygodniu.
- Zaktualizuj do 4.0.4 lub nowszej, najpierw na kopii testowej, potem na produkcji.
- Wyczyść cache bloku filtrów i przejrzyj katalog modułu pod kątem nieznanych plików PHP.
- Dodaj monitoring wersji modułów natywnych do swojej rutyny utrzymaniowej. To jest ta rzecz, której brak zamienił jedną lukę w masowy problem.
- Dopiero potem, na spokojnie, oceń SEO i wydajność filtrów. To są problemy do rozwiązania w kwartał, nie w noc.
Wniosek: ps_facetedsearch nie jest modułem do wyrzucenia. Jest modułem do pilnowania. Dla zdecydowanej większości polskich sklepów na PrestaShop pozostaje sensownym, wspieranym i wystarczającym rozwiązaniem, pod warunkiem że ktoś świadomie kontroluje, ile filtrów wystawia na froncie i co z tego trafia do Google.
Jeśli chcesz, żeby ktoś sprawdził to za Ciebie: audyt wersji modułów, konfiguracji filtrów i indeksowania to standardowy element opieki nad sklepem, którą prowadzę. Napisz do mnie, przejrzymy Twój sklep.

