Смешанный контент: остатки http:// внутри страницы на https://
Почему одна забытая картинка или скрипт по http:// сводит на нет защиту HTTPS-страницы, что браузеры блокируют или тихо переводят на https и как навести порядок раз и навсегда.
Безопасность · Опубликовано: 25 сентября 2026 г. · 6 мин чтения · Дмитрий Орлов
Перевести сайт на HTTPS — дело одного дня: получить сертификат, настроить редирект с 80-го порта, готово. А потом на половине страниц не появляется замок, перестаёт работать слайдер или шрифт молча откатывается на Arial. Сама страница пришла по https://, но что-то внутри неё всё ещё запрашивает http://. Это и есть смешанный контент (mixed content).
Почему один запрос по http:// имеет значение
HTTPS защищает страницу целиком только тогда, когда каждый её байт пришёл по зашифрованному соединению. Один скрипт, загруженный по обычному HTTP, может прочитать и подменить любой, кто находится на пути: открытый Wi-Fi, взломанный роутер, провайдер, вставляющий рекламу. Подменённый скрипт работает с полным доступом к странице: читает поля форм, переписывает ссылки, крадёт данные сессии. Шифрование самого HTML-документа после этого ничего не значит.
Браузеры делят смешанный контент на две группы — по тому, какой вред он может нанести.
- Активный (блокируемый) контент: скрипты, стили, iframe, шрифты, запросы
fetchи XHR, воркеры. Всё, что может изменить страницу или прочитать из неё данные. Современные браузеры блокируют его полностью: запрос не отправляется, в консоли появляется ошибка. - Пассивный (обновляемый) контент: изображения, аудио и видео. Худшее, что может сделать злоумышленник, — подменить картинку. Актуальные Chrome и Firefox вообще больше не загружают такие ресурсы по HTTP: они автоматически переписывают адрес на https://, а если по HTTPS ресурс недоступен, он просто не загружается.
Старые браузеры и некоторые встроенные веб-представления по-прежнему показывают пассивный смешанный контент как есть и помечают страницу как не полностью защищённую — отсюда и пропавший или перечёркнутый замок.
Формы — отдельная история. <form action="http://..."> на HTTPS-странице отправляет введённые данные в открытом виде. Браузеры предупреждают перед отправкой такой формы, и предупреждение выглядит настолько тревожно, что многие просто бросают заполнение.
Откуда он берётся
Почти любая проблема со смешанным контентом — наследие времён до переезда.
- Жёстко прописанные адреса в базе CMS. Редакторы вставляли картинки, пока сайт жил на HTTP, поэтому тексты записей, виджеты и настройки до сих пор содержат
http://example.com/uploads/.... Смена адреса сайта в админке не трогает уже сохранённый контент. - Старые встраивания. Видеоплееры, карты, счётчики и виджеты чатов, вставленные годы назад с адресом http://. Часть этих сервисов давно работает по HTTPS, часть уже не существует.
- CSS.
background-image: url(http://...)в таблице стилей или в инлайновом атрибутеstyle, а также@font-face, указывающий на хостинг шрифтов по HTTP. - Адаптивные изображения.
srcисправили, а вsrcsetостались варианты с http://, и на экране с высокой плотностью пикселей браузер может выбрать именно их. - Шаблоны и JavaScript. Тема, которая собирает абсолютные адреса с жёстко заданной схемой, или скрипт, который подгружает ресурсы по
http://уже во время работы страницы.
Как его найти
DevTools. Откройте страницу, откройте консоль, перезагрузите. Каждый запрос со смешанным контентом попадёт туда с точным адресом и пометкой, заблокирован он или переведён на https. В панели Network в Chrome фильтр mixed-content:all оставит в списке только такие запросы. Этот способ работает для одной страницы за раз.
Статический HTML. Быстрый первый проход по разметке:
curl -s https://example.com/ | grep -Eo '(src|href|srcset|action)="http://[^"]+"'
Адреса в CSS-файлах и те, что добавляет JavaScript, он не увидит, но большую часть наследия CMS поймает.
Отчёты CSP. Чтобы найти смешанный контент по всему сайту на реальном трафике, отдавайте политику в режиме report-only, которая разрешает только источники по HTTPS:
Content-Security-Policy-Report-Only: default-src https: data: blob: 'unsafe-inline' 'unsafe-eval'; report-uri /csp-report
Ничего не блокируется, но каждая загрузка по http:// порождает отчёт с адресом страницы и ресурса. Учтите, что upgrade-insecure-requests в политике report-only не действует, а старая директива block-all-mixed-content объявлена устаревшей: современные браузеры и так блокируют активный контент по умолчанию.
Отчёт SiteScan тоже это проверяет: он помечает каждую просканированную страницу, которая загружает ресурсы по http://, в пункте «Serve every asset over https://».
Как исправить
Используйте https:// или относительные адреса. Для собственных ресурсов самый надёжный вариант — путь вида /uploads/photo.jpg: он подхватывает схему и домен страницы. Для сторонних ресурсов переключитесь на https:// и проверьте, что сервис действительно отдаёт их по HTTPS. Если нет — замените ресурс или разместите его у себя.
Поиск и замена в базе — аккуратно. Сначала резервная копия. В WordPress используйте WP-CLI, а не голый SQL, потому что он правильно обрабатывает сериализованные данные PHP:
wp search-replace 'http://example.com' 'https://example.com' --all-tables --dry-run
Когда цифры выглядят правдоподобно, запустите ещё раз без --dry-run. Обычный SQL REPLACE меняет длину строк внутри сериализованных значений и может испортить настройки виджетов и плагинов.
Добавьте upgrade-insecure-requests как страховку. С этим заголовком браузер переписывает каждый подресурс с http:// на https:// ещё до запроса:
Content-Security-Policy: upgrade-insecure-requests
Это страховка, а не исправление: если у хоста нет HTTPS, запрос просто завершится ошибкой, а адреса с http:// останутся в контенте и в RSS-лентах.
Включайте HSTS, когда сайт уже чист. Strict-Transport-Security: max-age=31536000; includeSubDomains говорит браузеру больше никогда не обращаться к вашему домену по HTTP. Начните с небольшого max-age и увеличивайте его, когда убедитесь, что все поддомены работают по HTTPS.
Чек-лист
- В консоли нет предупреждений о смешанном контенте на основных шаблонах.
- Нет адресов http:// в
src,href,srcset,actionи CSSurl(). - Старые адреса в базе заменены инструментом, который не ломает сериализацию.
- Сторонние встраивания грузятся по HTTPS или удалены.
upgrade-insecure-requestsнастроен как страховка.- HSTS включён после того, как всё перечисленное выше приведено в порядок.
Читайте также
Проверьте, что из этого есть на вашем сайте
Бесплатное сканирование покажет битые ссылки, ошибки JS и проблемы производительности за минуту.