Модуль NGINX JavaScript (njs) представляет атрибуты XML не так, как библиотека libxml2 при канонизации, то есть при приведении документа к единому виду перед проверкой электронной подписи. Расхождение возникает, если атрибут опирается на внутреннюю сущность, описанную внутри самого документа. Проверка подписи в таком случае проходит успешно, а сам атрибут выглядит отсутствующим или усечённым. Развёртывания nginx-saml из-за этого теряют контроль над сроком действия, адресатом сообщения и корреляцией запросов. Уязвимость зарегистрирована как CVE-2026-101019 и отнесена к классу CWE-436, конфликт интерпретаций.
CVE-2026-101019 в NGINX JavaScript и последствия для SAML
Проблема затрагивает XML-модуль njs и проявляется в обоих движках: во встроенном njs и в QuickJS. Во время канонизации обращение к атрибуту по имени может вернуть неопределённое значение, хотя атрибут в документе явно присутствует и содержит ссылку на внутреннюю сущность. Обращение ко всему набору атрибутов иногда возвращает значение, построенное только по первому дочернему элементу. Проще говоря, приложение, читающее подписанный XML, видит не тот набор данных, который проверяла подпись.
Как проявляется расхождение
Внутренние сущности нужны, чтобы описывать повторяющиеся фрагменты XML внутри одного документа. Канонизация обязана развернуть их единообразно, и libxml2 это делает. Модуль njs ведёт себя иначе, поэтому один и тот же документ получает две разные трактовки. Этим и пользуется злоумышленник: значимые для безопасности атрибуты выглядят пропавшими или обрезанными, а подпись остаётся действительной.
Ограничение тут существенное. Для эксплуатации нужен по-настоящему подписанный документ, добыть который без серьёзных усилий не получится. Подделать подпись или чужую личность такой уязвимостью нельзя, доступность сервисов она тоже не подрывает. Речь идёт только о логике проверки. В nginx-saml со встроенным движком njs разработчики подтверждают влияние: обходятся проверки срока действия, поля Destination (адресата сообщения) и корреляции запросов. Ответ можно принять вне его исходного контекста или воспроизвести повторно.
Затронутые версии и исправление
Уязвимы ветки njs 1.x с версии 1.0.0 по 1.0.1 включительно и ветки 0.x с 0.7.10 по 0.9.9. Исправление появилось в njs 1.0.2. Для ветки 0.x версии с исправлением нет, поэтому администраторам таких установок придётся перейти на более новую ветку. Оценка опасности зависит от шкалы: 6.5 по CVSS v3.1 и 8.3 по CVSS v4.0. Затронутый компонент - модуль ngx_http_js_module.
Остальные продукты вендора, от аппаратных платформ до облачных сервисов и консоли управления, проверены и признаны не подверженными этой уязвимости.
Что делать с подписанным XML
Приложения, разбирающие подписанный XML, должны отклонять входные данные с объявлением типа документа (DTD, описание структуры документа) ещё до разбора. Проверка обязана охватывать весь документ после декодирования принятой кодировки, а запрет DTD на уровне парсера надёжнее поиска по строке. Отсутствующие атрибуты, значимые для безопасности, правильнее считать провалом проверки, а не необязательными значениями. Развёртываниям nginx-saml нужно явно проверять адресата, корреляцию запросов, когда незапрошенный единый вход не предполагается, срок действия утверждения (assertion), подтверждение субъекта и поля ответа, связывающие запрос с откликом.
Расхождения между реализациями XML-парсеров снова дают возможность обойти логику проверки подписанных документов. Одного несовпадения в трактовке атрибутов хватает, чтобы валидатор пропустил документ с обрезанным набором полей. Пока такие несоответствия устраняют по одному, потребителям подписанного XML придётся проверять не только подпись, но и полноту разобранных данных.
Ссылки