sistema: OPERATIVO
← volver a todos los hacks
SUPPLY CHAIN MEDIUM

pgAdmin 4 incorpora un panel LLM y hereda un LFI+SSRF clásico (CVE-2026-7817)

pgAdmin 4 9.15 corrige un LFI y un SSRF autenticados en los nuevos endpoints de configuración de la API LLM. La clase de bug tiene cuarenta años; la superficie es nueva.

2026-05-28 // 7 min affects: pgadmin-4-9.13, pgadmin-4-9.14

¿De qué se trata?

El 11 de mayo de 2026, el proyecto pgAdmin divulgó CVE-2026-7817, un par de fallos en los endpoints de configuración de la API LLM incluidos en pgAdmin 4 9.13 y 9.14. El reportante, acreditado como j3seer, descubrió que dos preferencias de usuario — api_key_file y api_url — llegaban al cliente LLM sin validación. Un usuario autenticado puede así leer cualquier fichero accesible al proceso del servidor (local file inclusion) y forzar al servidor a emitir peticiones HTTP hacia destinos internos como los servicios de metadatos cloud (server-side request forgery). La corrección llegó en pgAdmin 4 9.15 mediante el commit 24485fe96.

La clase de bug tiene cuarenta años. Lo nuevo es la superficie: el panel LLM de pgAdmin — un asistente para redactar consultas — actúa como puente hacia la red y el sistema de ficheros. A medida que más productos heredados añaden paneles «pregunta al asistente» en 2026, este tipo exacto de hallazgo se repetirá.

Cómo funciona

El panel LLM permite al usuario apuntar pgAdmin hacia un endpoint compatible con OpenAI configurando dos valores: una URL para la base de la API y una ruta a un fichero con la clave. Ambos se almacenan como preferencias de usuario y son consumidos por la ruta de chat y los endpoints de listado de modelos.

La forma vulnerable, simplificada a partir del issue de GitHub y del parche 9.15:

# Vulnerable (< 9.15) — pseudo-código de la construcción del cliente LLM
api_url      = preferences.get("llm.api_url")        # cadena arbitraria
api_key_path = preferences.get("llm.api_key_file")   # ruta arbitraria

with open(api_key_path, "r") as f:        # LFI: cualquier fichero legible por pgAdmin
    api_key = f.read()

client = OpenAIClient(base_url=api_url,   # SSRF: cualquier URL, incluida
                      api_key=api_key)    #       http://169.254.169.254/...

De ahí surgen dos comportamientos alcanzables:

  1. LFI vía api_key_file. La ruta es abierta por la cuenta de servicio de pgAdmin. El contenido es entregado al cliente del proveedor como clave de API. La manera natural de observar la lectura es la ruta de error — una clave malformada provoca una respuesta que confirma que la lectura ocurrió y, en algunas configuraciones, devuelve un fragmento. Apuntar el campo hacia una configuración de cuenta de servicio, una clave privada o un fichero de credenciales basta para confirmar la exfiltración.
  2. SSRF vía api_url. La cadena se usa tal cual como URL base para HTTP saliente. Establecerla en http://169.254.169.254/latest/meta-data/iam/security-credentials/ sobre un pgAdmin alojado en la nube hace que el servidor recupere las credenciales del rol de instancia en nombre del atacante. Tanto la ruta de chat como la de listado de modelos llegan a este punto.

La explotación requiere autenticación, lo único que mantiene el CVSS en 6.5 (CVSS 3.1) / 7.1 (CVSS 4.0). En una instancia pgAdmin con auto-registro, un mapeo SSO laxo o una cuenta de bajo privilegio filtrada, ese prerrequisito se cumple fácilmente.

El parche 9.15 es pequeño y vale la pena leerlo. Hace tres cosas en la frontera de las preferencias LLM: confina api_key_file al almacenamiento privado del usuario (modo servidor) o al directorio home (modo escritorio), exige formato ASCII imprimible y limita la lectura a 1024 bytes, y filtra api_url contra una nueva allow-list (config.ALLOWED_LLM_API_URLS) verificada en cada punto de entrada.

Por qué importa

Tres puntos, por orden de frecuencia en 2026.

Primero, el panel LLM atornillado es una nueva superficie para fallos antiguos. pgAdmin lanzó una pequeña función de IA y heredó un CWE-552 (LFI) y un CWE-918 (SSRF) en la costura. El mismo patrón aparece en herramientas de bases de datos, IDEs, sistemas de tickets y paneles de observabilidad a medida que cada uno añade «configura aquí tu proveedor LLM». Cualquier campo de preferencia que llegue a un open() o a un cliente HTTP sin validación es candidato.

Segundo, autenticado no equivale a seguro. El rol pgAdmin necesario para modificar las preferencias LLM lo tiene cualquiera que pueda iniciar sesión y editar sus propios ajustes. En un pgAdmin multitenant detrás de SSO — forma común en fintech y plataformas — el atacante práctico es cualquier identidad corporativa con motivos para apuntar una herramienta a su propia pestaña de pgAdmin.

Tercero, el SSRF a metadatos cloud sigue siendo el pivote post-autenticación con mayor rentabilidad en flotas PostgreSQL gestionadas. Si pgAdmin corre en EC2, GCE o AKS con un rol de instancia, el SSRF lee las credenciales STS del rol. Esas credenciales leen luego el secreto de la base, el bucket de snapshots RDS y todo lo que el rol pueda alcanzar. CVE-2026-7817 es interesante menos por lo que es que por el entorno en el que vive.

Es el mismo patrón ya señalado a inicios de 2026 en LMDeploy CVE-2026-33626 (SSRF en un servidor de inferencia) y LiteLLM CVE-2026-42208 (SQLi en un proxy LLM): vulnerabilidades web clásicas en software que no existía hace tres años, junto a credenciales y al tráfico de modelos.

Defensas

  1. Actualice a pgAdmin 4 9.15 o superior. El parche está en las notas de versión 9.15 e incluido junto a otras siete correcciones de seguridad (CVE-2026-7813 a CVE-2026-7820) en la misma release. No aplique esta sola.
  2. Audite las preferencias LLM antes de actualizar. Extraiga la tabla de preferencias de su base pgAdmin y busque valores de api_key_file que apunten fuera del área de almacenamiento del usuario y api_url que no sean https://api.openai.com, https://api.anthropic.com o el proveedor que realmente utilice. Cualquier otra cosa es mala configuración o evidencia de explotación.
  3. Defina config.ALLOWED_LLM_API_URLS explícitamente. Una vez en 9.15, declare la allow-list en config_local.py con los dos o tres endpoints de proveedor que su equipo usa realmente. Los valores por defecto son conservadores, pero el valor del control proviene de su estrechez.
  4. Bloquee la salida de pgAdmin hacia RFC1918 y link-local. En un pgAdmin alojado en la nube, deniegue el tráfico saliente del host pgAdmin hacia 169.254.0.0/16, 127.0.0.0/8 y los rangos RFC1918 relevantes, excepto a la propia base de datos. Esto neutraliza el impacto del SSRF aunque una futura variante esquive la allow-list. En AWS, prefiera IMDSv2 con un hop limit de 1 para que una petición desde el servidor no pueda alcanzar el servicio de metadatos en primer lugar.
  5. Ejecute pgAdmin con un usuario dedicado y de bajos privilegios. El vector LFI solo lee lo que el proceso pgAdmin puede leer. Una cuenta de servicio con un home vacío y sin pertenencia a ssl-cert, shadow o a la ruta de credenciales cloud-init despoja a la primitiva de lectura de la mayor parte de su valor.
  6. Generalice la lección a sus propios paneles LLM. Si su producto incluye una página «añada su proveedor LLM», trate la URL de API como cualquier otra URL controlada por el usuario que se pasa a un cliente HTTP (allow-list de esquema, host, puerto; resuelva una vez y fije), y trate la ruta de la clave como cualquier otra ruta controlada por el usuario (confinada a un directorio del usuario, longitud de lectura limitada, sin symlinks). El parche pgAdmin 9.15 es una referencia utilizable.

Estado

ElementoReferenciaFechaNotas
Issue abiertapgAdmin GitHub #99002026-05-01Reportada por j3seer
CVE asignadaCVE-2026-78172026-05-11Publicada en NVD
pgAdmin 4 9.15 publicadoproyecto pgAdmin2026-05-11Ocho correcciones de seguridad en total
Commit del parche24485fe962026-05-11Allow-list + confinamiento de ruta + formato ASCII
Análisis externoSentinelOne2026-05-18Incluye guía de detección
SeveridadNVDCVSS 3.1: 6.5 / CVSS 4.0: 7.1
Versiones afectadasproyecto pgAdmin9.13 ≤ versión < 9.15

La conclusión correcta no es «pgAdmin tuvo un bug». Es «la frontera de configuración LLM se está convirtiendo en un lugar estándar donde encontrar LFI y SSRF en productos maduros, y los patrones de validación para defenderla ya se conocen». Aplique el parche; luego aplique el patrón.

Sources