mastra-ai/mastra · error

Path traversal detected: directory "${directory}" escapes st

Error message

Path traversal detected: directory "${directory}" escapes storage directory

What it means

listDomainFiles() resolves the requested directory against the DB root and throws if the resolved path escapes that root. This guards filesystem-backed storage against path traversal (e.g. '../' sequences) reaching arbitrary directories.

Source

Thrown at packages/core/src/storage/filesystem-db.ts:107

      mkdirSync(parentDir, { recursive: true });
    }

    writeFileSync(tmpPath, JSON.stringify(data, null, 2), 'utf-8');
    renameSync(tmpPath, filePath);
  }

  /**
   * Clear all data from a domain JSON file.
   */
  clearDomain(filename: string): void {
    this.writeDomain(filename, {});
  }

  listDomainFiles(directory: string, extension = '.json'): string[] {
    const baseDir = resolve(this.dir, directory);
    const rootDir = resolve(this.dir);
    if (!baseDir.startsWith(rootDir + sep) && baseDir !== rootDir) {
      throw new Error(`Path traversal detected: directory "${directory}" escapes storage directory`);
    }
    if (!existsSync(baseDir)) return [];
    if (!statSync(baseDir).isDirectory()) {
      throw new Error(`Configured domain path "${directory}" is a file, expected a directory`);
    }

    return readdirSync(baseDir)
      .filter(file => extname(file) === extension && statSync(join(baseDir, file)).isFile())
      .map(file => `${directory}/${file}`);
  }

  /**
   * Check whether a domain file currently exists on disk.
   */
  domainFileExists(filename: string): boolean {
    const filePath = resolve(this.dir, filename);
    const rootDir = resolve(this.dir);
    if (!filePath.startsWith(rootDir + sep) && filePath !== rootDir) {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Sanitize/normalize the directory argument before calling (strip `..`, path separators, or allowlist known domain names).
  2. Pass static, hardcoded subdirectory names for known domains.
  3. If input is user-driven, validate against a allowlist pattern (e.g. /^[a-zA-Z0-9-_]+$/) first.
  4. Check the storage `dir` configuration for unexpected relative-path composition.

Example fix

// before
const files = db.listDomainFiles(userInput); // '../../etc' -> throws

// after
const domain = userInput.replace(/[^a-zA-Z0-9-_]/g, '');
if (!domain) throw new Error('invalid domain directory');
const files = db.listDomainFiles(domain);
Defensive patterns

Strategy: validation

Validate before calling

const path = require('path');
function isSafeDirName(dir) {
  if (typeof dir !== 'string' || dir.length === 0) return false;
  if (path.isAbsolute(dir)) return false;
  const norm = path.normalize(dir);
  return !norm.split(path.sep).includes('..');
}

Try / catch

try {
  const files = db.listDomainFiles(dir);
} catch (e) {
  if (e.message.startsWith('Path traversal detected')) {
    throw new Error(`Rejected unsafe storage directory: ${dir}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling listDomainFiles with a directory containing `..`, an absolute path, or any segment that resolves outside the storage root (`this.dir`).

Common situations: User- or request-supplied directory names passed straight into storage APIs; concatenating untrusted input into paths; misconfigured storage dir interacting with relative paths.

Related errors


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