Langroid: Neo4jChatAgent executes LLM-generated Cypher without validation (prompt-to-Cypher injection; config-conditional RCE), mirroring the SQLChatAgent bug fixed in CVE-2026-25879 (CVE-2026-55615)
Neo4jChatAgent passes LLM-generated Cypher queries straight to the Neo4j driver with no validation, no statement-type allowlist, and no opt-out gate. The query text is influenceable by prompt injection (direct user input or indirect content the agent reads back via RAG), so an attacker who can influence the prompt can read or destroy all graph data and, when APOC or dbms.security procedures are enabled on the server, achieve OS-command and filesystem access. This is the same defect class and threat model as the SQLChatAgent prompt-to-SQL-to-RCE issue fixed in version 0.63.0 (CVE-2026-25879); that fix did not extend to the neo4j module. ## Technical detail Untrusted-input to sink trace (reviewed on langroid HEAD b9df06f, v0.65.3): 1. Tool schemas accept raw query text from the LLM. `langroid/agent/special/neo4j/tools.py:4-9` (CypherRetrievalTool.cypher_query: str) and `:15-21` (CypherCreationTool.cypher_query: str). These tools are enabled unconditionally in `neo4j_chat_agent.py:412-419` (enable_message([GraphSchemaTool, CypherRetrievalTool, CypherCreationTool, DoneTool])). 2. Read path. `neo4j_chat_agent.py:300` cypher_retrieval_tool(msg) -> `:325` query = msg.cypher_query -> `:328` self.read_query(query) -> `:223` session.run(query, parameters). The LLM-controlled string is the first positional argument to session.run; parameters is None. No validation occurs between :325 and :223. 3. Write path. `neo4j_chat_agent.py:338` cypher_creation_tool(msg) -> `:348` query = msg.cypher_query -> `:351` self.write_query(query) -> `:276` session.write_transaction(lambda tx: tx.run(query, parameters)). The only inspection of the string (write_query :251-264) is a query.upper() substring test for CREATE/MERGE/CONSTRAINT/INDEX whose sole effect is setting self.config.database_created = True; it blocks nothing. A query such as `MATCH (n) DETACH DELETE n` (the same statement the built-in remove_database helper runs at :287-293) passes unrestricted. 4. Guarded-sibling contrast proving the incomplete fix. The SQLChatAgent, patched for the parent CVE, validates every query before execution. `langroid/agent/special/sql/sql_chat_agent.py:256` defines allow_dangerous_operations: bool = False (opt-in gate); `:618` _validate_query runs (a) a dangerous-pattern regex blocklist (_DANGEROUS_SQL_PATTERNS, :628-641), (b) a sqlglot statement-type allowlist defaulting to SELECT-only (:643-686), and (c) an AST-level dangerous-function blocklist (:687-704). run_query calls rejection = self._validate_query(query) at `:721` before executing. The neo4j read_query/write_query paths have no equivalent: a grep for _validate_query/allow_dangerous in neo4j_chat_agent.py returns nothing. The defense exists for SQL and is simply absent for Cypher, which is the definition of an incomplete fix for the same prompt-to-query-language injection class. ## Proof of concept (static, no third-party systems, no live Neo4j required) Step 1 (presence vs absence of the guard, one command): ``` grep -n "_validate_query\|allow_dangerous" langroid/agent/special/sql/sql_chat_agent.py # SQL: many hits (gate + validator + call site :721) grep -n "_validate_query\|allow_dangerous" langroid/agent/special/neo4j/neo4j_chat_agent.py # neo4j: ZERO hits ``` Step 2 (sink trace is direct, no interposed check): ``` read_query: msg.cypher_query (line 325) -> read_query(query) (328) -> session.run(query, parameters) (223) write_query: msg.cypher_query (348) -> write_query(query) (351) -> tx.run(query, parameters) (276) ``` The only string inspection (write_query 251-264) is a .upper() substring test that only sets database_created=True and rejects nothing. The asymmetry (validator + opt-out gate enforced on every SQL query at sql_chat_agent.py:721; nothing on either Cypher path) is the deterministic artifact: the same project, for the same injection class, guards one query language and not the other. A dynamic confirmation against an operator-owned disposable Neo4j (create a CSPRNG-marked node via cypher_creation_tool, read it back via cypher_retrieval_tool, then DETACH DELETE it) reproduces the read/write/destroy primitive without any third-party system. ## Impact An attacker who can influence the agent prompt (directly, or indirectly via content the agent reads back through RAG) controls the executed Cypher. Floor (no extra config, not contingent): unauthorized read of all graph data via cypher_retrieval_tool and full write/destroy (including MATCH (n) DETACH DELETE n) via cypher_creation_tool, plus the built-in LOAD CSV remote-fetch (SSRF) primitive. Ceiling (config-conditional, when APOC / dbms.security procedures are granted to the DB role, a common deployment): apoc.load.* (SSRF + remote/local file read), apoc.cypher.runFile / apoc.import.* / apoc.export.* (filesystem), and CALL dbms.* admin procedures, i.e. the Cypher analogue of the parent's COPY ... FROM PROGRAM RCE primitive. This mirrors the privileged-role contingency the parent advisory (CVE-2026-25879) accep
AI Analysis
Technical Summary
The Neo4jChatAgent component in Langroid passes LLM-generated Cypher queries directly to the Neo4j driver without any validation, statement-type allowlist, or opt-out mechanism. This lack of filtering allows attackers who can influence the prompt input (directly or indirectly via retrieval-augmented generation) to execute arbitrary Cypher queries. The read path uses session.run(query) with no validation, and the write path uses session.write_transaction(tx.run(query)) with only minimal substring checks that do not block dangerous queries. This contrasts with the SQLChatAgent, which enforces strict validation and an opt-in gate to prevent dangerous SQL operations. The vulnerability enables unauthorized data access and destruction, and when APOC or dbms.security procedures are enabled on the Neo4j server, it can lead to OS command execution and filesystem access. This is a prompt-to-Cypher injection vulnerability classified under CWE-74 and is a critical security issue. The affected versions are all Langroid versions before 0.65.5. No official patch or fix is currently documented.
Potential Impact
An attacker who can influence the prompt input to the Neo4jChatAgent can execute arbitrary Cypher queries on the Neo4j database. At minimum, this allows unauthorized reading of all graph data, full write and destructive operations (including deleting all nodes), and SSRF via LOAD CSV remote fetch. If the Neo4j server has APOC or dbms.security procedures enabled and granted to the database role, the attacker can execute OS commands and access the filesystem, effectively achieving remote code execution. This vulnerability can lead to complete compromise of the graph database and underlying host system, depending on server configuration.
Mitigation Recommendations
No official patch or fix is currently documented for this vulnerability. Users should consider disabling or restricting the use of Neo4jChatAgent until a fix is available. Applying strict validation and allowlisting of Cypher queries before execution, similar to the SQLChatAgent's approach, is recommended as a mitigation strategy. Monitor vendor advisories for updates or patches addressing this issue. Patch status is not yet confirmed — check the vendor advisory for current remediation guidance.
Langroid: Neo4jChatAgent executes LLM-generated Cypher without validation (prompt-to-Cypher injection; config-conditional RCE), mirroring the SQLChatAgent bug fixed in CVE-2026-25879 (CVE-2026-55615)
Description
Neo4jChatAgent passes LLM-generated Cypher queries straight to the Neo4j driver with no validation, no statement-type allowlist, and no opt-out gate. The query text is influenceable by prompt injection (direct user input or indirect content the agent reads back via RAG), so an attacker who can influence the prompt can read or destroy all graph data and, when APOC or dbms.security procedures are enabled on the server, achieve OS-command and filesystem access. This is the same defect class and threat model as the SQLChatAgent prompt-to-SQL-to-RCE issue fixed in version 0.63.0 (CVE-2026-25879); that fix did not extend to the neo4j module. ## Technical detail Untrusted-input to sink trace (reviewed on langroid HEAD b9df06f, v0.65.3): 1. Tool schemas accept raw query text from the LLM. `langroid/agent/special/neo4j/tools.py:4-9` (CypherRetrievalTool.cypher_query: str) and `:15-21` (CypherCreationTool.cypher_query: str). These tools are enabled unconditionally in `neo4j_chat_agent.py:412-419` (enable_message([GraphSchemaTool, CypherRetrievalTool, CypherCreationTool, DoneTool])). 2. Read path. `neo4j_chat_agent.py:300` cypher_retrieval_tool(msg) -> `:325` query = msg.cypher_query -> `:328` self.read_query(query) -> `:223` session.run(query, parameters). The LLM-controlled string is the first positional argument to session.run; parameters is None. No validation occurs between :325 and :223. 3. Write path. `neo4j_chat_agent.py:338` cypher_creation_tool(msg) -> `:348` query = msg.cypher_query -> `:351` self.write_query(query) -> `:276` session.write_transaction(lambda tx: tx.run(query, parameters)). The only inspection of the string (write_query :251-264) is a query.upper() substring test for CREATE/MERGE/CONSTRAINT/INDEX whose sole effect is setting self.config.database_created = True; it blocks nothing. A query such as `MATCH (n) DETACH DELETE n` (the same statement the built-in remove_database helper runs at :287-293) passes unrestricted. 4. Guarded-sibling contrast proving the incomplete fix. The SQLChatAgent, patched for the parent CVE, validates every query before execution. `langroid/agent/special/sql/sql_chat_agent.py:256` defines allow_dangerous_operations: bool = False (opt-in gate); `:618` _validate_query runs (a) a dangerous-pattern regex blocklist (_DANGEROUS_SQL_PATTERNS, :628-641), (b) a sqlglot statement-type allowlist defaulting to SELECT-only (:643-686), and (c) an AST-level dangerous-function blocklist (:687-704). run_query calls rejection = self._validate_query(query) at `:721` before executing. The neo4j read_query/write_query paths have no equivalent: a grep for _validate_query/allow_dangerous in neo4j_chat_agent.py returns nothing. The defense exists for SQL and is simply absent for Cypher, which is the definition of an incomplete fix for the same prompt-to-query-language injection class. ## Proof of concept (static, no third-party systems, no live Neo4j required) Step 1 (presence vs absence of the guard, one command): ``` grep -n "_validate_query\|allow_dangerous" langroid/agent/special/sql/sql_chat_agent.py # SQL: many hits (gate + validator + call site :721) grep -n "_validate_query\|allow_dangerous" langroid/agent/special/neo4j/neo4j_chat_agent.py # neo4j: ZERO hits ``` Step 2 (sink trace is direct, no interposed check): ``` read_query: msg.cypher_query (line 325) -> read_query(query) (328) -> session.run(query, parameters) (223) write_query: msg.cypher_query (348) -> write_query(query) (351) -> tx.run(query, parameters) (276) ``` The only string inspection (write_query 251-264) is a .upper() substring test that only sets database_created=True and rejects nothing. The asymmetry (validator + opt-out gate enforced on every SQL query at sql_chat_agent.py:721; nothing on either Cypher path) is the deterministic artifact: the same project, for the same injection class, guards one query language and not the other. A dynamic confirmation against an operator-owned disposable Neo4j (create a CSPRNG-marked node via cypher_creation_tool, read it back via cypher_retrieval_tool, then DETACH DELETE it) reproduces the read/write/destroy primitive without any third-party system. ## Impact An attacker who can influence the agent prompt (directly, or indirectly via content the agent reads back through RAG) controls the executed Cypher. Floor (no extra config, not contingent): unauthorized read of all graph data via cypher_retrieval_tool and full write/destroy (including MATCH (n) DETACH DELETE n) via cypher_creation_tool, plus the built-in LOAD CSV remote-fetch (SSRF) primitive. Ceiling (config-conditional, when APOC / dbms.security procedures are granted to the DB role, a common deployment): apoc.load.* (SSRF + remote/local file read), apoc.cypher.runFile / apoc.import.* / apoc.export.* (filesystem), and CALL dbms.* admin procedures, i.e. the Cypher analogue of the parent's COPY ... FROM PROGRAM RCE primitive. This mirrors the privileged-role contingency the parent advisory (CVE-2026-25879) accep
CVSS v4.0
Affected software
Run on your own infrastructure? Check whether these packages are installed with threat-finder — our free open-source scanner.
Weaknesses
AI-Powered Analysis
Machine-generated threat intelligence
Technical Analysis
The Neo4jChatAgent component in Langroid passes LLM-generated Cypher queries directly to the Neo4j driver without any validation, statement-type allowlist, or opt-out mechanism. This lack of filtering allows attackers who can influence the prompt input (directly or indirectly via retrieval-augmented generation) to execute arbitrary Cypher queries. The read path uses session.run(query) with no validation, and the write path uses session.write_transaction(tx.run(query)) with only minimal substring checks that do not block dangerous queries. This contrasts with the SQLChatAgent, which enforces strict validation and an opt-in gate to prevent dangerous SQL operations. The vulnerability enables unauthorized data access and destruction, and when APOC or dbms.security procedures are enabled on the Neo4j server, it can lead to OS command execution and filesystem access. This is a prompt-to-Cypher injection vulnerability classified under CWE-74 and is a critical security issue. The affected versions are all Langroid versions before 0.65.5. No official patch or fix is currently documented.
Potential Impact
An attacker who can influence the prompt input to the Neo4jChatAgent can execute arbitrary Cypher queries on the Neo4j database. At minimum, this allows unauthorized reading of all graph data, full write and destructive operations (including deleting all nodes), and SSRF via LOAD CSV remote fetch. If the Neo4j server has APOC or dbms.security procedures enabled and granted to the database role, the attacker can execute OS commands and access the filesystem, effectively achieving remote code execution. This vulnerability can lead to complete compromise of the graph database and underlying host system, depending on server configuration.
Mitigation Recommendations
No official patch or fix is currently documented for this vulnerability. Users should consider disabling or restricting the use of Neo4jChatAgent until a fix is available. Applying strict validation and allowlisting of Cypher queries before execution, similar to the SQLChatAgent's approach, is recommended as a mitigation strategy. Monitor vendor advisories for updates or patches addressing this issue. Patch status is not yet confirmed — check the vendor advisory for current remediation guidance.
Technical Details
- Gcve Source
- db.gcve.eu
- Osv Id
- GHSA-2pq5-3q89-j7cc
- Osv Schema Version
- 1.4.0
- Aliases
- ["CVE-2026-55615"]
- Ecosystems
- ["PyPI"]
- Database Specific Severity
- CRITICAL
- Cvss Version
- 4.0
Threat ID: 6a4c33ff27e9c797195f5c85
Added to database: 07/06/2026, 23:02:23 UTC
Last enriched: 07/06/2026, 23:10:51 UTC
Last updated: 07/31/2026, 19:22:59 UTC
Views: 85
Community Reviews
0 reviewsCrowdsource mitigation strategies, share intel context, and vote on the most helpful responses. Sign in to add your voice and help keep defenders ahead.
Want to contribute mitigation steps or threat intel context? Sign in or create an account to join the community discussion.
Actions
Updates to AI analysis require Pro Console access. Upgrade inside Console → Billing.
Need more coverage?
Upgrade to Pro Console for AI refresh and higher limits.
For incident response and remediation, OffSeq services can help resolve threats faster.
Latest Threats
Check if your credentials are on the dark web
Instant breach scanning across billions of leaked records. Free tier available.