Security Considerations for Deploying Code-Graph-RAG in Production
Deploy Code-Graph-RAG securely by binding the Memgraph and Qdrant services to loopback interfaces, disabling hybrid front-ends for untrusted repositories, enabling bearer-token authentication for the MCP server, and storing API keys in restricted environment files with 600 permissions.
Code-Graph-RAG builds knowledge graphs of codebases using Tree-sitter parsers and stores them in a local Memgraph instance, with optional vector embeddings in Qdrant. When moving from local experimentation to production environments, understanding the trust boundaries and threat model is essential to prevent unauthorized network access, code execution, and data exfiltration. This guide covers the security architecture, threat model, and hardening steps required for a safe deployment.
Core Security Architecture
Code-Graph-RAG integrates several components, each with specific security concerns and mitigations defined in docs/architecture/security.md:
-
Tree-sitter Parsing reads source files and produces ASTs. Pure parsers never execute repository code, but the C++ (
CPP_FRONTEND=hybrid) and C# (CSHARP_FRONTEND=auto) front-ends invoke external toolchains that may run parts of the repository under the current user's privileges. For untrusted repositories, explicitly setCSHARP_FRONTEND=treesitterto avoid invoking the Roslyn compiler. -
Memgraph Graph Store holds the structural graph locally. By default, Docker exposes port
7687on all network interfaces, making it reachable from any host on the same network if not properly bound. -
Qdrant Vector Store stores embeddings for semantic search. Like Memgraph, it publishes port
6333to the host network by default and requires the same loopback binding hardening. -
LLM and Embedding Providers send code snippets and queries to embedding services. All external traffic uses TLS enforced via
httpx. By default, the system uses a local UniXcoder model; external providers like OpenAI are only contacted whenCGR_EMBEDDING_PROVIDER=openaiis explicitly set. -
MCP Server provides an HTTP API for agents. It binds to
127.0.0.1by default. Binding to a non-loopback address requires setting theMCP_HTTP_AUTH_TOKENenvironment variable and implementing bearer-token validation. -
Agent Tools (CLI) execute shell commands and edit files on user request. The default mode screens commands against an allowlist and blocks destructive paths. A "YOLO" mode exists to disable this protection but is off by default.
-
XML and Other Parsers use
defusedxmlto safely parse XML from target projects, disabling dangerous features that could lead to entity-expansion attacks.
Threat Model and Trust Boundaries
The security model defines four primary trust boundaries that operators must enforce:
-
Untrusted Repository Input – The repository being indexed is treated as hostile input. While pure Tree-sitter parsers cannot execute code, hybrid front-ends for C++ and C# may invoke toolchains that run repository build scripts under the current user's privileges.
-
Local Service Exposure – Memgraph and Qdrant run in Docker containers with ports published to the host network. Without explicit loopback binding, these services are reachable from any host on the same network, creating an unauthenticated access vector.
-
LLM and Embedding Provider Boundary – When configured to use remote providers, code snippets travel over TLS. API keys are supplied via environment variables (
.env) and are never stored inside the graph database. -
MCP Server Boundary – By default, the server only listens on
127.0.0.1. If exposed to the network, authentication via a bearer token is mandatory.
The security model guarantees that credentials never appear in the graph and that network-exposed services are unauthenticated by default, requiring the operator to implement additional network controls or authentication layers.
Production Hardening Recommendations
Implement these controls to secure a production deployment:
-
Restrict Docker Port Bindings – Prevent unauthenticated remote access by binding Memgraph and Qdrant to localhost only. Use
-p 127.0.0.1:7687:7687for Memgraph and-p 127.0.0.1:6333:6333for Qdrant. This addresses the exposure tracked in issue #1012. -
Disable Hybrid Front-ends for Untrusted Code – Hybrid front-ends may execute build scripts. Export
CSHARP_FRONTEND=treesitterandCPP_FRONTEND=treesitterbefore runningcgr startto force pure parsing mode. -
Run the Daemon Stack Behind a Firewall – Limit exposure to internal networks only by using Docker's private bridge networks or restricting traffic to trusted IP ranges via host-level firewalls.
-
Secure LLM API Keys – Store keys in a
.envfile with restrictive permissions (chmod 600 .env) and never commit this file to version control. Thecodebase_rag/stack/manager.pyfile handles daemon lifecycle commands and respects these environment variables. -
Enable MCP Authentication – When binding the MCP server to a non-loopback address, set
MCP_HTTP_AUTH_TOKEN=<strong-token>and configure clients to send the bearer token in the HTTP Authorization header. -
Audit Dependencies – Supply-chain attacks are mitigated by pinned dependencies in
uv.lock. The project runs OSV-Scanner and Dependabot checks via CI. Keepuv.lockupdated and verify checksums. -
Use Signed Releases – Verify release artifacts with Sigstore to guarantee integrity. Use
cosign verify-blobwith the provided public key for the release tarball. -
Apply Least-Privilege Runtime – Run the daemon under a dedicated system user with limited permissions. Start the Docker stack with that user's UID to minimize blast radius.
Configuration Examples
Apply these hardening configurations in your production environment:
# 1. Restrict Docker port bindings to localhost (loopback)
docker run -d \
--name memgraph \
-p 127.0.0.1:7687:7687 \
memgraph/memgraph
docker run -d \
--name qdrant \
-p 127.0.0.1:6333:6333 \
qdrant/qdrant
# 2. Disable C# and C++ hybrid front-ends for untrusted repos
export CSHARP_FRONTEND=treesitter
export CPP_FRONTEND=treesitter
cgr start --repo-path /path/to/repo --update-graph
# 3. Secure MCP server with token authentication
export MCP_HTTP_AUTH_TOKEN="s3cr3t-token-$(uuidgen)"
cgr daemon up
# To bind to a specific interface with auth:
# cgr daemon up --bind 0.0.0.0 --token "$MCP_HTTP_AUTH_TOKEN"
# 4. Store API keys in a protected .env file
cat > .env <<EOF
OPENAI_API_KEY=sk-********************
MCP_HTTP_AUTH_TOKEN=s3cr3t-token-$(uuidgen)
EOF
chmod 600 .env
# 5. Verify a signed release artifact (example for version 0.0.484)
cosign verify-blob --key cosign.pub code-graph-rag-0.0.484.tar.gz
Key Implementation Files
Reference these source files to understand and configure the security posture:
-
docs/architecture/security.md– Contains the full security model, threat analysis, and assurance case for the system. -
.github/SECURITY.md– Defines the vulnerability reporting policy and security response procedures. -
codebase_rag/stack/manager.py– Implements daemon lifecycle commands includingdaemon_upanddaemon_down, handling service startup and binding logic. -
codebase_rag/stack/constants.py– Stores user-facing error messages and guidance for daemon binding and authentication failures. -
codebase_rag/cli.py– Serves as the CLI entry point and includes routing logic for MCP and daemon commands. -
docs/architecture/graph-schema.md– Describes how front-ends map source code to the unified graph schema, which is relevant when evaluating parsing modes.
Summary
- Bind Memgraph (port
7687) and Qdrant (port6333) to127.0.0.1to prevent unauthenticated remote access. - Set
CSHARP_FRONTEND=treesitterandCPP_FRONTEND=treesitterwhen indexing untrusted repositories to avoid arbitrary code execution via build toolchains. - Protect API keys in
.envfiles withchmod 600permissions, and enableMCP_HTTP_AUTH_TOKENwhen exposing the MCP server beyond localhost. - Verify release integrity using Sigstore cosign and maintain dependency hygiene by auditing the pinned
uv.lockfile.
Frequently Asked Questions
Does Code-Graph-RAG execute the code it indexes?
Pure Tree-sitter parsers do not execute code, but the C++ and C# hybrid front-ends (CPP_FRONTEND=hybrid, CSHARP_FRONTEND=auto) may invoke external toolchains that run repository build scripts under the current user's privileges. To prevent execution, set these environment variables to treesitter before running cgr start.
How do I prevent remote access to the Memgraph database?
By default, Docker publishes port 7687 on all interfaces. Bind it to loopback only by using the flag -p 127.0.0.1:7687:7687 when starting the container. The project tracks a change to make this the default behavior in issue #1012.
Is data sent to external LLM providers encrypted?
Yes, all HTTP traffic to external providers uses TLS via the httpx library. However, be aware that sensitive code leaves your machine when using external providers. The default configuration uses a local UniXcoder model; external providers are only contacted when CGR_EMBEDDING_PROVIDER=openai is explicitly configured.
How does the MCP server handle authentication?
By default, the MCP server binds to 127.0.0.1 and requires no authentication. If you bind it to a non-loopback address using --bind, you must set the MCP_HTTP_AUTH_TOKEN environment variable. Clients must then include the token as a Bearer token in the Authorization HTTP header, as enforced by the logic in codebase_rag/cli.py.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →