Перейти к содержимому
COS WP Woo
Назад к блогу
Обзоры28 мин чтения

Как выбирать плагины и не убить магазин: чек-лист аудита расширений

Плагин — это чужой код с правами администратора внутри вашего магазина. Разбираю, что проверять до установки, какие архитектурные звоночки видны уже после, и почему заброшенный или перепроданный плагин однажды становится вектором атаки.

# Как выбирать плагины и не убить магазин: чек-лист аудита расширений

Полтора года назад мне позвонил маркетолог одного из клиентов в состоянии, близком к панике. У них внезапно провалился весь трафик из рекламы — деньги в кампанию заливались исправно, а конверсия упала почти до нуля. Стали разбираться. Оказалось, что часть мобильных посетителей, переходивших по рекламной ссылке, вместо каталога товаров попадала на страницу с онлайн-казино на непонятном домене, а потом на некий сайт с розыгрышем айфона. Десктопные посетители и залогиненные администраторы видели обычный сайт — никакого редиректа, всё нормально. Именно поэтому проблему не замечали неделю: в админке всё выглядело идеально, а в Google Ads росли расходы без единого заказа.

Разобрались быстро, когда посмотрели логи и код. Виновником оказался плагин «похожие товары» — маленький, бесплатный, стоял на сайте года три, ни разу толком не привлекал внимания. Его исходный автор, судя по всему, продал права на плагин анонимному покупателю ещё год назад — это видно было по резкой смене тона в описании на WordPress.org и по тому, что changelog внезапно начал писаться ломаным английским вместо прежнего русского. Новый владелец пару месяцев вёл себя тихо, а потом выпустил обновление, в которое был зашит обфусцированный JavaScript. Скрипт проверял user-agent и реферер: если посетитель пришёл с мобильного устройства по рекламной ссылке и не был залогинен как администратор — редиректил его на партнёрку с азартными играми. Классическая cloaking-схема, которая роднит эту историю с десятками похожих случаев, которые я видел за карьеру в разных вариациях.

Я рассказываю эту историю не для того, чтобы напугать читателя мифическим монстром под кроватью. А для того, чтобы напомнить одну простую вещь, которую владельцы магазинов почему-то регулярно забывают в тот самый момент, когда нажимают кнопку «Установить» в каталоге плагинов WordPress. Плагин — это не иконка в App Store с песочницей вокруг. Это чужой PHP-код, который получает полный доступ к вашей базе данных, к файловой системе сервера, к сессиям администраторов, к платёжным настройкам, ко всему. WordPress не изолирует плагины друг от друга и от ядра — они выполняются в одном процессе с теми же правами, что и весь остальной сайт. Установить плагин — это буквально впустить в дом незнакомого человека и дать ему ключи от всех комнат, включая сейф. Большинство из них порядочные и просто делают свою работу. Но заранее это неизвестно, а проверить — можно.

Кстати, о размере проблемы в цифрах, которые я вижу на практике каждый раз, когда беру новый проект на аудит. Средний интернет-магазин на WooCommerce, который живёт три-четыре года и обрастал функциональностью постепенно, силами разных подрядчиков, приходит ко мне с двадцатью-тридцатью активными плагинами. При этом реально используемых из них, если разбираться честно, — обычно от восьми до двенадцати. Остальное — это накопленный хлам: плагин, который ставили для одной акции два года назад и забыли выключить; плагин, замену которому нашли, но старый деактивировать забыли; плагин, который вообще неясно зачем стоит, потому что человек, который его ставил, давно уволился, а знание умерло вместе с его уходом. Каждый такой «спящий» плагин — это не безобидный балласт, а полноценная активная поверхность атаки, которая продолжает получать обновления, продолжает исполнять код на каждой загрузке страницы и продолжает оставаться потенциальной дверью внутрь, даже если формально им никто не пользуется.

Я двадцать лет так или иначе связан с разработкой и продвижением интернет-магазинов, и за это время повидал десятки магазинов, у которых стояло от пятнадцати до сорока активных плагинов одновременно. Причём в подавляющем большинстве случаев никто в компании не мог с уверенностью сказать, зачем нужна половина из них и кто их вообще ставил. «Кажется, разработчик поставил на всякий случай», «это осталось от старой темы», «этот, по-моему, для чего-то с формами» — вот типичные ответы, которые я слышу на аудите. И вот в этом хаосе, где никто толком не следит за составом плагинов, и рождаются истории вроде той, с которой я начал. Поэтому сегодня хочу пройтись по тому, как я лично провожу аудит расширений — что смотрю до установки, что настораживает после, и почему тестовая копия сайта — это не паранойя разработчика, а единственный вменяемый способ вообще что-то проверить.

Каждый плагин — это чужой человек с ключами от вашего магазина

Начну с того, почему я вообще так серьёзно отношусь к этому вопросу. WordPress устроен так, что любой активированный плагин выполняется с теми же правами, что и весь остальной код сайта. Плагин может читать и писать в любую таблицу базы данных, включая таблицу пользователей с хешами паролей. Может создавать файлы где угодно в пределах прав веб-сервера. Может отправлять HTTP-запросы на внешние серверы — и вы не всегда узнаете, что именно и куда отправляется, если не смотрите специально. Может добавлять собственных пользователей с правами администратора. Может модифицировать другие плагины и темы через хуки. Иными словами, между «безобидным виджетом для отображения отзывов» и «полным контролем над сайтом» технически нет никакой границы — граница есть только в намерениях автора кода.

Это принципиально отличается от модели доверия, к которой люди привыкли в мобильных приложениях. Приложение на телефоне работает в песочнице, у него ограниченный список разрешений, которые можно выдать или отозвать, есть модерация в сторе, есть подписанные сертификаты разработчика. У плагина WordPress ничего этого нет в среднем случае. Каталог WordPress.org действительно проверяет код при первой публикации и иногда снимает плагины с явными уязвимостями, но это не защищает от того, что произойдёт с плагином через два года после публикации, когда его купит кто-то другой, или когда в очередном обновлении тихо появится новая функциональность, которую никто особо не читал построчно.

Я формулирую эту мысль клиентам максимально прямо: когда вы устанавливаете новый плагин, вы фактически нанимаете нового сотрудника с правами системного администратора, но при этом не проводите с ним собеседование, не проверяете рекомендации и подписываете трудовой договор не глядя. Согласитесь, звучит дико, если сформулировать так буквально. А происходит это на практике по десять раз за жизнь среднего магазина, потому что каждый плагин ставится с мыслью «ну это же просто маленькая функция, что тут может пойти не так».

А что если посмотреть на эту проблему с точки зрения самого WordPress как экосистемы, а не конкретного магазина? Открытость платформы — это одновременно её сила и её слабость. Именно благодаря тому, что любой разработчик может опубликовать плагин без сложной сертификации, экосистема располагает десятками тысяч расширений на любую мыслимую задачу, и это одна из причин, почему WordPress вообще стал такой массовой платформой для электронной коммерции. Но та же открытость означает отсутствие единого ответственного за качество и безопасность каждого конкретного расширения — эта ответственность размазана между автором плагина, модерацией каталога и, в конечном счёте, самим владельцем сайта, который нажимает кнопку «Установить». Я не вижу в этом устройстве ничего, что стоило бы менять — компромисс между открытостью и контролем в целом работает и обеспечил экосистеме взрывной рост. Но раз уж контроль качества частично лежит на владельце сайта, разумно относиться к этой роли серьёзно, а не перекладывать её молчаливо на кого-то другого.

И вот что особенно важно понимать: чем больше у плагина возможностей и чем глубже он интегрирован в ваш магазин, тем выше цена ошибки доверия. Плагин, который просто выводит виджет с погодой в сайдбаре, — это один уровень риска. Плагин, который имеет доступ к данным заказов, к платёжным токенам, к персональным данным покупателей, к настройкам доставки — совсем другой уровень, и относиться к выбору таких компонентов стоит с кратно большей осторожностью. Я видел, как владельцы магазинов трепетно выбирают платёжный шлюз, читают документацию, звонят в поддержку — и при этом за пять минут ставят первый попавшийся плагин для попапов с подпиской на рассылку, хотя этот попап технически имеет ровно такой же уровень доступа к сайту, как и платёжный модуль.

Что смотреть до того как нажали «Установить»

Первое, на что я смотрю в карточке любого плагина, — это дата последнего обновления. Не дата публикации, а именно дата последнего релиза. Если плагин не обновлялся больше года — это уже тревожный сигнал, даже если функционально он вроде бы работает. WordPress выпускает новые версии несколько раз в год, PHP развивается, появляются новые уязвимости в общих библиотеках — и плагин, который не поддерживается, со временем становится не просто бесполезным, а опасным, потому что известные уязвимости в старых версиях никто не закрывает. Причём я именно рекомендую смотреть на регулярность, а не на разовый факт свежего обновления: плагин, который получал спорадические обновления раз в два года, а потом вдруг обновился три раза за последний месяц без внятного changelog, — это тоже повод насторожиться, а не расслабиться. Именно так чаще всего выглядит смена владельца плагина, о которой я рассказывал в начале.

Второе — число активных установок и то, как оно менялось со временем, если такая история доступна. Большое число установок само по себе не гарантия безопасности — плагин с миллионом активных сайтов тоже может содержать критическую уязвимость, и такие случаи были у самых известных инструментов на рынке. Но большая база пользователей означает, что уязвимости в популярном плагине находят быстрее и чаще именно потому, что он представляет более привлекательную цель для исследователей безопасности и для самих атакующих. У маленького плагина с полусотней установок уязвимость может годами оставаться незамеченной просто потому, что никто не удосужился его как следует проверить — ни хорошие люди, ни плохие. Это не значит, что маленькие плагины плохие, но означает, что дополнительная проверка кода становится вашей персональной обязанностью, а не задачей широкого комьюнити.

Третье — активность автора в форуме поддержки. Я всегда захожу на вкладку поддержки в карточке плагина на WordPress.org и смотрю, отвечает ли автор на вопросы пользователей, как быстро и в каком тоне. Автор, который отвечает на тикеты в течение нескольких дней, разбирается в проблемах, признаёт баги и обещает исправления в следующей версии — это живой, вовлечённый разработчик. Автор, у которого последние тридцать вопросов в форуме висят без ответа месяцами, — это либо заброшенный проект, либо команда, которая физически не справляется с нагрузкой поддержки, и оба варианта означают, что помощи от них вы, скорее всего, не дождётесь в критический момент.

Четвёртое — открытые базы уязвимостей. Существуют публичные реестры уязвимостей именно для экосистемы WordPress — я регулярно заглядываю в такие базы перед тем, как рекомендовать клиенту новый плагин, особенно если речь о чём-то, что будет работать с оплатой, персональными данными или административным доступом. Важно смотреть не только сам факт наличия найденных уязвимостей в прошлом — это скорее нормально для любого достаточно популярного и долгоживущего плагина, — а то, как быстро автор их закрывал. Уязвимость, обнаруженная и закрытая за неделю, — это признак ответственной команды. Уязвимость, которая висела открытой месяцами при том, что о ней публично сообщили исследователи, — совсем другая история, и такой автор с высокой вероятностью поведёт себя так же и в следующий раз.

Пятое, и это чуть более тонкий момент — экономическая модель плагина. Я стараюсь понимать, на что вообще живёт автор или команда, которая его поддерживает. Если это open-source проект с понятной моделью — платная Pro-версия, разовые донаты, поддержка через агентство, — у него есть шанс жить долго, потому что есть стимул поддерживать качество. Если это полностью бесплатный плагин без единого явного источника дохода у автора — рано или поздно у автора либо кончится мотивация им заниматься, либо появится соблазн продать права тому, кто предложит деньги, и вы уже знаете, чем такая продажа иногда заканчивается. Я не говорю, что бесплатные плагины без монетизации — это заведомо плохо, среди них масса прекрасных долгоживущих проектов, которые авторы ведут просто из любви к делу. Но при прочих равных я отдаю предпочтение решению с понятной и устойчивой бизнес-моделью, потому что она снижает вероятность того, что через два года плагин попадёт в чужие руки.

Шестое, о чём я обязательно спрашиваю себя перед установкой, — а что вообще написано в отзывах на самой странице плагина, причём не только в пятизвёздочных, а именно в одно- и двухзвёздочных. Восторженные отзывы часто пишут в первые недели после установки, когда всё ещё работает и энтузиазм не остыл. А вот низкие оценки обычно оставляют люди, которые столкнулись с конкретной проблемой — конфликтом с определённой темой, потерей данных при обновлении, отсутствием ответа от поддержки. Я трачу минут пять на то, чтобы прочитать десяток последних низких оценок и посмотреть, ответил ли на них автор и как. Отсутствие ответов на негативные отзывы при активной публичной переписке по позитивным — сигнал, что автор избирательно взаимодействует с аудиторией, скорее в маркетинговых целях, чем в интересах реального качества продукта.

Седьмое — лицензия и происхождение кода. Подавляющее большинство плагинов в официальном каталоге WordPress распространяются по GPL-совместимой лицензии, что само по себе неплохо с точки зрения прозрачности — исходный код открыт, и теоретически любой специалист может его прочитать и проверить. Но открытая лицензия не означает, что кто-то реально этот код читал. Для критичных участков — оплата, работа с персональными данными, административный доступ — я стараюсь либо заказать краткий код-ревью у независимого разработчика, либо, если это невозможно по бюджету, хотя бы прогнать плагин через автоматический сканер уязвимостей перед тем, как ставить на боевой магазин. Это не даёт стопроцентной гарантии, но кратно снижает вероятность пропустить откровенно небрежный или вредоносный код.

Архитектурные звоночки, которые видны уже после установки

Есть набор признаков, которые не видны в карточке плагина на WordPress.org, но становятся заметны, как только вы поставили его на тестовую копию и заглянули под капот. Первый и, пожалуй, самый частый — плагин пишет все свои данные в таблицу postmeta вместо создания собственных таблиц базы данных. На первый взгляд это техническая мелочь, но на практике именно она превращает магазин на десять тысяч товаров в еле живой сайт через пару лет эксплуатации. Таблица postmeta и так одна из самых нагруженных в любом WooCommerce-магазине, потому что в ней хранятся все мета-поля товаров, заказов и вариаций. Каждый плагин, который бездумно добавляет туда собственные записи вместо создания отдельной таблицы под свою логику, делает эту таблицу тяжелее и запросы к ней медленнее — причём эффект не проявляется сразу, он накапливается месяцами и обнаруживается, когда сайт уже ощутимо тормозит, а виновника найти сложно, потому что виноватых оказывается сразу несколько плагинов одновременно.

Второй звоночек — плагин загружает свои скрипты и стили на каждой странице сайта независимо от того, нужен он на этой странице или нет. Открываете вкладку сетевых запросов в инструментах разработчика на главной странице интернет-магазина — и видите, что виджет для формы обратной связи, который используется на одной-единственной странице контактов, почему-то тянет свой JavaScript и на главной, и в каталоге, и в карточке товара, и в корзине. Это классическая небрежность в разработке, которая незаметна на одном плагине, но за десять таких плагинов складывается в секунды дополнительной загрузки на каждой странице сайта — и это как раз то, что убивает скорость магазина медленно и незаметно, о чём я подробно писал в другой статье про производительность каталога.

Третий признак — плагин требует отключить кеширование или изменить настройки безопасности, чтобы «корректно работать». Я воспринимаю это как красный флаг практически всегда. Хорошо спроектированный плагин умеет корректно работать вместе с популярными системами кеширования и не требует ослаблять защиту сайта ради своей функциональности. Если в документации плагина буквально написано «отключите кеш страницы, иначе форма не будет работать» — это означает, что автор либо не разобрался с правильной инвалидацией кеша через хуки, либо изначально проектировал плагин без оглядки на то, что сайт вообще может использовать кеш. Ни один из этих вариантов не внушает доверия к остальному качеству кода.

Четвёртый признак — избыточная телеметрия и внешние запросы, о которых не сказано прямо. Некоторые плагины при активации без явного согласия начинают отправлять данные о вашем сайте на сервер разработчика — не обязательно что-то злонамеренное, часто это банальная аналитика использования, но она должна быть прозрачной и опциональной, а не зашитой намертво. Я специально смотрю в код или хотя бы в сетевые запросы после установки плагина: если он молча стучится на десяток разных доменов при каждой загрузке страницы, это повод задать вопрос, зачем, даже если ответ окажется безобидным.

Расскажу конкретный пример из практики, который хорошо иллюстрирует, насколько незаметно такие вещи прячутся. На одном из проектов при аудите мы обнаружили плагин для отображения баннера со скидкой, который при каждой загрузке страницы каталога отправлял запрос на сторонний домен с данными о просмотренном товаре — якобы для «персонализации предложений». Никакой персонализации на практике не происходило, баннер был статичным и не менялся в зависимости от товара. То есть функция сбора данных существовала в коде отдельно от заявленной ценности плагина для магазина, и единственным бенефициаром этой телеметрии была неизвестная третья сторона, получавшая полную историю просмотров каталога конкретного магазина. Мы заметили это только потому, что специально смотрели вкладку сетевых запросов при разборе жалобы на медленную загрузку каталога — сама медлительность оказалась куда менее интересной находкой, чем то, что вообще происходило в фоне.

Пятый признак, который я бы назвал скорее организационным, чем техническим, — количество зависимостей от сторонних библиотек и то, насколько они устарели. Плагин, который тянет за собой версию jQuery пятилетней давности или библиотеку с известными и давно закрытыми в новых версиях уязвимостями, показывает, что автор либо не следит за экосистемой, либо сознательно экономит на обновлении зависимостей. Это тот случай, когда даже разработчик без глубокой экспертизы в безопасности может заметить проблему, если знает, куда смотреть, — а вот обычный владелец магазина без техническо­го фона такое заметить не сможет никогда, и здесь ему нужен кто-то, кто хотя бы иногда проводит подобный аудит на регулярной основе.

Тестовая копия — не паранойя, а единственный вменяемый способ проверки

Вот здесь я хочу сказать прямо и без оговорок: ставить новый плагин сразу на боевой магазин — это ошибка, которую я видел настолько часто, что перестал удивляться последствиям. Логика владельца понятна: «плагин маленький, проверенный, у него сто тысяч установок, что может пойти не так». А идёт не так ровно то, что предсказать заранее невозможно — конфликт с другим плагином, несовместимость с конкретной версией темы, неожиданный php-notice, который в самой безобидной ситуации превращается в белый экран смерти прямо на странице оформления заказа в разгар рабочего дня. Я видел магазин, который потерял часть заказов за один вечер именно из-за такого сценария — новый плагин для отображения остатков товара конфликтовал с кастомной темой ровно на странице чекаута, и часть покупателей просто не могла завершить оформление, получая ошибку без внятного объяснения.

Правильная практика простая и совсем не требует героических усилий: держите тестовую копию магазина — тот же код, та же (или свежая) копия базы данных, но на отдельном поддомене или локальном окружении, недоступном поисковикам и реальным покупателям. Любой новый плагин сначала ставится туда. Проверяется не только «плагин включился и не выдал ошибку» — это самый низкий и недостаточный уровень проверки. Проверяется реальный пользовательский путь: добавление товара в корзину, применение купона, оформление заказа с разными способами оплаты и доставки, поведение личного кабинета, работа поиска и фильтров. Проверяется скорость загрузки ключевых страниц до и после установки плагина — с помощью любого инструмента замера, чтобы иметь на руках конкретные цифры, а не ощущение «вроде не сильно медленнее».

Отдельный полезный приём — сознательно попробовать сломать плагин на тестовой копии, а не только проверить его в счастливом сценарии, когда всё вводится правильно. Отправить форму с пустыми полями, ввести в числовое поле буквы, загрузить файл неожиданного формата туда, где ожидается изображение, попробовать оформить заказ с нулевой суммой через применение нескольких купонов подряд. Хорошо написанный плагин корректно обработает любой из этих сценариев — покажет понятную ошибку, откажет в сохранении некорректных данных, не даст сайту сломаться. Плагин с небрежной валидацией входных данных в лучшем случае покажет пользователю нечитаемую техническую ошибку, а в худшем — пропустит вредоносный ввод дальше в базу данных, что уже прямая дорога к SQL-инъекции или межсайтовому скриптингу. Именно тестовая копия — то единственное место, где можно позволить себе побыть немного вредителем по отношению к собственному сайту, не рискуя реальными заказами.

Отдельно я всегда прошу посмотреть лог ошибок PHP на тестовой копии сразу после активации нового плагина. Многие проблемы не проявляются как явная поломка на экране — сайт продолжает выглядеть нормально, но в логе тихо копятся notice и warning об устаревших функциях, неопределённых переменных, deprecated-вызовах. Это тот случай, когда явной катастрофы ещё нет, но качество кода плагина уже говорит само за себя: если автор не потрудился убрать элементарные PHP-предупреждения в собственном коде, вряд ли стоит рассчитывать на аккуратную работу более сложных частей той же кодовой базы.

Есть ещё один практический приём, которым я пользуюсь на тестовой копии и который занимает совсем немного времени, но окупается регулярно. Перед установкой нового плагина я делаю полный снимок структуры директории `wp-content` — просто список файлов с их размерами и датами изменения. После установки и активации плагина снимаю такой же список повторно и сравниваю разницу. В подавляющем большинстве случаев разница ожидаема — появилась папка самого плагина, и всё. Но иногда обнаруживаются файлы, созданные совсем не там, где логично ожидать: что-то появилось в директории темы, что-то — в корне `wp-content`, что-то — с именем, явно маскирующимся под системный файл ядра WordPress. Такие находки не всегда означают злой умысел, иногда это просто неаккуратная архитектура плагина, который вместо собственной изолированной папки лезет куда попало. Но в любом случае это повод для дополнительного вопроса, прежде чем плагин попадёт на боевой сайт.

Есть ещё одна причина держать тестовую копию, помимо проверки перед установкой, — это возможность безопасно проверять обновления уже установленных плагинов. Я регулярно вижу магазины, где владелец боится обновлять плагины вообще, потому что один раз обновление что-то сломало на боевом сайте, и с тех пор политика «работает — не трогай» стала железным правилом. Это плохая стратегия, потому что устаревшие версии плагинов — один из самых частых векторов взлома, и рано или поздно неупомянутая уязвимость находится и эксплуатируется автоматизированным сканером. Правильный порядок — сначала обновление накатывается на тестовую копию, проверяется тот же набор пользовательских сценариев, и только после этого переносится на боевой сайт. Да, это требует дисциплины и небольшого количества дополнительного времени каждую неделю. Но это время не сравнится с тем, что потребуется на разбор инцидента, если что-то пойдёт не так на живом магазине с реальными покупателями внутри.

Заброшенные и перепроданные плагины: как любимый инструмент превращается в бэкдор

История, с которой я начал статью, — не редкое исключение, а хорошо задокументированный паттерн в экосистеме WordPress. Схема выглядит примерно одинаково из раза в раз. Есть плагин, который автор-энтузиаст написал несколько лет назад, он стал популярным, набрал десятки или сотни тысяч установок, но у автора со временем кончился интерес или время им заниматься — жизнь меняется, появляется основная работа, семья, другие приоритеты. Плагин продолжает висеть в каталоге, продолжает исправно работать на сотнях тысяч сайтов, но обновления выходят всё реже. И вот в какой-то момент к автору обращается покупатель, предлагающий разумную сумму денег за права на проект. Автор, у которого и так пропал интерес поддерживать код бесплатно, соглашается — с его точки зрения, это абсолютно рациональное решение, он получает деньги за то, что и так собирался забросить.

Проблема начинается дальше, когда новый владелец плагина — а купившие такие активы структуры далеко не всегда прозрачны в том, кто они на самом деле, — получает доступ к базе из сотен тысяч сайтов, на которых плагин уже активирован и которым не терпится получить свежее обновление. Это готовый канал распространения для чего угодно: скрытой рекламы, партнёрских ссылок без раскрытия, сбора данных сверх заявленного, а в худших случаях — вредоносного кода вроде того, что я описывал в начале статьи. Причём владельцу магазина, у которого этот плагин стоит третий год без единой мысли о нём, чрезвычайно сложно вовремя заметить смену контроля над проектом. Он просто видит уведомление «Доступно обновление» и нажимает «Обновить», как делал это десятки раз до этого без последствий.

Похожий, но чуть более мягкий сценарий деградации происходит и без формальной продажи прав — просто из-за естественной усталости автора-одиночки. Я видел плагин, которым несколько лет пользовался один из клиентов для управления промоакциями, — изначально быстрый, аккуратный, с отзывчивой поддержкой. Со временем автор явно перегорел: обновления стали выходить раз в год вместо нескольких раз в квартал, в форуме поддержки скопились десятки нерешённых вопросов, а сам плагин так и не получил совместимости с новыми версиями PHP, из-за чего на сервере стали появляться предупреждения об устаревших конструкциях языка. Формально плагин не был продан и не содержал ничего вредоносного — просто медленно умирал вместе с интересом своего единственного разработчика. Для владельца магазина итог почти такой же, как при недобросовестной продаже: рано или поздно плагин перестаёт быть безопасным просто в силу того, что никто не следит за его совместимостью с меняющейся вокруг средой.

Есть несколько сигналов, по которым можно заподозрить смену владельца ещё до того, как случится что-то плохое. Резкая смена стиля описания плагина в каталоге — если раньше текст был написан живым языком с примерами использования, а вдруг стал сухим, шаблонным или неестественно переведённым. Смена контактного email в поддержке или внезапное появление новых имён в списке контрибьюторов без какого-либо анонса в changelog. Появление в новых версиях функциональности, вообще не связанной с изначальным назначением плагина, — например, плагин для отображения социальных иконок вдруг обзаводится встроенной аналитикой посещаемости или собственной системой уведомлений, которая раньше не была частью замысла. Ни один из этих признаков сам по себе не доказательство злого умысла, но совокупность нескольких таких сигналов — весомый повод присмотреться внимательнее или временно приостановить автообновление конкретного плагина до ручной проверки нового кода.

Что делать, если критически нужный магазину плагин оказался заброшенным, а полноценной замены на рынке нет? У меня есть три варианта ответа в зависимости от ситуации, и я честно проговариваю все три с клиентом, а не молчаливо выбираю один. Первый — продолжать использовать плагин, но отключить у него автоматические обновления и вручную проверять каждую новую версию на тестовой копии, прежде чем накатывать на боевой сайт, а заодно регулярно сверяться с базами уязвимостей именно по этому конкретному плагину. Второй — нанять разработчика, который сделает форк последней доверенной версии кода, уберёт лишние внешние зависимости и будет сопровождать этот форк самостоятельно, без оглядки на оригинальный проект и его возможную смену владельца. Третий, и часто самый правильный на среднесрочном горизонте, — поискать функциональный аналог с более здоровой историей поддержки и один раз перенести данные, приняв разовые трудозатраты миграции ради того, чтобы не жить на пороховой бочке годами. Какой вариант выбрать — зависит от критичности функции, бюджета и горизонта планирования, но важно, чтобы выбор был осознанным, а не результатом того, что до этого вопроса просто не дошли руки.

Отдельно скажу про ответственность подрядчика, если плагины на ваш магазин ставит внешнее агентство или фрилансер, а не штатный сотрудник. Я считаю нормальной практикой прямо прописывать в договоре или техническом задании обязанность подрядчика обосновывать выбор каждого нового стороннего плагина — почему именно этот, какие альтернативы рассматривались, какие риски видит сам разработчик. Это не бюрократия ради бюрократии, а способ заставить исполнителя хотя бы формально продумать решение, а не тащить первый плагин, который выпал в верху поисковой выдачи каталога. Я видел договоры, где заказчик прямо запрещал подрядчику устанавливать что-либо не из согласованного списка без отдельного письменного одобрения, — жёстко, но для крупных магазинов с высокой ценой ошибки это оправданная предосторожность.

Здесь стоит сделать честную оговорку, потому что легко удариться в паранойю и начать подозревать любую продажу прав как заведомое зло. Смена владельца плагина — это не всегда плохо. Есть множество примеров, когда небольшой проект покупала компания с ресурсами на полноценную поддержку, и качество плагина после этого только выросло — появилась настоящая команда разработки, ускорились ответы в поддержке, закрылись старые известные проблемы. Разница между хорошим и плохим сценарием обычно видна в первые месяцы после смены владельца: растёт ли частота действительно полезных обновлений с понятным changelog, или обновления выходят реже, но зато появляются странные новые «фичи», о смысле которых остаётся только догадываться.

Практический вывод из всего этого простой: аудит плагина — это не разовое действие в момент установки, а то, что стоит повторять периодически для уже работающего магазина. Я рекомендую клиентам делать что-то вроде ревизии установленных расширений хотя бы раз в полгода: пройтись по списку активных плагинов, свериться с датами последних обновлений, посмотреть, не появились ли новые владельцы или подозрительные изменения в поведении. Это отдельная, отнюдь не героическая по трудозатратам задача, но она регулярно спасает магазины от историй вроде той, с которой началась эта статья.

Отдельно хочу сказать о плагинах, скачанных не из официальных каталогов, а с так называемых nulled-сайтов — площадок, которые раздают премиальные платные плагины бесплатно, обходя лицензионную защиту. Соблазн понятен: платная тема или плагин стоит несколько десятков долларов в год, а тут вроде бы то же самое и даром. Но подавляющее большинство таких «взломанных» копий на практике содержит встроенный вредоносный код — обычно бэкдор, который даёт анонимному третьему лицу постоянный доступ к сайту в обход всех ваших паролей и систем защиты. Я расцениваю это не как серую зону, а как прямое приглашение к взлому, потому что здесь злой умысел заложен изначально, а не появляется через два года после продажи прав добросовестным автором. Экономия в несколько тысяч рублей в год почти никогда не стоит того риска, которым она оборачивается, если что-то пойдёт не так.

Заканчивая эту тему, хочу сформулировать правило, которым сам руководствуюсь при принятии решения, ставить новый плагин или нет. Новый плагин появляется в магазине только тогда, когда он закрывает конкретную, реально существующую боль, а не потому что «пригодится на будущее» или «конкурент вроде тоже так делает». Каждый плагин — это не только новая функция, но и новая точка отказа, новая зависимость от чужого кода, новый пункт в списке того, что нужно регулярно проверять и обновлять. Магазин с пятью хорошо выбранными плагинами почти всегда надёжнее и быстрее магазина с тридцатью, даже если формально во втором случае возможностей вроде бы больше. Разница в том, что тридцать точек отказа контролировать физически сложнее, чем пять, вне зависимости от того, насколько внимателен владелец.

Именно поэтому мы в COS WP Woo изначально спроектировали продукт как одну систему вместо набора разрозненных модулей — поиск, B2B, безопасность, синхронизация с 1С, формы, кастомные поля и всё остальное живут в одном плагине с общей архитектурой, а не собираются владельцем магазина из десятка чужих расширений разного качества и с разной историей поддержки. Но я хочу закончить честно: даже к нам стоит применять ровно те же критерии аудита, что я описал выше, — смотреть на частоту обновлений, на реакцию на тикеты в поддержке, на архитектурные решения внутри. Правило замещения работает универсально, вне зависимости от того, кто автор конкретного кода: новый инструмент в магазине имеет право на существование только тогда, когда он реально убирает существующую боль, а не потому что кто-то красиво его прорекламировал. Если вы уже думаете о том, чтобы заменить зоопарк из разрозненных расширений на что-то одно — вот статья о том, сколько реально стоит такой зоопарк плагинов в деньгах и в рисках, а если вопрос именно в защите от чужого кода и брутфорса — у нас есть отдельный разбор того, как остановить ботов и брутфорс без сторонних плагинов безопасности, который дополняет сегодняшний чек-лист с другой стороны. А если вы уже задумались о переносе кастомных полей на что-то более предсказуемое, чем разрозненные ACF-надстройки сомнительного происхождения, — есть разбор того, как устроена замена ACF внутри единой системы.

И последнее, о чём хочу сказать напоследок. Аудит плагинов — это скучная, невидимая работа, которая никогда не попадёт в отчёт о росте продаж и не станет темой для гордости на встрече с инвестором. Но именно эта скучная работа отделяет магазин, который тихо работает годами, от магазина, который однажды утром получает звонок от маркетолога в панике, потому что реклама льётся, а заказов нет. Тот случай с редиректом на казино, с которого я начал, обошёлся клиенту в заметную сумму слитого рекламного бюджета за неделю, пока проблему не нашли, — и это без учёта репутационных издержек, потому что часть тех обманутых посетителей больше никогда не вернулась на сайт, даже когда всё почистили. Я не знаю ни одного владельца магазина, который бы потом сказал, что зря потратил время на аудит плагинов. Зато знаю нескольких, кто искренне жалел, что не сделал этого раньше.