Технический аудит · август 2026

Один лендинг, два города
и девять лет наслоений

Что смотрели
Исходный код, конфигурация, ассеты, логи антиспама, разметка
Объём
3 032 файла, 460 МБ; PHP 5.6+/Apache
Найдено
21 замечание: 3 критичных, 6 высоких, 8 средних, 4 низких
Метод
Статический анализ бэкапа. Боевые серверы не сканировались

Главное


Сайты живые и рабочие: форма заявки, антиспам и почтовая доставка сделаны аккуратно и в целом на хорошем уровне — антиспам за пять дней отсёк 281 ботовое обращение из 291 на московском лендинге. Основная проблема не в логике, а в том, что накопилось вокруг неё за девять лет.

В корне сайтов открыто лежат файлы с заявками клиентов: около 7 800 записей с именами и телефонами за 2017–2026 годы. Их закрывает единственное правило в .htaccess, и как минимум два файла под это правило не попадают — они скачиваются любым человеком, знающим имя файла. Рядом лежит забытая копия всего московского сайта на 156 МБ со своей базой заявок и вообще без защиты.

Вторая по значимости история — аналитика. На петербургском сайте цель «заявка» не отправляется в Метрику вообще: в коде проверяется счётчик московского сайта. Реклама на СПб оптимизируется по данным, которых нет. Плюс на обоих сайтах грузятся два сервиса Google, отключённые ещё в 2023 году.

Остальное — накопленный техдолг: библиотеки 2016–2017 годов, 90 МБ неиспользуемых файлов в корне, 7 МБ картинок в CSS при готовых и никуда не подключённых WebP, разъехавшиеся между городами копии одних и тех же файлов.

УровеньШт.Что это значитСрок
критично3Утечка персональных данных клиентов возможна прямо сейчас, без взлома24–48 часов
высокий6Теряются заявки и рекламные данные; устаревшие компоненты в почтовом тракте1 неделя
средний8Скорость, SEO, устаревшие библиотеки, расхождения между городами2–4 недели
низкий4Гигиена кода, мусор в корне, мелкие несоответствия контентапо возможности

Критично 3 находки · сделать в первую очередь

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

01

База заявок лежит в корне сайта, часть файлов не закрыта вовсе

критично МСКСПб

Заявки пишутся в CSV прямо в каталог сайта. Доступ закрывает одно правило в .htaccess, и оно указывает точное имя файла leads.csv. Файл leads(1).csv на питерском сайте под правило не подпадает — он отдаётся по прямой ссылке любому. Если хостинг когда-нибудь переедет на nginx или .htaccess потеряется при переносе, наружу уйдут все базы разом.

  • public_html/leads.csv — 4 555 заявок, 2017-02-17 … 2026-08-31 (487 КБ)
  • spb.kto-kruche.ru/public_html/leads.csv — 3 244 заявки (357 КБ)
  • spb.kto-kruche.ru/public_html/leads(1).csv — 402 заявки, правилом НЕ закрыт
  • .htaccess: <Files "leads.csv"> Require all denied </Files>
Что делать

Немедленно удалить leads(1).csv с сервера. Перенести хранение заявок на уровень выше public_html (как уже сделано для логов антиспама на СПб) и поменять путь в submit.php. Проверить access_log за последние месяцы — не скачивал ли кто-то эти файлы.

02

Каталог «Новый каталог» — полная копия сайта со своей базой заявок и без защиты

критично МСК

В корне московского сайта лежит папка с русским названием и пробелом — старая копия лендинга целиком: страница, ассеты, node_modules и отдельный файл заявок на 1 436 записей. Её собственный .htaccess содержит только редирект на HTTPS: ни запрета на CSV, ни Options -Indexes. То есть базу можно скачать напрямую, а содержимое папок, возможно, ещё и просматривается списком.

  • public_html/Новый каталог/ — 156 МБ, 10 файлов + node_modules + assets
  • public_html/Новый каталог/leads.csv — 1 436 заявок, 2017-02-17 … 2022-04-25
  • его .htaccess — 151 байт, только RewriteRule на https
  • форма в его index.php шлёт на ./submit.php, которого в папке нет
Что делать

Скачать папку в архив себе, затем удалить с сервера полностью. Ничего рабочего в ней нет — форма там всё равно нерабочая.

03

Старые версии главной страницы отдаются наружу и молча съедают заявки

критично МСКСПб

Рядом с рабочим index.php лежат прошлые версии страницы с тем же <title> и без запрета индексации — поисковики могут показывать их вместо главной. В этих копиях форма старая: без антиспам-токена и без чекбоксов согласия. Обработчик набирает по ним 180 баллов при пороге 60 и отбрасывает заявку — но отвечает браузеру «успешно», чтобы не подсказывать ботам. В результате живой человек, попавший на такую страницу, видит экран «Спасибо за заказ», а заявка не приходит никуда.

  • МСК: /_index.php (54 КБ), /_07_10_index.php (74 КБ)
  • СПб: /_index.php (49 КБ), /08_10_index.php (62 КБ)
  • во всех: anti_spam_token — 0 вхождений, consent_* — 0 вхождений
  • submit.php: if ($isSpam && ANTISPAM_ENFORCE) { echo '1'; exit; }
Что делать

Удалить все старые копии страниц с боевых серверов (архив держать в git, а не в корне сайта). Если какая-то версия нужна для А/Б-теста — закрывать её noindex и подключать актуальную форму.

Высокий риск 6 находок · неделя

Здесь нет мгновенной утечки, но деньги теряются каждый день: на слепой рекламе, на устаревших компонентах в почтовом тракте и на отсутствии базовой защиты HTTP.

04

На питерском сайте цель «заявка» не доходит до Метрики

высокий СПб

После успешной отправки формы код проверяет typeof yaCounter43295234 — это счётчик московского сайта. У СПб счётчик 55626235, и подключён он через современный API ym(), который вообще не создаёт глобальных объектов yaCounter*. Условие никогда не выполняется. Тот же промах в общем файле событий: он на обоих сайтах жёстко настроен на московский идентификатор.

  • spb/assets/js/main.js:286 — if (typeof yaCounter43295234 !== 'undefined')
  • spb/index.php — ym(55626235,"init",{...}), tag.js
  • ingevents.4.0.8.min.js (файл идентичен на обоих сайтах) — idsYM: ['43295234']
Что делать

Заменить вызов на ym(55626235,'reachGoal','lead') и вынести идентификатор счётчика в конфиг страницы, чтобы один и тот же скрипт работал в обоих городах. Проверить, какие цели в кабинете СПб не набирали конверсий, — по ним, скорее всего, велась оптимизация рекламы.

05

Три отключённых сервиса Google грузятся на каждой странице

высокий МСКСПб

Universal Analytics перестала принимать данные 1 июля 2023 года, Google Optimize закрыт 30 сентября 2023-го — оба до сих пор подключены и просто тратят время загрузки. Отдельная путаница на страницах благодарности: у Москвы там другой идентификатор аналитики, чем на главной, а у Питера — два контейнера GTM сразу, то есть конверсии считаются дважды.

  • index.php МСК — UA-181837891-1 + googleoptimize.com/optimize.js?id=OPT-T488BHN
  • index.php СПб — UA-181837891-2 + OPT-TD6SZ57
  • thankyou.php МСК — UA-128955771-1 (не совпадает с главной)
  • thankyou.php СПб — GTM-KSH852NL и GTM-KCBBG75 одновременно
Что делать

Снять UA и Optimize со всех страниц. Оставить по одному контейнеру GTM на город и внутри него — Метрику и, если нужен Google, GA4. Сверить идентификаторы на главной и на странице благодарности.

06

PHPMailer версии 2014 года в почтовом тракте

высокий МСКСПб

Используется PHPMailer 5.2.9 — у этой ветки есть публично известные уязвимости удалённого выполнения кода (CVE-2016-10033 и следующие). Прямо сейчас они не эксплуатируются: адрес отправителя захардкожен, тело письма экранируется, HTML-теги отсекаются антиспамом. Но это единственное, что отделяет от проблемы, — любая будущая правка формы может снять эту защиту незаметно.

  • assets/php/class.phpmailer.php — public $Version = '5.2.9';
  • актуальная ветка — 6.x; 5.2 не поддерживается с 2017 года
  • отправка идёт через mail(), без SMTP-аутентификации
Что делать

Обновить до PHPMailer 6.x (ставится через Composer, правок в submit.php почти не потребует). Заодно перевести отправку на SMTP с аутентификацией — письма с mail() на шаред-хостинге регулярно уходят в спам, а это напрямую потерянные заявки.

07

Нет ни одного заголовка безопасности

высокий МСКСПб

Редирект на HTTPS настроен, но дальше — пусто: нет HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy. Сайт можно поместить в чужой iframe, первый заход по http:// идёт открытым текстом, а сторонние скрипты (а их тут шесть внешних источников) ничем не ограничены.

  • .htaccess: только RewriteRule на https, Options -Indexes и запреты на файлы
  • внешние скрипты: comagic.ru, mango-office.ru, hesus.ru (iframe), cdnjs, jsdelivr, vk.com/rtrg
  • thankyou.php: js-confetti@latest — версия не зафиксирована, без SRI
Что делать

Добавить в .htaccess набор заголовков: Strict-Transport-Security, X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN, Referrer-Policy. CSP — следующим шагом, в режиме report-only, из-за обилия сторонних скриптов. Зафиксировать версию js-confetti вместо @latest.

08

Заявки клиентов уходят на личный ящик разработчика

высокий МСК

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

  • submit.php:191 — $mail->AddAddress('sayfullin-marat97@yandex.com', ...)
  • рабочие адреса: ktokruche.ru@yandex.ru, gabova_katya@mail.ru
Что делать

Убрать тестовый адрес после окончания настройки. На будущее — держать список получателей в config.php, а не в коде обработчика.

09

Персональные данные хранятся без срока и без резервных копий

высокий МСКСПб

Заявки копятся в одном CSV с 2017 года — девять лет имён и телефонов без регламента хранения, что 152-ФЗ прямо не одобряет. Структура файла уже разъехалась (часть строк с 7 и 9 колонками вместо 5), а единственная копия лежит на том же диске, что и сайт. Логи антиспама тоже содержат ПДн: IP, имя, часть телефона и текст комментария.

  • МСК: 4 555 строк — 4 532 по 5 колонок, 13 по 7, 8 по 9, 2 по 4
  • private/antispam-2026-08.log — 103 КБ за 5 дней, ротации и удаления нет
  • на МСК каталог логов внутри вебрута (public_html/private), закрыт только .htaccess
Что делать

Определить с клиентом срок хранения заявок (обычно 1–3 года), удалить более старые. Перенести заявки в БД или в CRM с регулярным бэкапом. Каталог логов на МСК вынести выше public_html, как на СПб, и настроить автоудаление старых файлов.

Средний приоритет 8 находок · 2–4 недели

Скорость загрузки, поисковая выдача и стоимость поддержки. Заметно на конверсии и на счёте за доработки, но не горит.

10

node_modules выложен в продакшн, библиотеки — 2016–2017 годов

средний МСКСПб

Страница подключает файлы напрямую из node_modules: сборки нет, минификации нет, 6,6 МБ пакетов лежит в корне каждого сайта. Версии девятилетней давности: у jQuery 3.1.1 есть известные XSS и prototype pollution, Bootstrap 3 снят с поддержки в 2019-м.

  • jquery 3.1.1 · bootstrap 3.3.7 · jquery-validation 1.16.0
  • fancybox 3.0.0 · slick-carousel 1.6.0 · animate.css 3.5.2 · maskedinput 1.4.1
  • 418 КБ JS/CSS подключается несжатым, отдельными запросами
Что делать

Поднять сборку (в проекте уже лежат gulpfile и webpack.mix.js от старой версии) — один минифицированный бандл вместо тринадцати файлов. Обновить jQuery до 3.7 и проверить fancybox/slick на совместимость. node_modules из корня убрать.

11

88 готовых WebP лежат в проекте и не подключены ни одной строкой

средний МСКСПб

Кто-то уже сконвертировал картинки в современный формат — и работа не доехала до страницы: в index.php ноль упоминаний webp. Одновременно только фоновые изображения в CSS весят почти 7 МБ, а на первом экране Питера грузится 1,8 МБ картинок сразу, без отложенной загрузки.

  • МСК: 88 файлов .webp, ссылок в index.php — 0
  • фоны в main.css: МСК 6,91 МБ · СПб 7,59 МБ (самый тяжёлый — 1 013 КБ)
  • <img> сразу: МСК 0,89 МБ / СПб 1,84 МБ; loading="lazy" — 0; srcset — 0
  • width/height проставлены у 1 картинки из 112 — отсюда «прыжки» вёрстки
Что делать

Подключить WebP через <picture> с JPEG-запасным вариантом, пережать фоны в CSS, добавить loading="lazy" всем картинкам ниже первого экрана и проставить width/height. Это самый дешёвый прирост в Core Web Vitals из возможных.

12

Нет сжатия и кэширования статики

средний МСКСПб

В .htaccess нет ни mod_deflate, ни mod_expires: CSS и JS отдаются несжатыми, у картинок нет Cache-Control. Повторный визит грузит всё заново.

  • main.css 44 КБ + lightgallery 25 КБ + lg-transitions 47 КБ — без gzip
  • заголовков Cache-Control / Expires для статики нет
Что делать

Добавить в .htaccess блоки mod_deflate (или brotli) и mod_expires с длинным сроком для картинок и шрифтов. Пятнадцать строк конфига, эффект на повторных визитах — кратный.

13

90 МБ мусора в корне сайтов

средний МСКСПб

Помимо «Нового каталога» в корне лежат ZIP-архивы с фотографиями (по 16 МБ на сайт, доступны на скачивание) и целый каталог картинок, на который нет ни одной ссылки во всём проекте.

  • public_html/assets/1img — 70 МБ, упоминаний в index/css/js: 0
  • ZIP в вебруте: away.zip, full.zip ×2, child.zip — 17,5 МБ на каждом сайте
  • мелочь: test.txt («wsactual 12/12/18»), пустая папка end/, old_thanks.php, icons/index.html (1 байт)
Что делать

Проверить, что assets/1img действительно не нужен, и удалить. Архивы с фотографиями — в облако, а не в корень сайта. Мелкие артефакты вычистить заодно.

14

SEO: два H1, нет canonical, нет микроразметки

средний МСКСПб

Базовая разметка сделана давно и с тех пор не пересматривалась. Для локального бизнеса с адресом, телефоном, ценой и отзывами отсутствие Schema.org — это прямая потеря расширенных сниппетов в выдаче.

  • <h1> — 2 штуки на странице («Кто круче» и «Посмотри,»)
  • rel="canonical" — нет; Schema.org / JSON-LD — нет
  • meta description — 50 симв. (МСК) и 60 (СПб) при норме 120–160
  • 42 картинки из 112 без alt, ещё часть с alt="img"
  • meta keywords — устаревший тег, поисковиками игнорируется
Что делать

Оставить один H1, добавить canonical, расписать description, проставить осмысленные alt. Разметить Schema.org LocalBusiness с адресом, телефоном, часами и AggregateRating по отзывам.

15

robots.txt и sitemap.xml неактуальны и с ошибками

средний МСКСПб

robots.txt закрывает /thanks.php — страницы с таким именем на сайтах нет, реальная страница благодарности называется /thankyou.php и открыта для индексации. Карта сайта сгенерирована в 2022 году, содержит одну ссылку и начинается с BOM-символа перед XML-декларацией, из-за чего валидаторы считают её некорректной.

  • robots.txt: Disallow: /thanks.php — файла нет; /thankyou.php не закрыт
  • директивы Sitemap: в robots.txt нет ни на одном сайте
  • sitemap.xml: BOM в начале файла, lastmod 2022-05-19, одна страница
Что делать

Переписать robots.txt под реальные имена страниц, добавить директиву Sitemap:. Пересобрать карту сайта без BOM, включить в неё /oferta.php и /policy.php, страницу благодарности закрыть noindex.

16

Один лендинг живёт в двух несинхронных копиях

средний МСКСПб

Города — это два независимых набора файлов, которые уже разошлись: main.js отличается на 96 строк, main.css — на 6 КБ. Любая правка делается дважды, и любая забытая правка превращается в баг ровно того типа, что описан в находке 04.

  • совпадают: anti-spam.php, token.php, PHPMailer, ingevents.js
  • расходятся: index.php, submit.php, main.js (96 строк), main.css, .htaccess
  • московский main.js вызывает ingEvents без проверки существования, питерский — с проверкой
Что делать

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

17

На питерском сайте московский контент

средний СПб

Адрес и карта верные, а вот телефон и отзывы — московские. Динамический коллтрекинг Comagic номер, скорее всего, подменяет, но при выключенном JS и в сообщениях об ошибках формы посетитель видит московский номер.

  • index.php СПб: tel:89585781720 (московский) — 3 вхождения
  • main.js СПб: «Позвоните нам: 8 (958) 578-17-20» в двух сообщениях об ошибке
  • все ссылки на отзывы — в московское сообщество vk.com/topic-140156514_…
  • своё сообщество СПб — vk.com/showigraktokruchespb — в отзывах не используется
Что делать

Вынести телефон и ссылки в конфиг города. Заменить блок отзывов на питерские — заодно это релевантнее для местной аудитории.

Низкий приоритет 4 находки

18

Кодировка объявлена слишком поздно

низкий МСКСПб

Спецификация требует, чтобы <meta charset> уложился в первые 1024 байта документа. Здесь он на 1126-м (МСК) и 1179-м (СПб) — выше него встали GTM, gtag и Optimize. Пока спасает заголовок сервера; при смене хостинга или конфигурации возможны «кракозябры».

Что делать

Поднять <meta charset> и <title> первыми строками <head>, счётчики — сразу после.

19

Битая ссылка на фоновое изображение

низкий МСК

В main.css (строка 333) есть правило с картинкой ../img/main_new/10.JPG, которой в проекте нет — в папке лежат только файлы с 1 по 9. Каждый показ этого блока даёт 404 в логе.

Что делать

Добавить недостающий файл или убрать правило.

20

Нет уведомления об обработке cookie, у документов нет даты редакции

низкий МСКСПб

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

Что делать

Добавить компактное уведомление о cookie со ссылкой на политику. Проставить в документах дату редакции.

21

Ссылка на Instagram в шапке обоих сайтов

низкий МСКСПб

Иконка со ссылкой на Instagram стоит в навигации. Ресурс из России недоступен, а компания-владелец признана в РФ экстремистской — для коммерческого сайта это лишний риск при нулевой пользе: ссылка всё равно никуда не ведёт.

Что делать

Убрать иконку, освободившееся место отдать Telegram или WhatsApp, которые уже есть рядом.

Соседние проекты на том же домене

Отдельная тема, которая напрямую лендингов не касается, но живёт на том же хостинге — а значит, взлом там открывает доступ и к файлам лендингов.

Каталоги game, game2, game3, game4 — это четыре приложения Laravel версии 5.4 на поддоменах game*.kto-kruche.ru. Ветка 5.4 вышла в январе 2017 года и не поддерживается с августа того же года: обновлений безопасности для неё не выходит девятый год.

В game и game4 при этом стоит APP_ENV=local и APP_DEBUG=true — в этом режиме Laravel показывает посетителю полную трассировку ошибки вместе с фрагментами кода и содержимым окружения. Файлы .env с паролями от баз данных лежат в корне этих каталогов, и по структуре папок похоже, что корнем сайта для поддомена служит именно она, а не public/ — тогда .env открыт снаружи. Это нужно проверить на боевом сервере: в бэкапе судить об этом можно только косвенно.

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

Что сделано хорошо

Чтобы картина была честной: свежая часть кода — антиспам и обработчик формы — сделана заметно лучше, чем всё, что вокруг неё.

  • Антиспам реально работает. С 26 по 31 августа на МСК отсечено 281 обращение из 291, на СПб — 5 из 12. Основные срабатывания: прямой POST без токена и без согласий.
  • Токен подписан HMAC-SHA256 и содержит метку времени — по ней же считается скорость заполнения формы. Секрет в JavaScript не попадает, у двух сайтов секреты разные.
  • Ботам отвечают «успешно». Заявка отбрасывается молча, бот не понимает, что его отсекли, и не начинает подбирать обход.
  • Защита от CSV-инъекций: значения, начинающиеся с =, +, -, @, экранируются — формула из поля «Имя» не выполнится при открытии файла в Excel.
  • Телефон проверяется по количеству цифр, а не по маске: если маска не загрузится, сервер не начнёт резать живые заявки.
  • Ошибки формы обработаны: кнопка разблокируется, текст ошибки показывается, протухший токен отдаёт 419 и просьбу обновить страницу вместо молчаливой потери заявки.
  • Ограничение частоты по IP с файловой блокировкой, и при собственном сбое лимитер пропускает заявку, а не режет её.
  • Никаких закладок: ни eval, ни shell_exec, ни забытых .git и .env в корне лендингов.
  • Принудительный HTTPS, отключённый листинг каталогов и закрытые config.php, anti-spam.php, *.log, *.json.
  • На СПб логи антиспама вынесены выше вебрута — правильное решение, которое осталось перенести на московский сайт.

Предложение по работам

Порядок продиктован не сложностью, а тем, что происходит, если ничего не делать. Этапы 0 и 1 закрывают риски, 2 и 3 — возвращают деньги.

Этап 024–48 часов

Закрыть утечку персональных данных

  1. Удалить с серверов leads(1).csv, каталог «Новый каталог», старые копии _index.php / _07_10_index.php / 08_10_index.php, ZIP-архивы фотографий.
  2. Перенести leads.csv и каталог логов антиспама выше public_html, поправить пути в submit.php и config.php.
  3. Убрать тестовый адрес разработчика из списка получателей.
  4. Просмотреть access_log за доступный период на предмет скачиваний CSV.
Этап 11 неделя

Вернуть аналитику и закрыть базовые дыры

  1. Починить цель «заявка» на СПб, вынести идентификаторы счётчиков в конфиг города.
  2. Снять UA и Google Optimize, оставить по одному контейнеру GTM на город, сверить страницы благодарности.
  3. Обновить PHPMailer до 6.x, перевести отправку на SMTP с аутентификацией.
  4. Добавить заголовки безопасности, зафиксировать версии внешних скриптов.
  5. Проверить и при необходимости закрыть .env и режим отладки на поддоменах game*.
Этап 22–3 недели

Скорость и поисковая выдача

  1. Подключить готовые WebP, добавить lazy, srcset, width/height, пережать фоны в CSS.
  2. Включить сжатие и кэширование статики в .htaccess.
  3. Собрать один бандл вместо тринадцати файлов из node_modules, обновить jQuery и плагины.
  4. Вычистить 90 МБ неиспользуемых файлов.
  5. Один H1, canonical, description, alt, Schema.org LocalBusiness, переписанные robots и sitemap.
Этап 3месяц

Убрать причину, а не симптомы

  1. Свести два города к одному шаблону с конфигом города; завести git-репозиторий.
  2. Перевести заявки из CSV в базу или CRM: бэкапы, срок хранения, выгрузка для менеджеров.
  3. Регламент хранения ПДн, уведомление о cookie, даты редакции документов.
  4. Заменить питерский контент на питерский: телефон, отзывы, ссылки на сообщества.

Как проверяли. Статический разбор резервной копии обоих сайтов: 3 032 файла, 460 МБ. Читали исходники PHP и JavaScript, конфигурацию Apache, разметку страниц, CSS и структуру ассетов, а также рабочие логи антиспама за 26–31 августа 2026 года. Все находки подтверждены конкретными строками в файлах — номера и пути указаны в блоках с доказательствами.

Чего мы не делали. Боевые серверы не сканировались, тестовых проникновений не проводилось, файлы не изменялись. Часть выводов о поддоменах game* сделана по структуре каталогов и требует проверки на работающем сервере. Оценка скорости загрузки — расчётная, по весу файлов; замеры Core Web Vitals на живых сайтах не снимались.