{"record":{"id":"625e8eb69661d352","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-file-name","errorCode":"error-invalid-file-name","errorMessage":"error-invalid-file-name","messagePattern":"error-invalid-file-name","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/media/file/functions/sanitizeFileName.ts","lineNumber":7,"sourceCode":"import path from 'node:path';\n\nexport function sanitizeFileName(fileName: string) {\n\tconst base = path.basename(fileName);\n\n\tif (base !== fileName) {\n\t\tthrow new Error('error-invalid-file-name');\n\t}\n\n\tif (base === '.' || base.startsWith('..')) {\n\t\tthrow new Error('error-invalid-file-name');\n\t}\n\n\tif (!/^[a-zA-Z0-9._-]+$/.test(base)) {\n\t\tthrow new Error('error-invalid-characters-in-file-name');\n\t}\n\n\treturn base;\n}\n","sourceCodeStart":1,"sourceCodeEnd":20,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/media/file/functions/sanitizeFileName.ts#L1-L20","documentation":"sanitizeFileName (apps/meteor/server/lib/media/file/functions/sanitizeFileName.ts:5-8) is a path-traversal guard used by the FileSystem store's createWriteStream/createReadStream/stat/unlink (file.server.ts). It rejects any name where path.basename(fileName) !== fileName, i.e. a name containing path separators that could escape the store directory ('../etc/passwd', 'sounds/alert.mp3', '/etc/passwd'). It throws a plain Error, not a Meteor.Error.","triggerScenarios":"Storing or retrieving a FileSystem-store file whose name contains '/' (directory components), e.g. a client or integration passing a full relative path as the file name; traversal attempts like '../../etc/shadow' in the file name field.","commonSituations":"Custom integrations uploading with unsanitized names from external systems (paths included); clients on other OSes sending names like 'C:\\\\uploads\\\\x.png' (backslash survives this check but fails the later regex); migrations importing legacy upload records whose names embed slashes; security scanners probing upload endpoints.","solutions":["Send only the final path component: strip directories before calling the store (path.basename on the caller side)","Rewrite legacy/stored file names that contain separators to their basename before migration or access","Never relax this guard - it is the server's path-traversal defense for the FileSystem store","Wrap store calls in try/catch and surface a validation error to the client instead of crashing"],"exampleFix":"// before\nconst store = FileUpload.getStore('FileSystem');\nconst stream = store.createWriteStream({ name: userSuppliedName, ... }); // '../evil' -> error-invalid-file-name\n\n// after\nconst safeName = path.basename(userSuppliedName).replace(/[^a-zA-Z0-9._-]/g, '_');\nconst stream = store.createWriteStream({ name: safeName, ... });","handlingStrategy":"validation","validationCode":"const isFlatName = (name: string): boolean => path.basename(name) === name;\nif (!isFlatName(name)) throw new Error('File name must not contain path separators');","typeGuard":"const isSafeStoreFileName = (name: string): name is string =>\n  path.basename(name) === name &&\n  name !== '.' &&\n  !name.startsWith('..') &&\n  /^[a-zA-Z0-9._-]+$/.test(name);","tryCatchPattern":"try {\n  const ws = store.createWriteStream({ name, ... });\n} catch (error: any) {\n  if (/error-invalid-file-name|error-invalid-characters-in-file-name/.test(error.message)) {\n    useSanitizedBasename(name); // fall back to basename with cleaned characters\n    return;\n  }\n  throw error;\n}","preventionTips":["Always send path.basename(fileName) from clients","Never build names from external paths verbatim","Keep stored names within [a-zA-Z0-9._-]"],"tags":["file-upload","path-traversal","security","filesystem-store","validation"],"backgroundTag":"path-traversal-blocked","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}