How CBM_ALLOWED_ROOT Restricts Indexing in Multi-Tenant Environments
CBM_ALLOWED_ROOT is an environment variable that confines repository indexing to a specific filesystem boundary, preventing untrusted callers from accessing arbitrary paths outside the tenant's designated directory.
The codebase-memory-mcp service provides Model Context Protocol (MCP) capabilities for indexing code repositories, but when operating in multi-tenant deployments or with untrusted AI agents, it must block attempts to index sensitive host paths. By setting CBM_ALLOWED_ROOT, administrators can enforce strict filesystem isolation, ensuring that each tenant's indexing operations remain confined to their allocated directory.
The Security Mechanism Behind CBM_ALLOWED_ROOT
When the index_repository command is invoked, the implementation in src/mcp/mcp.c performs a four-step validation process before any graph or database operations begin.
Path Canonicalization and Resolution
First, the supplied repo_path undergoes normalization to resolve absolute paths and eliminate symbolic links. The function canonicalize_repo_path_if_exists converts relative paths and components like ../ into a clean, absolute form, preventing attackers from using path traversal sequences to escape intended boundaries.
Environment Variable Enforcement
Second, the code retrieves the guard variable:
const char *allowed_root = getenv("CBM_ALLOWED_ROOT");
If CBM_ALLOWED_ROOT is set and non-empty, the system enters restricted mode and validates the requested path against this root.
The cbm_path_within_root Validation
Third, the helper function cbm_path_within_root (implemented in src/util/path.c) performs a secure prefix comparison. This function canonicalizes both the allowed root and the requested repository path, then verifies that the repository path is a descendant of the allowed root directory.
Rejection of Out-of-Scope Requests
Finally, if the validation fails, the command returns an error before any pipeline creation occurs. As seen in lines 4819-4826 of src/mcp/mcp.c, the implementation returns:
if (allowed_root && allowed_root[0] && repo_path &&
!cbm_path_within_root(allowed_root, repo_path)) {
return cbm_mcp_text_result("repo_path is outside the allowed root", true);
}
This ensures that no graph or database is touched for disallowed paths, providing fail-safe isolation.
Multi-Tenant Deployment Configuration
In a multi-tenant environment, each tenant receives a dedicated workspace directory. By exporting CBM_ALLOWED_ROOT before starting the MCP service, you can isolate tenant operations completely.
Configuration Example
To restrict a service instance to a specific tenant:
# Set the boundary for tenant-42
export CBM_ALLOWED_ROOT=/srv/mcp/tenant-42
# Start the service
./codebase-memory-mcp
Valid and Invalid Path Examples
With the above configuration, the service behaves as follows:
# Permitted: Path within the allowed root
codebase-memory-mcp index_repository repo_path=/srv/mcp/tenant-42/project1
# Result: Indexing proceeds normally
# Blocked: Path outside the allowed root
codebase-memory-mcp index_repository repo_path=/etc
# Result: Error - "repo_path is outside the allowed root"
# Blocked: Path traversal attempt
codebase-memory-mcp index_repository repo_path=/srv/mcp/tenant-42/../../../etc/passwd
# Result: Error - canonicalized path resolves outside allowed root
Implementation Details and Code References
The restriction logic resides in the MCP command handler at src/mcp/mcp.c, with the core path validation implemented in src/util/path.c. The cbm_path_within_root function handles the secure comparison, ensuring that both paths are canonicalized before checking the prefix relationship.
This mechanism is documented in the docs/CONFIGURATION.md reference guide and summarized in the repository's README.md, providing administrators with clear guidance on securing multi-tenant deployments.
Summary
- CBM_ALLOWED_ROOT acts as a filesystem boundary guard that prevents indexing outside designated directories.
- The validation occurs in
src/mcp/mcp.cbefore any graph or database operations, ensuring fail-safe rejection of unauthorized paths. - The
cbm_path_within_roothelper insrc/util/path.cperforms secure canonicalization and prefix checking to prevent bypasses via symbolic links or path traversal sequences. - In multi-tenant deployments, setting
CBM_ALLOWED_ROOTto tenant-specific directories (e.g.,/srv/mcp/tenant-123) ensures complete isolation between tenants and protects host system files.
Frequently Asked Questions
What happens if CBM_ALLOWED_ROOT is not set?
When the environment variable is unset or empty, the codebase-memory-mcp service operates without filesystem restrictions, allowing indexing of any path accessible to the process. This mode is suitable for trusted single-tenant environments but should never be used when handling requests from untrusted sources or in multi-tenant configurations.
Can symbolic links bypass the CBM_ALLOWED_ROOT restriction?
No. The implementation calls canonicalize_repo_path_if_exists on the requested path before validation, which resolves symbolic links to their actual targets. The cbm_path_within_root function then compares the canonicalized absolute paths, ensuring that a symlink pointing outside the allowed root is correctly identified and rejected.
How does this protect against path traversal attacks?
The combination of path canonicalization and the cbm_path_within_root prefix check prevents traversal sequences like ../ from escaping the allowed directory. Even if a caller supplies a path like /srv/mcp/tenant-42/../../../etc/passwd, the canonicalization resolves this to /etc/passwd, which fails the descendant check against /srv/mcp/tenant-42.
Is CBM_ALLOWED_ROOT checked for read operations or only indexing?
The analysis focuses on the index_repository MCP command, where the check is explicitly implemented in src/mcp/mcp.c. The restriction applies to repository indexing operations, preventing unauthorized filesystem traversal during the ingestion phase. Administrators should verify whether additional MCP commands in their specific deployment version enforce the same restriction for read operations by consulting the current source code.
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 →