El agente Neo4j de Langroid ejecuta Cypher generado sin control — el gemelo del fallo SQL
El agente de base de datos de grafos de Langroid entrega el Cypher generado por el modelo directamente a Neo4j, sin validación. Una inyección de prompt puede borrar el grafo o, con APOC habilitado, alcanzar el host — el mismo defecto ya corregido en el agente SQL, dejado abierto en el módulo Neo4j.
¿Qué es esto?
Langroid es un framework Python de código abierto para construir aplicaciones LLM multiagente. Uno de sus agentes auxiliares, Neo4jChatAgent, permite consultar una base de datos de grafos en lenguaje natural: el modelo traduce la petición a Cypher — el lenguaje de consulta de Neo4j — la ejecuta y luego explica el resultado. El 6 de julio de 2026, un aviso de seguridad (GitLab GLAD, GitHub GHSA-2pq5-3q89-j7cc) reveló que este agente entrega el Cypher generado por el modelo directamente al controlador de Neo4j, sin validación, sin lista blanca de tipos de instrucción y sin opción de desactivación. Está calificado como 9.8 (crítico) y clasificado como debilidad de inyección (CWE-74).
El detalle que justifica esta cobertura no es el fallo en sí, sino su linaje. Es la misma clase de defecto, y el mismo modelo de amenaza, que el fallo de prompt-a-SQL del agente SQLChatAgent de Langroid, corregido ya en la versión 0.63.0. Esa corrección nunca se extendió al módulo Neo4j, de modo que el mismo agujero quedó abierto en un agente hermano durante seis semanas más. Todas las versiones anteriores a 0.65.5 están afectadas; 0.65.5 aporta la corrección.
Cómo funciona
El mecanismo es una tubería texto-a-consulta a la que le falta una frontera de confianza. La pregunta del usuario — o, peor, el contenido que el agente relee mediante recuperación (RAG) — dirige qué Cypher emite el modelo, y ese Cypher se ejecuta tal cual.
# Patrón vulnerable (antes de 0.65.5), simplificado:
cypher = llm.generate(user_question) # texto influenciable por el atacante
session.run(cypher) # sin barrera de solo lectura, sin lista blanca
Como el texto de la consulta es influenciable por inyección de prompt — ya sea directa (un usuario hostil que dialoga con el agente) o indirecta (un documento, una página web o un nodo envenenado que el agente ingiere vía RAG) — un atacante que alcanza el prompt controla la consulta. De ahí se derivan dos niveles de escalada:
- Nivel de datos. Cypher no es de solo lectura. Instrucciones inyectadas pueden forzar al modelo a emitir escrituras o borrados: el atacante puede leer cada nodo del grafo o destruirlo por completo (un
DETACH DELETEsobre todos los nodos). Las cargas útiles se omiten aquí —[REDACTED]— pero la clase es sencilla: cualquier instrucción mutante que el controlador acepte. - Nivel de host. Neo4j incluye bibliotecas de procedimientos opcionales. Cuando APOC o los procedimientos
dbms.securityestán habilitados en el servidor, Cypher puede llegar al sistema operativo y al sistema de archivos. En ese punto, una inyección de prompt-a-Cypher se convierte en acceso a comandos y ficheros — ejecución remota de código condicionada por la configuración del servidor, no por un fallo adicional de Langroid.
El paralelismo con la variante SQL es exacto. Allí, primitivas propias del dialecto como COPY ... FROM PROGRAM convertían un cuadro de chat en ejecución de código en el host de la base de datos; aquí, los procedimientos APOC hacen el mismo trabajo para un almacén de grafos. Lenguaje de consulta distinto, forma idéntica.
Por qué importa
Los agentes «texto-a-consulta» son ya un componente habitual — SQL, Cypher, SPARQL, filtros de MongoDB, DSL de Elasticsearch. Cada backend constituye su propia superficie de inyección, y cada uno confía en una cadena escrita por un LLM bajo la influencia de entradas no confiables. El caso Langroid ilustra con claridad dos puntos que los defensores deben interiorizar.
Primero, corregir un lenguaje de consulta no corrige los demás. El agente SQL se endureció en junio; el agente Neo4j, estructuralmente idéntico, siguió siendo vulnerable porque la remediación se escribió como una corrección puntual y no como una política aplicada a todos los agentes que emiten consultas. Si su código tiene una superficie texto-a-consulta, muy probablemente tiene varias.
Segundo, la entrada inicial no tiene por qué ser un usuario malicioso. La vía indirecta — un nodo del grafo, un documento recuperado o una página raspada que porta instrucciones que el agente relee después — significa que la superficie de ataque incluye todo contenido que el agente ingiere. Es el vector más difícil de razonar y el más fácil de pasar por alto.
Defensas
La corrección de origen y el patrón general se refuerzan mutuamente:
- Actualice a Langroid 0.65.5 o posterior, que cierra este fallo concreto. Luego audite cada agente que emita consultas en su pila en busca del mismo defecto, en lugar de confiar en que un módulo corregido lo deja a salvo.
- Trate las consultas generadas por el LLM como salida no confiable. Configure por defecto la sesión de base de datos del agente en solo lectura e imponga una lista blanca de tipos de instrucción que rechace escrituras, cambios de esquema y llamadas a procedimientos salvo que un caso concreto lo requiera.
- Opere con una cuenta de base de datos de mínimo privilegio. Asigne al agente un rol de Neo4j limitado a los datos que necesita. Deshabilite APOC y los procedimientos
dbms.securitysalvo necesidad real; si se requieren, restrínjalos condbms.security.procedures.allowlistal mínimo indispensable. Esto elimina el nivel de host aunque se alcance el de datos. - Someta las acciones mutantes a revisión humana. Una consulta destructiva debe exigir confirmación explícita, no dispararse automáticamente desde un turno de conversación.
- Aísle el almacén de grafos. Segméntelo en la red y asegúrese de que el host que ejecuta Neo4j no exponga credenciales ambientales ni una superficie de comandos que una consulta fugada pudiera aprovechar.
- Registre las consultas generadas. Guardar el Cypher exacto que emitió el modelo convierte un incidente opaco en uno auditable y hace aflorar pronto los intentos de inyección.
Estado
| Elemento | Referencia | Fecha | Notas |
|---|---|---|---|
| Inyección Cypher del agente Neo4j | GHSA-2pq5-3q89-j7cc / CVE-2026-55615 | 2026-07-06 | CVSS 9.8; afecta a langroid < 0.65.5; corregido en 0.65.5 |
| RCE prompt-a-SQL del agente SQL (espejo) | CVE-2026-25879 | 2026-06-01 | Misma clase; corregido en 0.63.0; la corrección no cubría Neo4j |
| Escalada a nivel de host | Procedimientos APOC / dbms.security | — | RCE condicionada por la configuración del servidor, no un fallo aparte |
La lectura correcta no es «un agente de grafos tuvo un bug». Es que una clase de inyección conocida y ya corregida reapareció sin corregir en un agente hermano — el recordatorio de que la remediación texto-a-consulta es una política que se aplica en todas partes, no una corrección que se entrega una sola vez.