Skip to content

Windows Path Validation Failures in server.mjs #12

@ckelsoe

Description

@ckelsoe

Version: v0.10.2
OS: Windows 11

Summary

On Windows, every file in the Claude Code Organizer dashboard shows "Invalid or disallowed path" when attempting to view file details, restore files, or export. There are two related issues, both caused by Unix path assumptions.

Steps to Reproduce

  1. Install and run on Windows: npx @mcpware/claude-code-organizer
  2. Open dashboard at http://localhost:3847
  3. Click on any discovered file to view its details
  4. Result: "Invalid or disallowed path" error for every file

Root Cause — Two Issues

Issue 1: Hardcoded / in isPathAllowed() (line 47-54)

function isPathAllowed(filePath) {
  const resolved = resolve(filePath);
  if (resolved.startsWith(CLAUDE_DIR + "/") || resolved === CLAUDE_DIR) return true;
  if (resolved.startsWith(HOME + "/")) return true;
  return false;
}

On Windows, resolve() returns paths with \ but the check concatenates with /, producing a mixed separator — which never matches.

Issue 2: startsWith("/") absolute path checks (lines 525, 574, 691)

Multiple API endpoints guard with:

if (!filePath || !filePath.startsWith("/") || !isPathAllowed(filePath)) {

Windows absolute paths start with a drive letter (e.g., C:\), not /, so this rejects every path before isPathAllowed() is even called.

Affected Endpoints

Endpoint Line Purpose
POST /api/restore ~525 File restoration (undo delete)
GET /api/file-content ~574 File detail panel
POST /api/export ~691 Export directory validation

Fix

- import { join, extname, resolve, dirname } from "node:path";
+ import { join, extname, resolve, dirname, sep, isAbsolute } from "node:path";

  // In isPathAllowed():
-   if (resolved.startsWith(CLAUDE_DIR + "/") || resolved === CLAUDE_DIR) return true;
-   if (resolved.startsWith(HOME + "/")) return true;
+   if (resolved.startsWith(CLAUDE_DIR + sep) || resolved === CLAUDE_DIR) return true;
+   if (resolved.startsWith(HOME + sep)) return true;

  // In /api/restore (line ~525):
-   if (!filePath || !filePath.startsWith("/") || !isPathAllowed(filePath)) {
+   if (!filePath || !isAbsolute(filePath) || !isPathAllowed(filePath)) {

  // In /api/file-content (line ~574):
-   if (!filePath || !filePath.startsWith("/") || !isPathAllowed(filePath)) {
+   if (!filePath || !isAbsolute(filePath) || !isPathAllowed(filePath)) {

  // In /api/export (line ~691):
-   if (!exportDir.startsWith("/")) {
+   if (!isAbsolute(exportDir)) {

Notes

  • This bug only affects Windows. Unix/macOS use / natively, so the hardcoded checks work there.
  • The scanner (src/scanner.mjs) correctly uses join() which produces OS-native paths, but the server validation gates reject them.
  • path.isAbsolute() and path.sep are the correct cross-platform alternatives from Node.js stdlib.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions