Repository navigation
security: Cypher injection via .cgc bundle labels and relationship types #1382
Description
core/cgc_bundle.py:988-995, :1058-1076
label_str = ':'.join(labels) # straight from nodes.jsonl
query = (f"MERGE (n:{label_str} {{{pk_field}: $pk_val}}) SET n += $props …")
# ...
query = f"CREATE (n:{label_str}) SET n = $props RETURN {id_function}(n) as new_id"
# ...
rel_type = edge.get('type') # straight from edges.jsonl
query = f"MATCH (a:{from_label} …), (b:{to_label} …) CREATE (a)-[r:{rel_type}]->(b) SET r = $props"_validate_bundle (:794) checks only that four files exist and that metadata.json has a cgc_version key — it never compares the value. Labels and relationship types are never validated. BundleRegistry.download_file (bundle_registry.py:131) downloads bundles from a HuggingFace dataset with no checksum and no signature.
Reproduced. Two :Victim nodes were seeded in an isolated graph. A bundle was built whose node _labels was:
Evil) WITH n MATCH (v:Victim) DETACH DELETE v //
Evil… is not in _PK_MAP, so it hits the CREATE (n:{label_str}) SET n = $props branch, yielding the executed query:
CREATE (n:Evil) WITH n MATCH (v:Victim) DETACH DELETE v //) SET n = $props …$ cgc bundle import evil.cgc
✅ Successfully imported evil.cgc Nodes: 2 | Edges: 0
Victim nodes remaining: 0 ← pre-existing data destroyed
The import reported success.
Impact. Importing a bundle — a first-class, documented distribution mechanism with seven dedicated docs and a public registry — executes arbitrary Cypher as the CGC user. Combined with the unauthenticated HTTP gateway (POST /api/v1/tools/call → load_bundle), this is remotely reachable.
Fix. Validate every label and relationship type against schema_contract.NODE_LABELS / RELATIONSHIP_TYPES (or at minimum ^[A-Za-z_][A-Za-z0-9_]*$) before interpolation, and reject the bundle otherwise. Add a signed/hashed manifest check in bundle_registry.download_file.
Related existing issues
- Bug: bundle import fails with "Create node n expects primary key name as input" - _PK_MAP missing DbTable/ExternalClass #1322 — hits the same
CREATE (n:{label_str}) SET n = $propsbranch, from a missing_PK_MAPentry - security: Cypher injection regex bypass and missing read-only session enforcement in FalkorDB wrapper #1010 — Cypher injection through a different entry point (the
execute_cypher_queryregex denylist)
Filed separately because the root cause and fix differ; close as a duplicate if maintainers judge otherwise.
Audit environment
| Version | codegraphcontext 0.5.2 (PyPI) |
| Commit | df3af04 |
| Backend | FalkorDB Lite (falkordblite 0.9.0), Python 3.12.3, Linux |
| Corpus | the CodeGraphContext repo itself — 784 files, 23 languages, 5,501 Function nodes |
Audit ID G-C1 · severity critical · from an end-to-end audit of CGC 0.5.2 (63 findings). Reported with the reproduction as run.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
- StatusShow more project fieldsNo status
Activity
github-actions commentedon Jul 26, 2026
Hi! 👋 Join our CodeGraphContext Discord channel to collaborate: https://discord.gg/dR4QY32uYQ