Filesystem Claude Middleware Rejects Allowed Nested Paths On Windows
On Windows, path validation in FilesystemClaudeTextEditorMiddleware and FilesystemClaudeMemoryMiddleware rejects valid nested virtual paths due to backslash vs forward slash mismatch in allowed_prefixes comparison.
The `_validate_and_resolve_path` method reconstructs `virtual_path` using `str(full_path.relative_to(self.root_path))`, which yields Windows backslashes in the relative path. The subsequent `_is_within_allowed_prefix` check compares forward-slash directory boundaries, so a valid descendant like `/workspace/nested/file.txt` is not recognized as starting with `/workspace/` and raises ValueError.
On a Windows machine, create a temporary directory with `workspace/nested` subdirectories. Instantiate `FilesystemClaudeTextEditorMiddleware(root_path=str(temp_dir), allowed_prefixes=['/workspace'])`. Call `middleware._validate_and_resolve_path('/workspace/nested/file.txt')`. It raises `ValueError: Path must start with one of: ['/workspace']`.
Fixing Code Block
def _validate_and_resolve_path(self, virtual_path: str) -> Path:
if not virtual_path.startswith("/"):
raise ValueError("Path must start with '/'")
relative_path = virtual_path.lstrip("/")
full_path = (self.root_path / relative_path).resolve()
try:
full_path.relative_to(self.root_path.resolve())
except ValueError:
raise ValueError("Path is outside the root directory")
# Normalize to POSIX separators for allowed_prefixes comparison
normalized_virtual_path = "/" + full_path.relative_to(self.root_path.resolve()).as_posix()
if not self._is_within_allowed_prefix(normalized_virtual_path):
raise ValueError(f"Path must start with one of: {self.allowed_prefixes}")
return full_path
The fix replaces the Windows backslash-returning `str(full_path.relative_to(...))` with `.as_posix()`, which always produces forward slashes. The leading slash is preserved, and the prefix check now receives `/workspace/nested/file.txt` instead of a Windows-style path with backslashes, correctly matching `/workspace/`.
Edge Case Audit
This change only normalizes path separators and does not alter security boundaries, but verify on both Windows and POSIX. If the codebase later refactors path handling to use `os.path.sep` instead of `Path.as_posix()`, the issue may reappear. No data migration or public API change is required. To rollback, revert the virtual path reconstruction line to the previous `str()` form and disable nested-path support on Windows until a permanent fix is applied.