Инцидент eMudhra: Go закрыл дыру за 7,5 часа — что делать в 2026
PrimeCoder · 2026 · формат: news
Что произошло, почему это важно и что взять в работу.
Security-релизы рантайма теперь выходят за часы, и это обязывает пересобрать все Go-бинарники, а не просто обновить систему.
Связанные услуги: каталог, AI Boost Team, стать клиентом.
Семь с половиной часов, или новая скорость патчей
17 октября 2026 года Mozilla занесла в OneCRL восемь промежуточных сертификатов eMudhra. 19 октября вышли Go 1.27.3 и 1.26.10. Между первым сообщением о проблеме и опубликованным релизом прошло меньше семи с половиной часов.
Для владельца бизнеса это выглядит как новость из чужой жизни: какие-то сертификаты, какой-то удостоверяющий центр в Индии, язык Go где-то на бэкенде. Только вот Go сегодня держит платёжные шлюзы, интеграции с банками, сервисы доставки, внутренние API у огромного числа российских компаний. И весь этот парк надо пересобрать. Не обновить сервер. Пересобрать.
Причина скучная и потому неприятная: приватные ключи восьми промежуточных CA eMudhra оказались меньше 256. Среди значений, которые потом обсуждали публично, были 4, 56 и 115. Нормальный приватный ключ для P-384 это случайное число длиной около сотни десятичных цифр. Ключ длиной в три цифры восстанавливается из публичного сертификата перебором на ноутбуке. Дальше владелец такого ключа выпускает валидный TLS-сертификат на любой домен, и клиент, доверяющий корню eMudhra или кросс-подписи Sectigo, его примет. Это готовый перехват трафика, без взлома и без эксплойта.
Хроника: четыре дня от сигнала до релиза
| Дата (2026) | Что произошло |
|---|---|
| 17 октября | Исследователь пишет Apple, Google, Microsoft, Mozilla и самой eMudhra. Mozilla в тот же день сама восстанавливает ключи и блокирует восемь промежуточных CA через OneCRL. Chrome блокирует их в день сообщения. |
| 18 октября | eMudhra отзывает сертификаты. |
| 19 октября | Подключается Apple. Выходят Go 1.27.3 и 1.26.10. |
| 20 октября | Microsoft. Утром независимые исследователи раскрывают слабость ключей публично. |
| 26 октября | Roland Shoemaker из команды безопасности Go публикует разбор инцидента. |
| 27 октября | Удаление корня eMudhra из Chrome Root Store доходит до пользователей. |
Внутри 19 октября всё уложилось в один рабочий день по тихоокеанскому времени. В 11:45 внешний исследователь сообщает Go Security о неанонсированных действиях Mozilla. В 12:30 Mozilla пишет сама и просит не раскрывать детали, но выпустить патч как можно скорее. К 14:00 патч готов, исследователь присылает тестовые сертификаты, подписанные восстановленными ключами. В 15:00 начинается выпуск, в 19:13 релиз опубликован. Сама сборка и публикация заняли чуть больше четырёх часов.
Анонс намеренно сделали расплывчатым: Go «блокирует доверие небольшому набору промежуточных сертификатов из-за конкретных проблем с их эксплуатацией». Защищающиеся получили сигнал обновиться. Атакующие не узнали, что именно искать.
«Слабый» здесь значит буквально следующее: каждый из восьми приватных ключей меньше 256.
Что было до: у Go не было режима «срочно»
Политика безопасности Go знала два трека. PUBLIC для мелочей, которые чинят в обычных минорных релизах. PRIVATE для серьёзных уязвимостей: исправление готовят закрыто, релиз анонсируют за 3–7 дней. Такой график работал годами, потому что у админов было время на планирование окна обновления.
Случай eMudhra в это окно не влезал. Ключ, который восстанавливается за микросекунды, не ждёт неделю приватной подготовки. Появился трек URGENT: ситуация, когда эксплуатация вот-вот начнётся и предупреждать заранее некогда. Релиз 19 октября стал первым прогоном этого трека, и первый блин показал узкие места релизного процесса. Пока выпуск занимал дни, они не мешали. Теперь мешают, и команда их устраняет.
Одно предложение из разбора стоит внимания: анонсировать URGENT-релизы в момент старта процесса, чтобы у пользователей оставалось хотя бы несколько часов на подготовку. Практический вывод простой. Подпишитесь на golang-announce. Если ваш сервис собран на Go, рассылка про новые версии перестаёт быть шумом.
Почему на Linux нечем было закрыть дыру
Проверка сертификатов в Go зависит от платформы, и это ключевая деталь всего сюжета.
На Windows и macOS crypto/x509 передаёт проверку цепочки системе, через CryptoAPI и Security.framework. Когда Microsoft и Apple выкатили отзыв, Go-программы получили его сами, без пересборки.
На Linux системного API для проверки цепочек нет. Go берёт корни из системного хранилища (/etc/ssl/certs/...) и проверяет цепочку своим верификатором внутри бинарника. Списки отзыва CRL и OCSP он не проверяет. Значит, никакой отзыв сертификата на уровне ОС на Go-программу не действует. Закрыть дыру можно было только новым рантаймом, который жёстко запрещает цепочки через скомпрометированные промежуточные CA.
Обновление пакета ca-certificates помогает частично. В Debian исправление вышло (20250419+deb13u1 для trixie, 20250419~deb12u2 для bookworm). В distroless- и scratch-образах, куда хранилище корней скопировано на этапе сборки, обновлять нечего: образ придётся пересобрать.
Кому что делать
| Где крутится сервис | Действие |
|---|---|
| Windows, macOS | Отзыв приходит с обновлением ОС. Пересборка не обязательна, но версию тулчейна всё равно проверьте. |
| Linux, обычный образ | Пересобрать бинарники на Go 1.27.3 / 1.26.10 или новее. Обновить ca-certificates. |
| Distroless, scratch | Пересобрать образ: корни вшиты на этапе сборки. |
| Go 1.25 и раньше | Исправления не будет. Апгрейд тулчейна и пересборка. |
Обновить рантайм на сервере недостаточно
Вот та самая мысль, ради которой стоит читать этот разбор целиком. Верификатор зашит в бинарник. Пока вы не пересобрали сервис новым тулчейном, в нём живёт старый код, доверяющий слабому промежуточному CA. Пропатченный Go на соседней машине вашего бинарника не касается.
Пересобирать нужно всё, что ходит по TLS: напрямую через net/http и crypto/tls, через gRPC, через SDK облаков, через драйверы баз данных. Внешне это выглядит как рутина про «обновите зависимости», а по факту это инвентаризация всего, что вы собираете и куда деплоите.
- Проверьте, чем собран бинарник. go version -m ./bin/my-service покажет тулчейн, которым он собран. go version покажет версию на машине сборки.
- Прогоните govulncheck по готовым бинарникам, не по исходникам: GOTOOLCHAIN=go1.27.3+auto go install golang.org/x/vuln/cmd/govulncheck@latest, затем govulncheck -mode=binary ./bin/my-service. Проверка по артефакту ловит то, что исходники уже не помнят.
- Пройдитесь по парку разом. Обход каталогов с go version по каждому файлу и сортировкой по версии даёт список того, что отстало. Для десятка сервисов это минуты, для сотни — вечер, зато без догадок.
- Пересоберите базовые образы и прогоните CI заново. Образ, собранный полгода назад, содержит ровно те корни, которые были полгода назад.
Отдельно про масштаб. В логах Certificate Transparency сертификатов, выпущенных шестью TLS-интермедиатами eMudhra, нет. Активной эксплуатации на момент разбора не обнаружено. Это не повод расслабиться: отсутствие следов в CT и отсутствие атаки это разные вещи, а ключ, который перебирается за секунды, оставляет мало следов.
Где подвох
Первый риск связан с самим треком URGENT. Если такие релизы станут нормой, обновление Go превратится из планового события в пожарную тревогу. Инженерная команда из трёх человек не может жить в режиме «патч вышел в 19:13, пересобери всё до утра». Значит, нужен регламент: кто читает golang-announce, кто собирает список бинарников, кто отвечает за пересборку в нерабочее время. Без этого срочный релиз рантайма превращается в срочный простой.
Второй риск в иллюзии «мы обновили систему». Обновлённый ca-certificates в Debian, свежий пакет в apt, зелёный статус в мониторинге. На Linux этого мало, и это неочевидно для тех, кто привык к миру, где проверка цепочек делегирована ОС.
Третий риск: кросс-подписи. У каждого из восьми промежуточных CA eMudhra была кросс-подпись от корня Sectigo AAA Certificate Services. Простое удаление корня eMudhra ничего не решает, потому что цепочка сойдётся через Sectigo. Именно поэтому Go блокировал не корень, а сами промежуточные сертификаты по SPKI.
Четвёртый: старые версии. Go 1.25 и более ранние исправления не получат вообще. Если у вас на проде сервис, собранный три года назад и с тех пор не трогавшийся, у него нет ни патча, ни плана апгрейда. Это отдельная задача, и она не решается в день инцидента.
Вердикт
Семь с половиной часов от сообщения до релиза это хорошая новость про мейнтейнеров Go и плохая новость про процессы у всех остальных. Рантайм теперь отвечает за безопасность за часы. Ваша инфраструктура отвечает за пересборку за дни, недели или никогда.
Что делать на этой неделе, без героизма. Подписаться на golang-announce. Прогнать go version -m по всем своим бинарникам и увидеть реальную картину: сколько из них собрано на версиях, которые уже не получат патчей. Завести привычку хранить версию тулчейна в метаданных релиза, чтобы в следующий раз не искать её по сусекам. Пересобрать сервисы на 1.27.3, 1.26.10 или новее. Для distroless-образов запланировать пересборку отдельным пунктом, а не «когда будет время».
И держать в голове простое правило. ОС можно обновить. Бинарник Go можно только пересобрать. Пока вы этого не сделали, в проде работает старый верификатор со старыми довериями, и никакой патч на сервере этого не изменит.