Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/codegraphcontext/utils/cypher_readonly.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@
"db.propertykeys",
"db.schema.visualization",
"db.indexes",
# Kùzu / LadybugDB (the default embedded backends) expose schema
# introspection as table functions rather than db.* procedures. All are
# read-only; Kùzu's config form `CALL threads=4` is not on the list and
# stays rejected.
"show_tables",
"table_info",
"show_connection",
"show_indexes",
"db_version",
})

_FORBIDDEN_PATTERNS = (
Expand Down
18 changes: 17 additions & 1 deletion tests/unit/utils/test_cypher_readonly.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,20 @@ def test_blocks_call_to_unlisted_procedures():


def test_call_subquery_still_rejected():
assert not is_read_only_cypher("CALL { MATCH (n) RETURN n } RETURN 1")
assert not is_read_only_cypher("CALL { MATCH (n) RETURN n } RETURN 1")


def test_allows_kuzu_introspection_table_functions():
# Kùzu is the default backend; its schema introspection must keep working
# through `cgc query` after the CALL allowlist (#1727).
assert is_read_only_cypher("CALL show_tables() RETURN *")
assert is_read_only_cypher("CALL SHOW_TABLES() RETURN *")
assert is_read_only_cypher("CALL table_info('Function') RETURN *")
assert is_read_only_cypher("CALL show_connection('CALLS') RETURN *")
assert is_read_only_cypher("CALL db_version() RETURN *")


def test_kuzu_config_and_index_writes_still_rejected():
assert not is_read_only_cypher("CALL threads=4")
assert not is_read_only_cypher("CALL create_fts_index('Function', 'idx', ['name'])")
assert not is_read_only_cypher("CALL drop_fts_index('Function', 'idx')")
Loading