FlawOpen

flawopen.com/Teardowns/cve-2026-105750-docling-html-render-local-file-disclosure

● CVE-2026-105750 · CVSS 5.9 · Средний
Исследования · FlawOpen

CVE-2026-105750: раскрытие локальных файлов при HTML-рендеринге Docling

Версии Docling до 2.118.1 могут раскрывать локальные текстовые файлы, если Python-код рендерит недоверенный HTML из filesystem Path при render_page=True и установленном Playwright. В браузерном пути не применялся enable_local_fetch и не ограничивался доступ каталогом документа. Обновитесь до 2.118.1 или новее.

💡 Простыми словами (ELI5)

Представьте конвертер как сотрудника, который фотографирует страницу, открытую в браузере. Настройка говорила «не загружать локальные файлы», но один путь рендеринга всё равно пропускал такие запросы. Если переданная страница заставляла браузер показать файл, доступный конвертеру, видимый текст мог попасть на изображение возвращённого документа. Исправление проверяет настройку и ограничивает разрешённые локальные файлы каталогом исходного документа.

Ключевые понятия и термины

Docling HTML backend
Компонент Docling, который обрабатывает HTML и может отрисовать страницу в браузере без интерфейса, чтобы сохранить её визуальное представление.
HTMLBackendOptions(render_page=True)
Параметр Python API, включающий путь рендеринга в браузере. По умолчанию он выключен.
enable_local_fetch
Параметр политики, определяющий, можно ли загружать локальные файлы как ресурсы документа. Каждый backend должен применять его к каждому запросу ресурса.
Playwright
Необязательная зависимость для автоматизации браузера, используемая при рендеринге HTML-страниц Docling.
Path input
Исходный файл, переданный как путь файловой системы. В отличие от потока, он задаёт браузерному пути источник file URL.
CWE-863
Incorrect Authorization: фильтр запросов в режиме рендеринга не применял настроенную политику доступа к локальным файлам.

Связи со стандартами

  • Ссылка CWE для слабого места, описанного в этом руководстве: CWE-863

Анализ первопричины

В уязвимых версиях при рендеринге HTMLDocumentBackend._get_browser_request_block_reason() разрешал URL file: до проверки enable_local_fetch или ограничения разрешённого пути каталогом исходного документа. Для Docling 2.82.0–2.90.x в уведомлении сказано, что фильтрации запросов в режиме рендеринга вообще не было. Уязвимая граница — политика запросов ресурсов браузера, а не вся обработка HTML или каждая установка Docling. GitHub advisory указывает CWE-863 для причины и дополнительно CWE-552 для воздействия раскрытия; здесь CWE-863 выбран как основная классификация причины.

Пошаговый сценарий атаки

Шаг 1

Приложение включает дополнительный HTML-рендеринг

Уязвимая конфигурация использует Python API с HTMLBackendOptions(render_page=True) и установленным Playwright. По уведомлению, конфигурация по умолчанию, CLI Docling и docling-serve не относятся к затронутым.

Шаг 2

Приложение передаёт HTML как filesystem Path

Уведомление ограничивает затронутый вход недоверенным HTML, переданным как Path. Потоковые входы используют page.set_content() с непрозрачным источником и не затрагиваются этим путём file-подресурсов.

Шаг 3

Браузер без интерфейса запрашивает локальный ресурс

HTML может вызвать запросы подресурсов при рендеринге. Уязвимый callback разрешал file: без применения разрешения на локальный доступ; даже при включённой настройке путь не ограничивался каталогом источника, как в режиме без рендеринга.

Шаг 4

Видимый текст может попасть в изображение страницы

Описанное воздействие ограничено текстом, который локальный файл показывает в видимой области браузера. Начиная с Docling 2.91.0 JavaScript отключён; не следует обобщать проблему до произвольного выполнения кода или чтения невидимых байтов.

Шаг 5

Исправленный фильтр восстанавливает обе проверки

Docling 2.118.1 разрешает загрузить сам исходный документ, блокирует другие запросы file: без включённого enable_local_fetch и ограничивает разрешённые локальные подресурсы каталогом документа.

Исходный код: Уязвимый vs Защищённый вариант

Уязвимый фрагмент показывает безусловное разрешение file:, описанное в уведомлении сопровождающих; это не полный исходный файл. Исправленный фрагмент соответствует upstream-коммиту 1612b88: он разрешает исходный HTML, требует enable_local_fetch для остальных локальных файлов, разрешает путь запроса и ограничивает его каталогом документа. Обновитесь до 2.118.1 или новее, а не копируйте этот узкий фрагмент. Отдельная обработка data:, about: и blob: не относится к правилу локальных файлов.

Фрагмент исходного кода: docling/backend/html_backend.py — фрагменты политики запросов и рендеринга

УЯЗВИМАЯ РЕАЛИЗАЦИЯ
# Уязвимый путь рендеринга: file: разрешался до проверки политики локальной загрузки.
if scheme in {"file", "data", "about", "blob"}:
    return None
БЕЗОПАСНЫЙ ИСПРАВЛЕННЫЙ ВАРИАНТ
def _is_allowed_browser_file_request(self, request_url: str) -> bool:
    local_base_path = self._get_browser_local_base_path()
    if local_base_path is not None and request_url == local_base_path.as_uri():
        return True  # The source document itself must remain loadable.

    if not self.options.enable_local_fetch or local_base_path is None:
        return False

    requested_path = Path(url2pathname(urlparse(request_url).path)).resolve()
    return requested_path.is_relative_to(local_base_path.parent)

# В _get_browser_request_block_reason():
if scheme == "file":
    if self._is_allowed_browser_file_request(request_url):
        return None
    # В противном случае вернуть причину блокировки запроса.

Чек-лист по защите системы для инженеров

Источники