ruvnet/ruflo · error · Error
${label} escapes project directory
Error message
${label} escapes project directory What it means
Thrown by the internal validatePath() function in daemon.ts when a resolved absolute path does not start with process.cwd() and does not contain '.claude-flow' or 'bin' in its resolved form. This prevents path traversal outside the expected project directory structure. The '.claude-flow' and 'bin' exceptions allow legitimate daemon infrastructure paths.
Source
Thrown at v3/@claude-flow/cli/src/commands/daemon.ts:385
// Must be absolute after resolution
const resolved = resolve(path);
// Check for null bytes (injection attack)
if (path.includes('\0')) {
throw new Error(`${label} contains null bytes`);
}
// Check for shell metacharacters in path components
if (/[;&|`$<>]/.test(path)) {
throw new Error(`${label} contains shell metacharacters`);
}
// Prevent path traversal outside expected directories
if (!resolved.includes('.claude-flow') && !resolved.includes('bin')) {
// Allow only paths within project structure
const cwd = process.cwd();
if (!resolved.startsWith(cwd)) {
throw new Error(`${label} escapes project directory`);
}
}
}
/**
* #1914: Resolve the `--workspace` flag to an absolute path, or return null
* if it is absent / not a usable string. Rejects values with null bytes or
* shell metacharacters (defence-in-depth — the value is later embedded in a
* forked child's argv and compared against `ps`/`tasklist` output).
*/
export function resolveWorkspaceFlag(raw: unknown): string | null {
if (typeof raw !== 'string') return null;
const trimmed = raw.trim();
if (!trimmed) return null;
if (trimmed.includes('\0') || /[;&|`$<>]/.test(trimmed)) return null;
return resolve(trimmed);
}
View on GitHub (pinned to 6b01dc5a68)
Solutions
- Ensure the path resolves within the current working directory
- Remove '../' sequences that would traverse above the project root
- If the path legitimately points to a .claude-flow or bin directory, verify the resolved path contains that substring
Example fix
// before (cwd is /home/user/myproject)
validatePath('../../etc/config', 'config');
// after
validatePath('./config/daemon.json', 'config');
// or use an absolute path within the project
validatePath('/home/user/myproject/config/daemon.json', 'config'); Defensive patterns
Strategy: validation
Validate before calling
import { resolve } from 'path';
function isWithinProject(path: string, cwd: string = process.cwd()): boolean {
const resolved = resolve(path);
return resolved.includes('.claude-flow') || resolved.includes('bin') || resolved.startsWith(cwd);
}
if (!isWithinProject(userPath)) {
throw new Error('Path escapes project directory');
} Type guard
function isWithinCwd(path: string, cwd: string): boolean {
const resolved = resolve(path);
return resolved.startsWith(cwd) || resolved.includes('.claude-flow') || resolved.includes('bin');
} Try / catch
try {
validatePath(userPath, 'workspace');
} catch (e) {
if (e instanceof Error && e.message.includes('escapes project directory')) {
// Use a path within cwd or a .claude-flow directory
userPath = resolve(process.cwd(), userPath.replace(/^\.\.[\/\\]/g, ''));
}
} Prevention
- Use relative paths or paths anchored to process.cwd()
- Avoid '../' sequences that traverse above the project root
- Paths under .claude-flow/ or bin/ are explicitly allowed
When it happens
Trigger: resolve(path) yields an absolute path outside the current working directory (e.g. '/etc/passwd' when cwd is '/home/user/project'), and the resolved path does not include '.claude-flow' or 'bin' as substrings.
Common situations: A relative path with '../' sequences that escapes the project root; an absolute path pointing to system directories; the daemon was started from a different working directory than expected.
Related errors
- ${label} contains null bytes
- ${label} contains shell metacharacters
- basePath contains disallowed characters
- Key contains disallowed characters
- Namespace contains disallowed characters
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/f8617774e51ac9e8.
Report an issue: GitHub.