Repository navigation
fix(security): allowlist CALL procedures in read-only Cypher guard - #1735
Merged
Shashankss1205 merged 1 commit intoSep 27, 2026
Merged
Shashankss1205 merged 1 commit into
Shashankss1205 merged 1 commit into
Conversation
is_read_only_cypher() blocklisted write procedures by name prefix (apoc, dbms, db.*), which any procedure outside those namespaces bypassed entirely — e.g. Neo4j GDS write/mutate procedures or neosemantics' n10s.rdf.import.fetch (SSRF + write). CALL is now rejected by default and only permitted for a small, explicit allowlist of read-only introspection procedures (db.labels, db.relationshipTypes, db.propertyKeys, db.schema.visualization, db.indexes). CALL subqueries and any unrecognised procedure name fail closed. Fixes CodeGraphContext#1727
|
@ayushi2577 is attempting to deploy a commit to the shashankss1205's projects Team on Vercel. A member of the Team first needs to authorize it. |
Contributor
Author
|
@Shashankss1205 Please review it ! |
Shashankss1205
approved these changes
Sep 27, 2026
Shashankss1205
left a comment
Collaborator
There was a problem hiding this comment.
Verified locally: trial-merged onto main, the guard suite plus every test touching the read-only path (120 tests) pass. Inverting to an allowlist is the right model — fail closed. Thanks!
bismay70
pushed a commit
to bismay70/CodeGraphContext
that referenced
this pull request
Oct 15, 2026
…lowlist CodeGraphContext#1735 inverted the read-only guard to a CALL allowlist, but listed only Neo4j db.* procedures, so `cgc query "CALL show_tables() RETURN *"` stopped working on Kùzu, the default backend. Adds Kùzu/LadybugDB's read-only table functions; config-setting CALLs and FTS index create/drop stay rejected. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1727
What
is_read_only_cypher()blocked write procedures by matching specific nameprefixes (
apoc,dbms,db.*). Anything outside those three namespaces —e.g. Neo4j GDS write/mutate procedures (
gds.pageRank.write,gds.louvain.mutate) or neosemantics (n10s.rdf.import.fetch, SSRF + writein one call) — passed the guard untouched.
Fix
Invert the model:
CALLis now rejected by default and only allowed for anexplicit, auditable allowlist of read-only introspection procedures
(
db.labels,db.relationshipTypes,db.propertyKeys,db.schema.visualization,db.indexes). AnyCALLwhose procedure nameisn't recognized — including a
CALL { ... }subquery, where no procedurename can even be parsed — fails closed.
Reuses the existing literal/comment-stripping and clause-position logic from
#1511 so
n.call,$call,AS call, and identifiers that merely contain"call" keep working as before.
Testing
test_allows_allowlisted_introspection_calls,test_blocks_call_to_unlisted_procedures, andtest_call_subquery_still_rejectedtotests/unit/utils/test_cypher_readonly.py.test_cypher_readonly.pyandtest_cypher_readonly_enforcement.pystill pass unchanged../tests/run_tests.sh fast.Out of scope
Extending
_read_session_kwargs()to give Kuzu/embedded-Kuzu/Nornic/Ladybuga session-level read backstop, as discussed on the issue — tracking
separately since those engines have no equivalent to request.