ruvnet/ruflo · error · Error

memory path contains disallowed characters

Error message

memory path contains disallowed characters

What it means

Security guard inside resolveMemoryPath() (agenticow-loader.ts:72): the raw, pre-resolution path is tested against /\.\.[\\/]|\0/ and rejected. This is D-2 style hardening (the same rule the MCP verbs use) blocking path traversal ('../', '..\\') and NUL-byte injection before the path is joined onto the project cwd. Any '..' path segment with a following slash or backslash, anywhere in the string, is enough to trigger it.

Source

Thrown at v3/@claude-flow/cli/src/mcp-tools/agenticow-loader.ts:72

}

/** Reset the module-level load cache. Test-only seam. */
export function __resetAgenticowCache(): void {
  _agenticowMod = null;
  _loadAttempted = false;
}

export function degradedResult(reason: string): { success: true; degraded: true; reason: string } {
  return { success: true, degraded: true, reason };
}

/**
 * Resolve a user-supplied memory path against the project cwd, rejecting path
 * traversal and NUL bytes (D-2 style hardening — same rule the MCP verbs use).
 */
export function resolveMemoryPath(path: string): string {
  if (!path || typeof path !== 'string') throw new Error('memory path is required');
  if (/\.\.[\\/]|\0/.test(path)) throw new Error('memory path contains disallowed characters');
  return isAbsolute(path) ? path : resolve(getProjectCwd(), path);
}

/**
 * Lineage manifest companion path. agenticow persists the COW chain
 * (working → checkpoints → base) into `<file>.agenticow.json` next to the
 * `.rvf` data file. Without it, forks/checkpoints are in-memory only and
 * disappear when the AgenticMemory handle closes.
 */
export function manifestFor(file: string): string {
  return `${file}.agenticow.json`;
}

/** Validate a COW branch/checkpoint label (alnum + a small safe symbol set). */
export function validateLabel(label: string): string {
  if (!label || typeof label !== 'string') throw new Error('label is required');
  if (label.length > 256) throw new Error('label exceeds 256 chars');
  if (!/^[A-Za-z0-9_.\-:/@]+$/.test(label)) {

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Restructure so the memory file lives under the project cwd and reference it with a plain relative path containing no '..' segments
  2. Pass an absolute path when the file genuinely lives outside the project cwd
  3. Sanitize incoming paths yourself (reject '..' segments and NUL) before forwarding them to the tool

Example fix

// before
await callTool('agenticow_ingest', {
  path: '../shared/vectors.rvf', // throws: disallowed characters
  records: [{ vector: [0.1] }],
});

// after
await callTool('agenticow_ingest', {
  path: '/srv/shared/vectors.rvf', // absolute path, no '..' segment
  records: [{ vector: [0.1] }],
});
Defensive patterns

Strategy: validation

Validate before calling

function isSafeMemoryPath(p: string): boolean {
  return !/\.\.[\\/]|\0/.test(p); // same rule as resolveMemoryPath
}
if (!isSafeMemoryPath(userPath)) throw new TypeError('path must not contain .. or NUL');

Try / catch

try {
  await callTool('agenticow_ingest', args);
} catch (e) {
  if (e instanceof Error && e.message.includes('disallowed characters')) {
    return { error: 'bad_request', detail: 'reject path traversal in memory path' };
  }
  throw e;
}

Prevention

When it happens

Trigger: Any agenticow_* tool call whose path contains a parent-directory segment anywhere — '../../etc/passwd', 'data/../../secrets.rvf', '..\\win\\mem.rvf' — or an embedded NUL byte ('\0'). Because the check runs on the raw string before resolve(), even a benign interior segment like 'a/../b' is rejected, not just leading traversal.

Common situations: Paths built by concatenating user input; normalizing paths that legitimately cross directories ('../shared/memory.rvf'); templates that emit relative paths rooted outside the project; adversarial probes against an exposed MCP endpoint.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/7592baeda98207e9. Report an issue: GitHub.