mastra-ai/mastra · error · HTTPException

Invalid file path "${filePath}". Path traversal is not allow

Error message

Invalid file path "${filePath}". Path traversal is not allowed.

What it means

Thrown by assertSafeFilePath when any '/'-separated segment of the skill file path is '..' or '.', indicating path traversal. This prevents escaping the skill directory via segments like '../../etc/passwd'. It is an HTTPException with status 400.

Source

Thrown at packages/server/src/server/handlers/workspace.ts:1314

  return name;
}

/**
 * Validate that a file path is safe (no traversal, no absolute paths).
 * Prevents malicious API responses from writing files outside the skill directory.
 */
function assertSafeFilePath(filePath: string): string {
  // Reject absolute paths
  if (filePath.startsWith('/') || /^[a-zA-Z]:/.test(filePath)) {
    throw new HTTPException(400, {
      message: `Invalid file path "${filePath}". Absolute paths are not allowed.`,
    });
  }
  // Reject path traversal attempts
  const segments = filePath.split('/');
  for (const segment of segments) {
    if (segment === '..' || segment === '.') {
      throw new HTTPException(400, {
        message: `Invalid file path "${filePath}". Path traversal is not allowed.`,
      });
    }
  }
  return filePath;
}

interface SkillFileEntry {
  path: string;
  content: string;
  encoding: 'utf-8' | 'base64';
}

interface SkillFilesResponse {
  skillId: string;
  owner: string;
  repo: string;
  branch: string;

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Remove '.' and '..' segments by resolving and re-relativizing the path before sending it (e.g. path.posix.normalize, then verify it does not start with '..').
  2. Send canonical paths exactly as returned by the Skills API file listing.
  3. Sanitize or reject paths containing traversal segments in your own service before proxying to this endpoint.

Example fix

// before
const p = `${base}/../${name}`;
await installSkill({ workspaceId, filePath: p });
// after
const p = path.posix.normalize(path.posix.join(base, name));
if (p.split('/').includes('..')) throw new Error('traversal');
await installSkill({ workspaceId, filePath: p });
Defensive patterns

Strategy: validation

Validate before calling

function hasNoTraversal(p) {
  return !p.split('/').some(s => s === '..' || s === '.');
}
if (!hasNoTraversal(filePath)) throw new Error('Path contains traversal segments');

Type guard

function isTraversalFree(p: unknown): p is string {
  return typeof p === 'string' && !p.split('/').some(seg => seg === '..' || seg === '.');
}

Try / catch

try {
  await installSkill({ workspaceId, filePath });
} catch (e) {
  if (String(e.message).includes('Path traversal is not allowed')) {
    throw new Error(`Refusing unsafe path: ${filePath}. Use a canonical path from the skill listing.`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Requesting a skill file with a path containing '..' or '.' segments, e.g. 'foo/../../secret.txt' or './SKILL.md', against the workspace skills endpoint.

Common situations: Users constructing paths by string concatenation with user input; directory-style navigation assumptions ('.' for current dir); malicious payloads probing for traversal vulnerabilities.

Related errors


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