Mixed Content: как найти и исправить HTTP-ресурсы на HTTPS-сайте
Mixed Content: как найти и исправить HTTP-ресурсы на HTTPS-сайте
Mixed content — это ситуация, когда SSL/TLS проверку-страница подгружает ресурсы (изображения, скрипты, стили, iframes) по HTTP. Современные браузеры либо блокируют такие ресурсы (active mixed content — скрипты, стили), либо показывают предупреждение (passive — картинки, медиа). В статье разберём, как автоматически найти все проблемы, исправить их в коде и отловить новые через Content-Security-Policy.
Active vs Passive mixed content: что блокируется
Браузеры различают два типа:
- Active (blockable):
<script>,<link rel="stylesheet">,<iframe>, XHR/fetch, WebSocket. Блокируется полностью — в консоли ошибка «Mixed Content: The page was loaded over HTTPS, but requested an insecure resource». - Passive (upgradable):
<img>,<audio>,<video>. С 2020 года Chrome автоматически апгрейдит их до HTTPS, и если сервер не отвечает — картинка просто не грузится.
Результат одинаково плох: сломанный дизайн, нерабочие скрипты аналитики, замок в адресной строке превращается в «не защищено». Пользователь уходит.
Как найти mixed content за 5 минут
Самый быстрый способ — DevTools в Chrome:
- Откройте страницу, F12 → Console.
- Фильтр «Issues» или поиск по «Mixed Content».
- Вкладка Security покажет статус TLS и список небезопасных ресурсов.
Для массовой проверки всего сайта используйте:
# grep по исходникам
grep -rn "http://" public/ --include="*.html" --include="*.js" --include="*.css"
# либо crawl с проверкой
wget --spider -r -l 3 --no-verbose https://example.com 2>&1 | grep "http://"
Онлайн-инструменты: Enterno.io Security Scanner найдёт mixed content, устаревшие cipher suites и проблемы с заголовками за один скан. Также проверьте рендер страницы через SSL Checker.
Исправление: правильные URL
Золотое правило — всегда использовать протокол-относительные или абсолютные HTTPS-URL:
<!-- Плохо -->
<img src="http://cdn.example.com/logo.png">
<script src="http://analytics.com/tracker.js"></script>
<!-- Хорошо -->
<img src="https://cdn.example.com/logo.png">
<script src="https://analytics.com/tracker.js"></script>
<!-- Допустимо (унаследует протокол страницы) -->
<img src="//cdn.example.com/logo.png">
Протокол-относительный синтаксис (//cdn...) сегодня считается устаревшим — явно указывайте https://. Это улучшает читаемость и не ломается при открытии файла из локальной файловой системы.
Автоматическая починка: upgrade-insecure-requests
Если в коде сотни HTTP-ссылок и переписать всё сразу нельзя — добавьте CSP-директиву, которая автоматически апгрейдит все запросы до HTTPS:
# HTTP-заголовок (предпочтительно)
Content-Security-Policy: upgrade-insecure-requests
# Или в meta
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
Важно: upgrade-insecure-requests работает только если целевой сервер отвечает по HTTPS. Иначе ресурс всё равно не загрузится — просто ошибка будет уже не «mixed content», а «net::ERR_SSL_PROTOCOL_ERROR». Используйте как временное решение, пока чистите код.
Блокировка и отчёты через CSP
Более строгий вариант — директива block-all-mixed-content (заменена на upgrade-insecure-requests в современных браузерах, но работает как fallback):
Content-Security-Policy: block-all-mixed-content; report-uri /csp-report
С report-uri или report-to вы получите JSON-отчёт о каждом нарушении. Это лучший способ найти mixed content, спрятанный в редко используемых разделах сайта или в пользовательском контенте. Подробнее о CSP — в статье «HSTS и preload» и разделе о заголовках в Security Scanner.
Частые источники mixed content
- Хардкод в базе данных: старые записи в WordPress/CMS с
http://в img src. Решение — SQL-миграция:UPDATE posts SET content = REPLACE(content, 'http://example.com', 'https://example.com'). - Сторонние виджеты: старые версии YouTube embed, Vimeo, аналитики. Обновите embed-код.
- CDN без HTTPS: редко, но встречается. Смените CDN или купите сертификат.
- Внутренние API документацию: фронтенд ходит на
http://api.example.com. Настройте HTTPS на всех внутренних эндпоинтах. - Пользовательские изображения: загруженные когда-то на HTTP-хостинги. Прокси через ваш домен или пере-загрузите.
Проверка после фикса
После исправлений прогоните:
- DevTools Console — не должно быть ни одного «Mixed Content» warning.
- Enterno.io Security Scanner — оценка A.
curl -sI https://example.com | grep -i content-security-policy— заголовок на месте.- мониторинг сайтов CSP report-uri — отсутствие новых нарушений в течение недели.
Часто задаваемые вопросы
Изображение по HTTP ломает безопасность сайта?
Напрямую — нет, passive mixed content не даёт атакующему выполнить код. Косвенно — да: он может подменить картинку (например, логотип банка) или использовать для трекинга. Современные браузеры поэтому всё равно апгрейдят всё до HTTPS.
Мой сторонний виджет отдаёт iframe по HTTP — что делать?
Он будет заблокирован полностью. Свяжитесь с провайдером и потребуйте HTTPS. Если это legacy-сервис без HTTPS — ищите альтернативу, CSP ничем не поможет.
Можно ли отключить проверку mixed content в браузере?
В Chrome можно кликнуть на замок → «Site settings» → «Insecure content: Allow», но только для своего браузера и только для диагностики. В проде это не помогает.
upgrade-insecure-requests работает для XHR/fetch?
Да, для всех типов запросов со страницы, включая fetch, XHR, WebSocket. Но не для навигации пользователя по ссылкам — там нужен HSTS.
Заключение
Mixed content чинится за час: найдите HTTP-ссылки через DevTools или crawler, замените на HTTPS, включите upgrade-insecure-requests и CSP-reporting для защиты от регрессий. Security Scanner enterno.io покажет все проблемы безопасности страницы за один клик, а Monitors зафиксирует ухудшение заголовков после очередного деплоя.
Спецификация CSP — W3C CSP3. Mixed Content — W3C Mixed Content. Проверка — Mozilla Observatory.
Проверьте ваш сайт прямо сейчас
Проверить →