-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Below description comes from C Opus 45 based on my prompt and is approved.
Problem
CypherQueryFilter uses a keyword blocklist to reject non-read queries. This is inherently fragile:
new Neo4j versions can introduce new write/admin keywords, and it's easy to miss one. Issues #479 and
#480 are symptoms of this — we keep discovering keywords we forgot to block.
Proposed approach
Use Neo4j's own query planning as the primary security boundary. Before executing a user-provided
Cypher query, run EXPLAIN <query> against Neo4j. The Bolt protocol result summary includes a
queryType field (r, w, rw, s). If it's not r, reject.
This delegates parsing to the one authority that definitively knows what constitutes a write — Neo4j
itself. No keyword list to maintain, and it's future-proof against new syntax.
Tradeoffs
- One extra round-trip per user query (EXPLAIN then execute). Acceptable for
#cypher_rawsince a
Neo4j call is already being made. - Need to verify the Laudis PHP client exposes
queryTypefrom the result summary. EXPLAINitself should be safe (read-only by design), but worth verifying.
Role of existing CypherQueryFilter
Keep the keyword filter as a fast-fail / defense-in-depth layer. It rejects obviously bad queries
without hitting Neo4j. But it no longer needs to be the sole security boundary, so missing a keyword
becomes "slightly wasteful round-trip" rather than "security hole."
SHOW as a special case
SHOW queries (e.g. SHOW USERS, SHOW DATABASES) are read-only from Neo4j's perspective, so
EXPLAIN would classify them as r. If blocking information disclosure is desired, the keyword filter
is still needed for that — it's a policy decision beyond read-vs-write.
AC
- User-provided Cypher queries are validated via EXPLAIN before execution
- Non-read queries are rejected based on the EXPLAIN result
CypherQueryFilterkeyword blocklist is retained as secondary defense- Tests