mastra-ai/mastra · error

Invalid ${label} path: ${input}

Error message

Invalid ${label} path: ${input}

What it means

Thrown by #assertRelativePath when a path supplied to a workspace skill operation is absolute or contains traversal segments ('..'). It normalizes backslashes to forward slashes and rejects any path that starts with '/' or has a '..' segment, returning the cleaned segment list on success.

Source

Thrown at packages/core/src/workspace/skills/workspace-skills.ts:1488

  /**
   * Join path segments (workspace paths use forward slashes)
   */
  #joinPath(...segments: string[]): string {
    return segments
      .map((seg, i) => (i === 0 ? stripTrailingSlashes(seg) : stripLeadingAndTrailingSlashes(seg)))
      .filter(Boolean)
      .join('/');
  }

  /**
   * Validate and normalize a relative path to prevent directory traversal.
   * Throws if the path contains traversal segments (..) or is absolute.
   */
  #assertRelativePath(input: string, label: string): string {
    const normalized = input.replace(/\\/g, '/');
    const segments = normalized.split('/').filter(seg => Boolean(seg) && seg !== '.');
    if (normalized.startsWith('/') || segments.some(seg => seg === '..')) {
      throw new Error(`Invalid ${label} path: ${input}`);
    }
    return segments.join('/');
  }

  /**
   * Get parent path
   */
  #getParentPath(path: string): string {
    const lastSlash = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\'));
    return lastSlash > 0 ? path.substring(0, lastSlash) : '/';
  }
}

/**
 * Split a path into segments, tolerating both POSIX (`/`) and Windows (`\`)
 * separators. Workspace-internal paths use forward slashes, but consumer-supplied
 * absolute paths (e.g. via `new Workspace({ skills: [...] })`) may use backslashes
 * on Windows.

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Sanitize the input: strip leading slashes and resolve/remove '.' and '..' segments before calling
  2. Reject absolute or traversal inputs at your app boundary (e.g. return a validation error to the caller)
  3. Resolve paths against a known base directory and verify the result stays inside it
  4. Use paths returned by the skills API (discovered references/scripts/assets) instead of free-form input

Example fix

// before
await skills.readSkillFile(skillId, userInputPath);
// after
const rel = userInputPath.replace(/\\/g, '/').split('/').filter(s => s && s !== '.');
if (userInputPath.startsWith('/') || rel.some(s => s === '..')) throw new Error('invalid path');
await skills.readSkillFile(skillId, rel.join('/'));
Defensive patterns

Strategy: validation

Validate before calling

function isSafeRelativePath(p: string): boolean {
  const norm = p.replace(/\\/g, '/');
  if (norm.startsWith('/')) return false;
  const segs = norm.split('/').filter(s => s && s !== '.');
  return !segs.some(s => s === '..');
}

Type guard

function isRelativeSkillPath(p: unknown): p is string {
  return typeof p === 'string' && p.length > 0 && isSafeRelativePath(p);
}

Try / catch

try {
  await skills.readSkillFile(id, path);
} catch (e) {
  if (e instanceof Error && /Invalid .* path:/.test(e.message)) {
    return { error: 'Path must be relative and cannot contain ..' };
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling skill file APIs (read/write/reference/script/asset path operations) with inputs like '/etc/passwd', '../secret.txt', 'C:\\tmp\\file', or any string containing a '..' segment.

Common situations: Model- or user-supplied paths passed straight through to skill file tools; joining a user-controlled relative path onto a skill base dir without sanitizing; Windows-style absolute paths pasted in.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/381a9466b5607961. Report an issue: GitHub.