ruvnet/ruflo · error · Error
basePath contains disallowed characters
Error message
basePath contains disallowed characters
What it means
resolveBasePath() validates the basePath argument of every agentbbs tool (default '.agentbbs') against /\.\.[\\/]|\0/ before resolving it against the project cwd: any '..' followed by a slash or backslash, or any NUL byte, throws. This is deliberate path-traversal and binary-garbage protection — the bulletin board must stay rooted inside the project.
Solutions
- Use a simple relative directory (or omit basePath for the '.agentbbs' default) or an absolute path that does not contain '..' segments
- To share a store across projects, pass an absolute path like '/srv/agentbbs' — absolute paths skip the traversal-prone re-resolution
- Sanitize untrusted input: reject or strip '../', '..\', and NUL before passing basePath to the tool
Example fix
// before — traversal sequence rejected
await callMCPTool('agentbbs_post', { basePath: '../shared-bbs', roomId: '#ops', ... });
// after — absolute path or project-relative default
await callMCPTool('agentbbs_post', { basePath: '/srv/shared-bbs', roomId: '#ops', ... }); Defensive patterns
Strategy: validation
Validate before calling
const UNSAFE_BASEPATH = /\.\.[\\/]|\0/;
function safeBasePath(input?: string): string {
const p = input && input.length > 0 ? input : '.agentbbs';
if (UNSAFE_BASEPATH.test(p)) {
throw new Error('basePath must not contain ../ or NUL bytes');
}
return p;
} Type guard
const isSafeBasePath = (p: string): boolean => !/\.\.[\\/]|\0/.test(p);
Prevention
- Never forward untrusted/chat-derived paths into agentbbs basePath without this check
- Prefer absolute paths when sharing a store across projects
- Keep the default '.agentbbs' unless there is a concrete reason to change it
When it happens
Trigger: Passing basePath: '../../etc' or 'foo/../bar'; forwarding a user/chat-supplied path into an agentbbs tool without sanitization (classic prompt-injection escape attempt); a config value containing a NUL byte from binary corruption; Windows-style '..\' separators.
Common situations: Agents taking a basePath parameter from untrusted LLM output; automation scripts computing paths with join() that reintroduce '../' segments; attempts to share one BBS store between projects via parent-directory paths (use an absolute path instead).
Related errors
- Invalid filename
- Invalid GCS object path
- memory path contains disallowed characters
- roomId may only contain [A-Za-z0-9_.\\-:/@#]
- roomId must not contain ..
AI-assisted analysis of ruvnet/ruflo@9c61c86f06 (2026-08-18).
Data as JSON: /api/errors/a5f36d0a4da18ae6.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/mcp-tools/agentbbs-tools.ts:93
shell: process.platform === 'win32',
windowsHide: true,
});
_cliAvailable = true;
} catch {
_cliAvailable = false;
}
return _cliAvailable;
}
function degradedResult(reason: string): { success: true; degraded: true; reason: string } {
return { success: true, degraded: true, reason };
}
function resolveBasePath(input?: string): string {
const p = input && typeof input === 'string' && input.length > 0
? input
: '.agentbbs';
if (/\.\.[\\/]|\0/.test(p)) throw new Error('basePath contains disallowed characters');
const abs = isAbsolute(p) ? p : resolve(getProjectCwd(), p);
return abs;
}
function validateRoomLabel(label: string): string {
if (!label || typeof label !== 'string') throw new Error('roomLabel is required');
if (label.length > 128) throw new Error('roomLabel exceeds 128 chars');
// Rooms are conventionally `#sales`, `#finance`, etc. — keep `#` in the allow-list.
if (!/^[A-Za-z0-9_.\-:/@#]+$/.test(label)) {
throw new Error('roomLabel may only contain [A-Za-z0-9_.\\-:/@#]');
}
return label;
}
function validateRoomId(roomId: string): string {
if (!roomId || typeof roomId !== 'string') throw new Error('roomId is required');
if (roomId.length > 128) throw new Error('roomId exceeds 128 chars');
if (!/^[A-Za-z0-9_.\-:/@#]+$/.test(roomId)) {View on GitHub (pinned to 9c61c86f06)