FlawOpen

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

● CVE-2026-105750 · CVSS 5.9 · Media
Investigación · FlawOpen

CVE-2026-105750: divulgación de archivos locales al renderizar HTML en Docling

Las versiones de Docling anteriores a 2.118.1 pueden revelar archivos de texto locales cuando el código Python renderiza HTML no confiable desde un filesystem Path con render_page=True y Playwright instalado. La ruta del navegador no aplicaba enable_local_fetch ni limitaba el acceso al directorio del documento. Actualiza a 2.118.1 o posterior.

💡 Explicación en Lenguaje Sencillo (ELI5)

Imagina que un conversor es una persona que fotografía una página abierta en el navegador. Una opción decía «no cargues archivos locales», pero una ruta de renderizado dejaba pasar esas solicitudes. Si la página enviada conseguía que el navegador mostrara un archivo que el conversor podía leer, el texto visible podía terminar en la imagen del documento devuelto. La corrección comprueba la opción y limita los archivos locales permitidos al directorio del documento de origen.

Conceptos Clave y Términos

Docling HTML backend
Componente de Docling que analiza HTML y puede renderizar la página en un navegador sin interfaz para capturar su presentación visual.
HTMLBackendOptions(render_page=True)
Opción de la API de Python que activa la ruta de renderizado en navegador. Está desactivada de forma predeterminada.
enable_local_fetch
Opción de política que controla si se pueden cargar archivos locales como recursos del documento. Cada backend debe aplicarla a todas las solicitudes de recursos.
Playwright
Dependencia opcional de automatización de navegador usada para renderizar páginas HTML en Docling.
Path input
Archivo de origen proporcionado como ruta del sistema de archivos. A diferencia de una entrada stream, proporciona al flujo del navegador un origen file URL.
CWE-863
Incorrect Authorization: el filtro de solicitudes del modo de renderizado no aplicó la política configurada para el acceso a archivos locales.

Mapeos de marcos

  • Referencia CWE para la debilidad descrita en esta guía: CWE-863

Análisis de Causa Raíz

En las versiones afectadas en modo de renderizado, HTMLDocumentBackend._get_browser_request_block_reason() permitía las URL file: antes de comprobar enable_local_fetch o limitar la ruta resuelta al directorio del documento de origen. Para Docling 2.82.0–2.90.x, el aviso indica que el modo de renderizado ni siquiera filtraba las solicitudes. El límite vulnerable es la política de solicitudes de recursos del navegador, no el análisis general de HTML ni todas las instalaciones de Docling. El aviso de GitHub clasifica la causa como CWE-863 y también enumera CWE-552 por el impacto de divulgación; esta página usa CWE-863 como mapeo primario de la causa.

Flujo de Ataque Paso a Paso

Paso 1

La aplicación activa el renderizado HTML opcional

La implementación vulnerable usa la API de Python con HTMLBackendOptions(render_page=True) y tiene Playwright instalado. La configuración predeterminada, la CLI de Docling y docling-serve no forman parte de la configuración afectada descrita en el aviso.

Paso 2

La aplicación entrega HTML como filesystem Path

El aviso limita la entrada afectada a HTML no confiable entregado como Path. Las entradas stream usan page.set_content() con un origen opaco y no se ven afectadas por esta ruta de subrecursos file.

Paso 3

El navegador sin interfaz solicita un recurso local

El HTML puede hacer que el renderizado solicite subrecursos. El callback afectado permitía file: sin aplicar el permiso de acceso local; incluso con la opción activada, no limitaba el recurso al directorio de origen como sí lo hacía la ruta sin renderizado.

Paso 4

El texto legible puede aparecer en la imagen renderizada

El impacto publicado se limita al texto que un archivo local muestra dentro del área visible del navegador. JavaScript está desactivado en el navegador desde Docling 2.91.0; no generalices el fallo como ejecución arbitraria de código o lectura de bytes invisibles.

Paso 5

El filtro corregido restaura ambos controles

Docling 2.118.1 permite cargar el propio documento de origen, bloquea otras solicitudes file salvo que enable_local_fetch esté activado y limita los subrecursos locales permitidos al directorio del documento.

Código Fuente: Vulnerable vs. Seguro

El fragmento vulnerable muestra la regla que permitía file: incondicionalmente, según el aviso de los mantenedores; no es un archivo fuente completo. El fragmento corregido sigue el commit upstream 1612b88: permite cargar el HTML de origen, exige enable_local_fetch para otros archivos locales, resuelve la ruta solicitada y exige que permanezca dentro del directorio del documento. Actualiza a 2.118.1 o posterior en lugar de copiar este fragmento. El tratamiento separado de data:, about: y blob: queda fuera de la regla de archivos locales.

Fragmento de origen: docling/backend/html_backend.py — fragmentos concretos de la política de solicitudes y renderizado

IMPLEMENTACIÓN VULNERABLE
# Ruta de renderizado afectada: file: se permitía antes de comprobar la política de acceso local.
if scheme in {"file", "data", "about", "blob"}:
    return None
PARCHE SEGURO Y ROBUSTO
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)

# En _get_browser_request_block_reason():
if scheme == "file":
    if self._is_allowed_browser_file_request(request_url):
        return None
    # De lo contrario, devuelve el motivo por el que se bloqueó la solicitud.

Lista de Verificación de Seguridad para Ingeniería

Fuentes