{"record":{"id":"b0f96bbe16c1aeb3","repo":"mastra-ai/mastra","slug":"path-traversal-detected-directory-directory","errorCode":null,"errorMessage":"Path traversal detected: directory \"${directory}\" escapes storage directory","messagePattern":"Path traversal detected: directory \"(.+?)\" escapes storage directory","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/storage/filesystem-db.ts","lineNumber":107,"sourceCode":"      mkdirSync(parentDir, { recursive: true });\n    }\n\n    writeFileSync(tmpPath, JSON.stringify(data, null, 2), 'utf-8');\n    renameSync(tmpPath, filePath);\n  }\n\n  /**\n   * Clear all data from a domain JSON file.\n   */\n  clearDomain(filename: string): void {\n    this.writeDomain(filename, {});\n  }\n\n  listDomainFiles(directory: string, extension = '.json'): string[] {\n    const baseDir = resolve(this.dir, directory);\n    const rootDir = resolve(this.dir);\n    if (!baseDir.startsWith(rootDir + sep) && baseDir !== rootDir) {\n      throw new Error(`Path traversal detected: directory \"${directory}\" escapes storage directory`);\n    }\n    if (!existsSync(baseDir)) return [];\n    if (!statSync(baseDir).isDirectory()) {\n      throw new Error(`Configured domain path \"${directory}\" is a file, expected a directory`);\n    }\n\n    return readdirSync(baseDir)\n      .filter(file => extname(file) === extension && statSync(join(baseDir, file)).isFile())\n      .map(file => `${directory}/${file}`);\n  }\n\n  /**\n   * Check whether a domain file currently exists on disk.\n   */\n  domainFileExists(filename: string): boolean {\n    const filePath = resolve(this.dir, filename);\n    const rootDir = resolve(this.dir);\n    if (!filePath.startsWith(rootDir + sep) && filePath !== rootDir) {","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/storage/filesystem-db.ts#L89-L125","documentation":"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.","triggerScenarios":"Calling listDomainFiles with a directory containing `..`, an absolute path, or any segment that resolves outside the storage root (`this.dir`).","commonSituations":"User- or request-supplied directory names passed straight into storage APIs; concatenating untrusted input into paths; misconfigured storage dir interacting with relative paths.","solutions":["Sanitize/normalize the directory argument before calling (strip `..`, path separators, or allowlist known domain names).","Pass static, hardcoded subdirectory names for known domains.","If input is user-driven, validate against a allowlist pattern (e.g. /^[a-zA-Z0-9-_]+$/) first.","Check the storage `dir` configuration for unexpected relative-path composition."],"exampleFix":"// before\nconst files = db.listDomainFiles(userInput); // '../../etc' -> throws\n\n// after\nconst domain = userInput.replace(/[^a-zA-Z0-9-_]/g, '');\nif (!domain) throw new Error('invalid domain directory');\nconst files = db.listDomainFiles(domain);","handlingStrategy":"validation","validationCode":"const path = require('path');\nfunction isSafeDirName(dir) {\n  if (typeof dir !== 'string' || dir.length === 0) return false;\n  if (path.isAbsolute(dir)) return false;\n  const norm = path.normalize(dir);\n  return !norm.split(path.sep).includes('..');\n}","typeGuard":null,"tryCatchPattern":"try {\n  const files = db.listDomainFiles(dir);\n} catch (e) {\n  if (e.message.startsWith('Path traversal detected')) {\n    throw new Error(`Rejected unsafe storage directory: ${dir}`);\n  }\n  throw e;\n}","preventionTips":["Never pass user-supplied strings directly as domain directories.","Allowlist known domain directory names.","Normalize paths before passing them to storage APIs.","Sanitize IDs used to build directory names."],"tags":["security","path-traversal","filesystem"],"backgroundTag":"path-traversal-detected","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}