This plugin implements comprehensive security measures to prevent Cypher injection attacks, unauthorized database modifications, and resource exhaustion while maintaining a simple and familiar interface.
The plugin uses a multi-layered security approach:
- Preflight Validation - EXPLAIN-based query checks before execution
- Query Type Detection - Automatic read/write classification
- Write Protection - Explicit user consent required for modifications
- Resource Limits - Configurable record and query size limits
- Parameterization - Safe value substitution in queries
# ✅ SECURE - Parameterized query with validation
{
"query": "MATCH (n:Person {name: $name}) RETURN n",
"parameters": {"name": "John"}
}Before executing any query, the plugin runs EXPLAIN to:
- Validate syntax - Catch errors before execution
- Detect query type - Identify read ('r'), write ('w'), read-write ('rw'), or schema ('s') queries
- Enforce permissions - Block write queries unless explicitly allowed
# Plugin automatically runs: EXPLAIN <your_query>
# Checks summary.query_type before actual executionDefault Behavior (Secure):
- ❌
CREATEoperations blocked - ❌
DELETE/DETACH DELETEblocked - ❌
SET/REMOVEoperations blocked - ❌
MERGEoperations blocked - ✅
MATCHandRETURNallowed - ✅ Schema queries (
SHOW,CREATE INDEX) allowed
When allow_write_queries is enabled:
⚠️ User explicitly opts in via checkbox⚠️ Warning messages displayed- ✅ All write operations permitted
- ❌ Administrative operations still blocked
Always Blocked (Even with Write Permission):
CREATE DATABASE/DROP DATABASECREATE USER/DROP USERCREATE ROLE/DROP ROLESET PASSWORDCALL dbms.*system procedures
Query Length:
- Maximum: 2000 characters
- Prevents buffer overflow attacks
Record Limits:
- Default: 1000 records per query
- Configurable via
max_recordsparameter - Uses efficient streaming with
fetch_size - Prevents memory exhaustion
Connection Management:
- Singleton driver pattern per tool instance
- Automatic connection pooling
- Proper cleanup on destruction
Always use Neo4j's standard parameterization syntax:
# ✅ SECURE - Parameters are safely handled
{
"query": "MATCH (n:Person {name: $name, age: $age}) RETURN n",
"parameters": {"name": "John", "age": 30}
}{
"query": "MATCH (n:Person {name: $name}) RETURN n",
"parameters": {"name": "Alice"}
}{
"query": "MATCH (a:Person)-[r:KNOWS]->(b:Person) WHERE a.name = $name RETURN r, b",
"parameters": {"name": "Bob"}
}{
"query": "MATCH p = (start:Person {id: $startId})-[*1..3]-(end) RETURN p",
"parameters": {"startId": "123"}
}{
"query": "MATCH (n:Person) WHERE n.age > $minAge AND n.city = $city RETURN n",
"parameters": {"minAge": 25, "city": "New York"}
}{
"query": "CREATE (p:Person {name: $name, age: $age}) RETURN p",
"parameters": {"name": "Charlie", "age": 35},
"allow_write_queries": true
}{
"query": "MATCH (p:Person {id: $id}) SET p.status = $status RETURN p",
"parameters": {"id": "123", "status": "active"},
"allow_write_queries": true
}The plugin provides specific error messages for different security violations:
Write queries are not allowed. Query type: 'w'.
Enable 'Allow Write Queries' to execute write operations.
Query syntax error: Neo.ClientError.Statement.SyntaxError
Query too long (max 2000 characters)
1. Basic Validation
├─ Check query is non-empty string
└─ Check query length ≤ 2000 chars
2. Preflight Check
├─ Execute: EXPLAIN <query>
├─ Check for syntax errors
├─ Get query_type from summary
└─ Validate: if write_disabled && type not in ['r','s'] → REJECT
3. Query Execution
├─ Execute query with parameters
├─ Stream results with fetch_size
└─ Limit to max_records
# ✅ GOOD
{"query": "MATCH (n:Person {name: $name}) RETURN n", "parameters": {"name": user_input}}
# ❌ BAD - Vulnerable to injection
{"query": f"MATCH (n:Person {{name: '{user_input}'}}) RETURN n"}- Keep disabled by default
- Enable only for trusted operations
- Review queries before execution
- Use in controlled workflows
# Use max_records parameter
{
"query": "MATCH (n:Person) RETURN n",
"max_records": 100 # Limit to 100 records
}# Target specific databases
{
"query": "MATCH (n:Node) RETURN n",
"database": "production" # Isolate to specific database
}- Storage: Credentials encrypted in Dify platform
- Transmission: HTTPS/TLS for all connections
- Validation: Connection tested during credential setup
- Timeout: 10-second connection timeout prevents hanging
- No Logging: Credentials never logged or exposed
If you discover a security vulnerability:
- Do NOT open a public issue
- Email: security@neo4j.com
- Include detailed reproduction steps
- Allow time for patching before disclosure
"MATCH (n) DETACH DELETE n" # Data deletion
"DROP DATABASE mydb" # Schema deletion
"CALL db.stats()" # System procedures
"CREATE USER admin" # Administrative operations
"DELETE n WHERE n.id = 1" # Unparameterized deletion"MATCH (n:Person) RETURN n" # Simple queries
"MATCH (a)-[r]->(b) RETURN a, r, b" # Relationship queries
"MATCH (n:Person {name: $name}) RETURN n" # Parameterized queries
"MATCH (n) WHERE n.age > $age RETURN n LIMIT 100" # Filtered queries- Familiar Interface: Keep using standard Cypher syntax
- Automatic Protection: Security is transparent to users
- Parameterization Support: Full Neo4j parameter support
- Resource Protection: Automatic LIMIT enforcement
- Operation Filtering: Dangerous operations blocked
- Length Limits: Prevents malformed queries
- Always use parameters for user values:
{name: $name}not{name: 'user_input'} - Keep queries focused: Single-purpose queries are more secure
- Use appropriate limits: Specify reasonable LIMIT values
- Test with parameters: Verify parameterized queries work as expected
This simplified approach provides strong security while maintaining the familiar Cypher query interface that users expect.