{"record":{"id":"5fd4b0f36043801c","repo":"mastra-ai/mastra","slug":"path-traversal-detected-file-filename-escape","errorCode":null,"errorMessage":"Path traversal detected: file \"${filename}\" escapes storage directory","messagePattern":"Path traversal detected: file \"(.+?)\" escapes storage directory","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/storage/filesystem-db.ts","lineNumber":126,"sourceCode":"    }\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) {\n      throw new Error(`Path traversal detected: file \"${filename}\" escapes storage directory`);\n    }\n    return existsSync(filePath);\n  }\n\n  removeDomainFile(filename: string): void {\n    this.cache.delete(filename);\n    const filePath = resolve(this.dir, filename);\n    const rootDir = resolve(this.dir);\n    if (!filePath.startsWith(rootDir + sep) && filePath !== rootDir) {\n      throw new Error(`Path traversal detected: file \"${filename}\" escapes storage directory`);\n    }\n    if (existsSync(filePath)) {\n      rmSync(filePath);\n    }\n  }\n\n  /**\n   * Invalidate the in-memory cache for a domain, forcing a re-read from disk on next access.","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/storage/filesystem-db.ts#L108-L144","documentation":"domainFileExists() resolves the given filename against the storage root and throws if the resolved path escapes that root. It prevents probing for files outside the storage directory via traversal sequences.","triggerScenarios":"Calling domainFileExists (directly or via sharedFileExists) with a filename containing `..`, an absolute path, or otherwise resolving outside `this.dir`.","commonSituations":"Passing untrusted/user-supplied filenames or keys into existence checks; building filenames by concatenating external IDs without sanitization.","solutions":["Sanitize the filename before calling (strip path separators and `..`; derive from a allowlisted ID).","Use library APIs that generate filenames internally (e.g. per-entity helpers) rather than hand-built strings.","Validate IDs used in filenames against a strict pattern before composing paths.","Log the offending filename to identify which caller is passing unsafe values."],"exampleFix":"// before\nconst exists = db.domainFileExists(`../../${id}.json`); // throws\n\n// after\nconst safeName = `${String(id).replace(/[^a-zA-Z0-9-_]/g, '')}.json`;\nconst exists = db.domainFileExists(safeName);","handlingStrategy":"validation","validationCode":"const path = require('path');\nfunction isSafeFileName(name) {\n  if (typeof name !== 'string' || name.length === 0) return false;\n  if (path.isAbsolute(name)) return false;\n  const norm = path.normalize(name);\n  return !norm.split(path.sep).includes('..') && !norm.includes('/') && !norm.includes('\\\\');\n}","typeGuard":null,"tryCatchPattern":"try {\n  return db.domainFileExists(name);\n} catch (e) {\n  if (e.message.startsWith('Path traversal detected')) {\n    return false; // treat unsafe names as nonexistent, and log\n  }\n  throw e;\n}","preventionTips":["Sanitize or encode entity IDs before embedding them in filenames.","Derive filenames from library helpers rather than string concatenation.","Reject IDs containing slashes or `..` at ingestion time.","Log rejected filenames to find the caller passing unsafe input."],"tags":["security","path-traversal","filesystem"],"backgroundTag":"path-traversal-detected","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}