Skip to content

security: Cypher injection via .cgc bundle labels and relationship types #1382

Closed

Description

@Shashankss1205

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

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.

Activity

  1. added
    bugSomething isn't working
    severity: criticalSilent data loss, arbitrary query execution, or a headline feature that never works
    area: graphDatabase abstraction, Cypher generation, schema, bundles
    on Jul 26, 2026
  2. github-actions commented on Jul 26, 2026

    @github-actions
    Contributor

    Hi! 👋 Join our CodeGraphContext Discord channel to collaborate: https://discord.gg/dR4QY32uYQ

  3. moved this from Backlog tasks to In progress in CGC Progress Boardon Jul 26, 2026
  4. moved this from In progress to Done in CGC Progress Boardon Jul 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: graphDatabase abstraction, Cypher generation, schema, bundlesbugSomething isn't workingseverity: criticalSilent data loss, arbitrary query execution, or a headline feature that never works

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions