Version
codebase-memory-mcp 0.10.5
Platform
Windows (x64)
Install channel
npm
Binary variant
standard
What happened, and what did you expect?
Summary
On Windows, codebase-memory-mcp allow-root --approve-sensitive <path> records a sensitive-root grant, but
index_repository (and the HTTP UI indexing route) still refuses the exact same path with:
C:/Program Files (x86)/Steam/steamapps/common/Factorio/data: path is a home or credential directory.
To index it anyway, run: codebase-memory-mcp allow-root --approve-sensitive C:/Program Files (x86)/Steam/steamapps/common/Factorio/data
The grant appears to be recorded correctly (with the ! sensitive marker), yet the refusal persists for any
path whose first component under the drive is Program Files / Program Files (x86) — i.e. the escape hatch
is broken exactly where it is needed most.
Root cause
The refusal is a byte-exact string equality check failing across Windows path-separator mismatch.
-
index_repository calls cbm_workspace_root_allowed (src/mcp/mcp.c:8074). Before that, the repo path is
canonicalized and its separators are normalized to forward slashes:
// src/mcp/mcp.c:1396-1398 (canonicalize_repo_path_if_exists)
if (cbm_canonical_path(repo_path, real, sizeof(real))) {
cbm_normalize_path_sep(real);
...
-
The candidate path is classified sensitive because Program Files (x86) matches WS_WINDOWS_SYSTEM_TREES
(src/foundation/workspace.c:159-164), returning CBM_WS_DENY_SENSITIVE from
cbm_workspace_classify_root.
-
A sensitive refusal can only be lifted by an exact sensitive-grant match. In cbm_workspace_root_allowed:
// src/foundation/workspace.c:548
if (verdict == CBM_WS_DENY_SENSITIVE && match.exact_sensitive) {
return true;
}
match.exact_sensitive is set in ws_match_visit:
// src/foundation/workspace.c:394-395
if (sensitive && ws_paths_equal(root, m->candidate)) {
m->exact_sensitive = true;
}
ws_paths_equal is a raw byte comparison (src/foundation/workspace.c:230-232) — it does not normalize
separators and uses strncmp/strlen with no case folding in ws_is_ancestor_or_equal
(src/foundation/workspace.c:216-228).
-
The grant itself is stored with native Windows backslashes because allow-root writes the canonical path
without normalizing separators (src/main.c:1014-1025 → cbm_workspace_grant_add → fprintf(f, ...),
src/foundation/workspace.c:480). So the grant file line is:
!C:\Program Files (x86)\Steam\steamapps\common\Factorio\data
while the candidate the indexer compares against is normalized to:
C:/Program Files (x86)/Steam/steamapps/common/Factorio/data
"C:\Program Files..." vs "C:/Program Files..." are not byte-equal → exact_sensitive stays false →
the sensitive override is ignored → the path is refused.
Why it only bites Windows system-tree paths
Non-sensitive paths (e.g. E:\Factorio) are allowed as soon as they are contained by a grant
(match.contained, checked via cbm_path_within_root, which does normalize separators and does
case-insensitive comparison on Windows, src/mcp/mcp.c:8406-8419). They never reach the exact-separator
check. Only CBM_WS_DENY_SENSITIVE refusals — which are precisely the Program Files / Users /
credential-name cases — require ws_paths_equal, and that byte compare is where the separator mismatch
kills the override.
Impact
allow-root --approve-sensitive becomes a no-op for every Windows path beneath Program Files /
Program Files (x86) — the most common location for installed software trees (e.g. a Steam game's
data folder containing moddable prototypes/scripts/API sources).
- The error message unconditionally suggests the exact command that has already been run and cannot succeed,
so there is no in-band way to proceed.
Suggested fix
Normalize path separators consistently when comparing a stored grant against a candidate, in
cbm_workspace_grant_add's canonicalization and/or in the equality path used by
cbm_workspace_root_allowed. Concretely:
- Normalize the stored grant to forward slashes at write time (
src/foundation/workspace.c:480), and/or
- Make the sensitivity override use a separator-insensitive (and on Windows case-insensitive) comparison —
e.g. reuse cbm_path_within_root/canonical_path_has_root semantics (which already normalize and fold
case on Windows) for the exact_sensitive test instead of the byte-exact ws_paths_equal.
Note there is also an asymmetry worth unifying: allow-root stores backslashes while index_repository
normalizes to forward slashes, which is the immediate cause of the mismatch. Both paths should agree on the
same canonical form.
Environment
- OS: Windows (NTFS, case-insensitive)
- codebase-memory-mcp version: 0.10.5
- Path type affected:
C:\Program Files (x86)\...
Reproduction
Reproduction
On Windows (tested with codebase-memory-mcp 0.10.5):
# 1. Record the sensitive grant
codebase-memory-mcp allow-root --approve-sensitive 'C:/Program Files (x86)/Steam/steamapps/common/Factorio/data'
# -> "allowed root recorded: C:\Program Files (x86)\Steam\steamapps\common\Factorio\data"
# 2. Grant file now contains (note backslashes)
# !C:\Program Files (x86)\Steam\steamapps\common\Factorio\data
# 3. Attempt to index — always refuses despite the recorded grant
codebase-memory-mcp cli index_repository --repo-path 'C:/Program Files (x86)/Steam/steamapps/common/Factorio/data'
# -> "...: path is a home or credential directory. To index it anyway, run: ... --approve-sensitive ..."
Logs
Diagnostics trajectory (memory / performance / leak issues)
Project scale (if relevant)
No response
Confirmations
Version
codebase-memory-mcp 0.10.5
Platform
Windows (x64)
Install channel
npm
Binary variant
standard
What happened, and what did you expect?
Summary
On Windows,
codebase-memory-mcp allow-root --approve-sensitive <path>records a sensitive-root grant, butindex_repository(and the HTTP UI indexing route) still refuses the exact same path with:The grant appears to be recorded correctly (with the
!sensitive marker), yet the refusal persists for anypath whose first component under the drive is
Program Files/Program Files (x86)— i.e. the escape hatchis broken exactly where it is needed most.
Root cause
The refusal is a byte-exact string equality check failing across Windows path-separator mismatch.
index_repositorycallscbm_workspace_root_allowed(src/mcp/mcp.c:8074). Before that, the repo path iscanonicalized and its separators are normalized to forward slashes:
The candidate path is classified sensitive because
Program Files (x86)matchesWS_WINDOWS_SYSTEM_TREES(
src/foundation/workspace.c:159-164), returningCBM_WS_DENY_SENSITIVEfromcbm_workspace_classify_root.A sensitive refusal can only be lifted by an exact sensitive-grant match. In
cbm_workspace_root_allowed:match.exact_sensitiveis set inws_match_visit:ws_paths_equalis a raw byte comparison (src/foundation/workspace.c:230-232) — it does not normalizeseparators and uses
strncmp/strlenwith no case folding inws_is_ancestor_or_equal(
src/foundation/workspace.c:216-228).The grant itself is stored with native Windows backslashes because
allow-rootwrites the canonical pathwithout normalizing separators (
src/main.c:1014-1025→cbm_workspace_grant_add→fprintf(f, ...),src/foundation/workspace.c:480). So the grant file line is:while the candidate the indexer compares against is normalized to:
"C:\Program Files..."vs"C:/Program Files..."are not byte-equal →exact_sensitivestaysfalse→the sensitive override is ignored → the path is refused.
Why it only bites Windows system-tree paths
Non-sensitive paths (e.g.
E:\Factorio) are allowed as soon as they are contained by a grant(
match.contained, checked viacbm_path_within_root, which does normalize separators and doescase-insensitive comparison on Windows,
src/mcp/mcp.c:8406-8419). They never reach the exact-separatorcheck. Only
CBM_WS_DENY_SENSITIVErefusals — which are precisely theProgram Files/Users/credential-name cases — require
ws_paths_equal, and that byte compare is where the separator mismatchkills the override.
Impact
allow-root --approve-sensitivebecomes a no-op for every Windows path beneathProgram Files/Program Files (x86)— the most common location for installed software trees (e.g. a Steam game'sdatafolder containing moddable prototypes/scripts/API sources).so there is no in-band way to proceed.
Suggested fix
Normalize path separators consistently when comparing a stored grant against a candidate, in
cbm_workspace_grant_add's canonicalization and/or in the equality path used bycbm_workspace_root_allowed. Concretely:src/foundation/workspace.c:480), and/ore.g. reuse
cbm_path_within_root/canonical_path_has_rootsemantics (which already normalize and foldcase on Windows) for the
exact_sensitivetest instead of the byte-exactws_paths_equal.Note there is also an asymmetry worth unifying:
allow-rootstores backslashes whileindex_repositorynormalizes to forward slashes, which is the immediate cause of the mismatch. Both paths should agree on the
same canonical form.
Environment
C:\Program Files (x86)\...Reproduction
Reproduction
On Windows (tested with codebase-memory-mcp 0.10.5):
Logs
Diagnostics trajectory (memory / performance / leak issues)
Project scale (if relevant)
No response
Confirmations