Внешний аудит Cortex не нашёл critical- или high-уязвимостей, но обнаружил семь способов нарушить изоляцию, раскрыть секреты или истощить ресурсы кластера. Главный вывод для платформенной команды: severity отдельного бага не равна риску всей системы. Если внутреннему клиенту доступен служебный gRPC или management endpoint, «средняя» находка может превратиться в запись метрик от имени соседнего tenant или утечку ключей к backend.

3 августа Daniel Blando, maintainer Cortex, опубликовал итоги проверки в блоге CNCF. Материалы Linux Foundation доступны по CC BY 3.0; эта русская адаптация сокращает анонс, сверяет его с техническим отчётом Quarkslab и добавляет план действий для операторов. Проверка актуальности выполнена 4 августа 2026 года.

Что именно проверяли

Cortex хранит метрики многих клиентов в одном распределённом контуре. Tenant ID ограничивает чтение и запись series, rules и конфигураций Alertmanager. Поэтому аудиторы исследовали не абстрактное «качество безопасности», а конкретную границу доверия: может ли один tenant воздействовать на данные другого и может ли внутренний компонент нарушить работу кластера.

Два специалиста Quarkslab провели white-box review коммита b4f5cfc37d83: изучили threat model, выполнили статический анализ и динамические тесты. В scope вошли ingestion и query paths, gossip/memberlist, runtime configuration и debug endpoints. Такой scope важен: отчёт подтверждает состояние выбранного коммита и выбранных путей, но не доказывает безопасность любой конфигурации Cortex или окружающей инфраструктуры.

Результат — шесть находок уровня medium и одна low. Аудиторы оценили общий уровень как satisfying: код структурирован, критические пути покрыты тестами, а exploitation большинства проблем требует внутреннего доступа. Последняя оговорка не должна успокаивать. В multi-tenant платформе tenant, sidecar, соседний namespace или скомпрометированный Pod уже могут оказаться тем самым «внутренним» субъектом.

Tenant boundary сломался на обходном пути

Самая важная находка касалась streaming gRPC PushStream. Обычный путь строил доверие вокруг аутентифицированного tenant, но сообщение в stream несло собственный TenantID. Обработчик доверял этому полю, поэтому caller с доступом к ingester gRPC мог отправить samples в пространство другого tenant.

Это типичный архитектурный сбой: проверка существовала, но не охватывала новый транспорт. Unary write подписывался, streaming RPC оставался вне того же механизма. Исправление в Cortex проверяет tenant на стороне distributor до отправки сообщения и усиливает stream-push подпись. Maintainers выбрали другой дизайн, чем первоначально предложили аудиторы, но Quarkslab подтвердил эквивалентное свойство безопасности.

Оператору важно проверить не только версию, но и topology. Если distributor gRPC доступен клиентским сетям напрямую, старый Cortex имел более широкий attack surface. После обновления ограничьте service и NetworkPolicy так, чтобы внутренние RPC принимались только от ожидаемых компонентов. Auth gateway для публичного remote write не заменяет сегментацию служебных портов.

Служебный /config оказался хранилищем секретов

Вторая эксплуатационно опасная группа — management endpoints. /config сериализовал runtime configuration в YAML. Часть credential fields уже использовала маскирующий тип, но пароли Swift, etcd, Redis и HTTP basic auth оставались обычными строками и возвращались открыто.

Исправление переводит эти поля в тип, который редактирует значение при выводе. Но redaction не превращает endpoint в публичный API. Конфигурация раскрывает topology, адреса сервисов, feature flags и другие данные, полезные атакующему даже без паролей.

Проверьте маршрут до management listener из трёх точек: интернета, tenant namespace и administrative namespace. Ожидаемый результат — доступ только из операционного контура через аутентифицированный proxy или закрытую сеть. После обновления отдельно убедитесь, что чувствительные поля замаскированы; не сохраняйте полный ответ /config в CI-логи и тикеты.

Лимиты памяти — часть security boundary

Три medium-находки превращали входные данные в неограниченное потребление ресурсов:

  • gzip payload мог разжиматься за пределы ожидаемого размера;
  • protobuf histogram мог запросить чрезмерное число buckets и память под них;
  • memberlist connection позволял читать пакет без достаточного ограничения размера и времени.

Cortex v1.21.1 добавил предел decompressed message, ограничение native histogram и параметры для размера пакета, read timeout и числа параллельных memberlist connections. Это не просто performance tuning. В multi-tenant системе отсутствие верхней границы позволяет одному клиенту отнять память и CPU у остальных.

Не копируйте defaults вслепую. Снимите распределение реальных request sizes и histogram sizes, выберите лимит выше нормального p99 с небольшим запасом, затем проверьте controlled rejection. Слишком высокий предел сохраняет DoS-риск, слишком низкий превращает корректную телеметрию в потерянные samples. Алерт должен отличать rejected input от OOM и общей перегрузки distributor.

Gossip и status UI тоже входят в модель угроз

Low-находка в memberlist показывала, что пакет с неверным integrity digest логировался, но не отбрасывался. Отдельная medium-находка позволяла crafted peer name попасть в status page без HTML escaping. Обе проблемы требуют доступа к внутреннему gossip-контуру, однако именно там компоненты принимают решения о membership и маршрутизации.

В v1.21.1 пакеты с неверной подписью отбрасываются, а status pages используют auto-escaping template. Официальный разбор Cortex также рекомендует включить -memberlist.encryption-enabled=true, если gossip пересекает недоверенную сеть. Шифрование не отменяет NetworkPolicy: оно защищает сообщение, а сегментация сокращает число тех, кто вообще может подключиться.

Обновление закрывает код, но не конфигурацию

Все семь исправлений вошли в Cortex v1.21.1. На 4 августа это последний опубликованный release. План rollout для production-кластера должен выглядеть так:

  1. Зафиксируйте фактическую версию и digest образа каждого Cortex component, а не только значение Helm chart.
  2. Сопоставьте доступ к public HTTP, internal gRPC, memberlist и management listeners с источниками трафика.
  3. Обновитесь минимум до v1.21.1 через обычный canary или поэтапный rollout; заранее прочитайте release notes и проверьте deprecated flags.
  4. Подтвердите tenant isolation тестом из отдельного тестового tenant: чужая запись и чтение должны завершаться отказом, а собственный поток — работать.
  5. Проверьте redaction /config, закрытость endpoint и отсутствие старых ответов в логах, артефактах CI и системах поддержки.
  6. Нагрузите ingestion крупными, но допустимыми payloads и гистограммами; убедитесь, что лимиты отклоняют превышение без OOM и cascading restart.
  7. Наблюдайте rolling window за rejected requests, gRPC errors, memberlist failures, restarts и расхождением ingestion rate между tenants.

Rollback на уязвимую версию нельзя считать безопасным стандартным выходом. Если новая версия ломает workload, заранее подготовьте вариант остановить rollout, изолировать несовместимый input или временно отключить проблемный путь, не возвращая прежнюю tenant boundary.

Ограничения аудита

Проверка длилась с 30 марта по 16 апреля и была привязана к одному commit. Она не охватывает ваш ingress, identity provider, Kubernetes RBAC, object storage policy, service mesh и секреты в Helm values. Статус «все findings исправлены» означает, что аудиторы проверили remediation в upstream; он не подтверждает, что ваш cluster использует нужный image и не экспонирует лишние endpoints.

Главный урок Cortex шире одного проекта. В distributed platform граница tenant проходит через каждый transport, serializer и debug page. Security review должен искать не только отсутствующую аутентификацию, но и обходные пути, неограниченное выделение памяти и служебные интерфейсы. Обновление до v1.21.1 закрывает найденные дефекты; доказательство безопасной эксплуатации начинается после обновления — с сетевой карты, негативных тестов и наблюдаемого rollout.