flawopen.com/AI Security/langroid-neo4j-cypher-injection-cve-2026-55615
Langroid CVE-2026-55615: Prompt-to-Cypher Injection
Langroid passed model-generated Cypher to Neo4j without validation. Upgrade to 0.65.5; database permissions remain the security boundary.[1], [2], [4]
A librarian lets a visitor ask questions in plain language, then gives the visitor’s database instructions directly to a powerful clerk. If a hostile note changes the question, the clerk still follows the instructions. CVE-2026-55615 let untrusted prompt content influence Cypher that Langroid sent to Neo4j, so a read tool could expose graph data and a write tool could alter it.[1]
Core Concepts & Subsystem Terms
Cypher- Neo4j’s query language for reading and changing graph data. A query can also invoke procedures or remote data features when the database role and server configuration permit them.[1]
Neo4jChatAgent- A Langroid agent that turns a natural-language task into Cypher and sends it through retrieval or creation tools to a Neo4j database.[1], [3]
Prompt injection- Untrusted user input or retrieved content changes a model’s behavior. When the model can call a database tool, the resulting query must be treated as untrusted input.[1]
Framework mappings
- CWE reference for the weakness described in this guide: CWE-74
Step-by-Step Attack Flow
An affected graph agent accepts model-generated queries
Langroid versions through 0.65.4 are affected. The documented path requires an attacker to influence the agent prompt directly or through content the agent retrieves; the model must then use the Neo4jChatAgent tool. The advisory assigns CWE-74 and CVSS 4.0 9.2 (Critical).[1], [2]
The tool forwards the model’s Cypher
In the vulnerable path, cypher_retrieval_tool reads msg.cypher_query and passes it to read_query; cypher_creation_tool passes its query to write_query. The advisory traces those values to session.run(query, parameters) and tx.run(query, parameters) without an intervening validation gate.[1], [3]
Query permissions determine the immediate impact
A retrieval query could read graph data available to the connected role; a creation query could change or delete data within that role’s privileges. The advisory also identifies LOAD CSV remote fetching. Host-level file access or command execution is conditional on enabled procedures such as APOC or dbms.security and the database role’s grants; it is not an unconditional result.[1]
Version 0.65.5 adds tool-level query checks
The maintainer’s resolution says 0.65.5 adds a default-off allow_dangerous_operations option, read-only restrictions for retrieval, and checks that reject selected write, file, network, and execution primitives in the tool handlers. These checks are defense in depth, not authorization. The maintainer’s resolution and Langroid’s SQL-agent guidance both point to least-privilege database roles as the security boundary.[1], [3], [4], [5]
Upgrade and enforce database-side limits
Upgrade Langroid to 0.65.5 or later, confirm the resolved dependency in deployed images, and keep allow_dangerous_operations disabled unless a trusted use case explicitly requires it. Give Neo4j a dedicated least-privilege role, disable unneeded procedures, and constrain the agent host’s filesystem and network access.[4], [5]
Source Code: Flaw vs. Secure Implementation
The vulnerable excerpt follows the advisory’s source trace: model-supplied cypher_query reached the query helper and Neo4j driver without a validation check. The hardened excerpt is a behavior-focused representation of the 0.65.5 fix, not a verbatim patch: the maintainer says validation runs in tool handlers, retrieval is read-only by default, and dangerous operations are gated. Treat query checks as defense in depth, not authorization. The maintainer’s resolution and Langroid’s SQL-agent guidance point to least-privilege Neo4j roles as the security boundary; isolate the agent process as well. Langroid documents these keyword/pattern checks as inherently bypassable; keep Neo4j grants as the enforcement boundary.[1], [3], [4], [6]
# Vulnerable Neo4jChatAgent path (Langroid <= 0.65.4).
def cypher_retrieval_tool(self, msg: CypherRetrievalTool):
query = msg.cypher_query
return self.read_query(query)
def read_query(self, query: str):
with self.driver.session() as session:
return session.run(query, parameters=None)
# 0.65.5 behavior: validate at the LLM-facing tool boundary.
def cypher_retrieval_tool(self, msg: CypherRetrievalTool):
query = msg.cypher_query
rejection = validate_cypher_query(
query, is_write=False,
allow_dangerous=self.config.allow_dangerous_operations,
)
if rejection is not None:
return rejection
return self.read_query(query)
Engineering & System Hardening Checklist
- ✓Inventory Langroid deployments and lockfiles; upgrade every affected environment to 0.65.5 or later and rebuild deployed images.[1], [4]
- ✓Keep
allow_dangerous_operations=Falseunless a reviewed use case requires broader operations; record any exception and its owner.[1], [4] - ✓Create a dedicated Neo4j role for each agent and grant only required labels, read/write actions, and procedures; do not rely on the LLM or query validator as authorization.[1], [5]
- ✓Disable APOC, dbms.security, LOAD CSV, and other file, network, or operating-system capabilities when the application does not need them; verify the effective grants on the agent’s database role.[1]
- ✓Keep retrieval tools read-only and separate them from tools that can create or update records; require a separate authorization decision for consequential writes.[1], [4]
- ✓Test that an ordinary retrieval request succeeds while a harmless policy-test query representing a write or privileged procedure is rejected before the Neo4j driver is called.[3], [4]
- ✓Constrain the agent host’s filesystem, secrets, and network egress so a query-validation bypass cannot inherit broad host authority.[1]
- ✓Review database audit logs and agent traces for unexpected query types or procedure calls during the vulnerable deployment window; rotate credentials if their access may have been exposed.