{"record":{"id":"9acf1aa418f6cda9","repo":"FlowiseAI/Flowise","slug":"invalid-or-unsafe-filename-detected","errorCode":null,"errorMessage":"Invalid or unsafe fileName detected","messagePattern":"Invalid or unsafe fileName detected","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/src/storage/BaseStorageProvider.ts","lineNumber":48,"sourceCode":"        chatflowId: string,\n        chatId: string,\n        fileName: string,\n        orgId: string\n    ): Promise<fs.ReadStream | Buffer | undefined>\n    abstract removeFilesFromStorage(...paths: string[]): Promise<StorageSizeResult>\n    abstract removeSpecificFileFromUpload(filePath: string): Promise<void>\n    abstract removeSpecificFileFromStorage(...paths: string[]): Promise<StorageSizeResult>\n    abstract removeFolderFromStorage(...paths: string[]): Promise<StorageSizeResult>\n    abstract getStorageSize(orgId: string): Promise<number>\n    abstract getMulterStorage(): any\n    abstract getLoggerTransports(logType: 'server' | 'error' | 'requests' | 'audit', config?: any): any[]\n\n    /**\n     * Shared utility for sanitizing filenames to prevent path traversal and other issues\n     */\n    protected sanitizeFilename(filename: string): string {\n        if (!filename || isUnsafeFilePath(filename)) {\n            throw new Error('Invalid or unsafe fileName detected')\n        }\n        const sanitizedFilename = sanitize(filename)\n        // Remove leading dots to prevent hidden files or relative path jumps\n        const cleaned = sanitizedFilename.replace(/^\\.+/, '')\n        if (!cleaned || cleaned.includes('/') || cleaned.includes('\\\\')) {\n            throw new Error('Invalid filename after sanitization')\n        }\n        return cleaned\n    }\n\n    /**\n     * Shared utility for getting the base storage path\n     */\n    protected getStoragePath(): string {\n        const storagePath = process.env.BLOB_STORAGE_PATH\n            ? path.join(process.env.BLOB_STORAGE_PATH)\n            : path.join(getUserHome(), '.flowise', 'storage')\n","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/src/storage/BaseStorageProvider.ts#L30-L66","documentation":"First guard in BaseStorageProvider.sanitizeFilename. It rejects a filename that is empty/null or flagged as unsafe by isUnsafeFilePath (path-traversal patterns such as `../`, absolute paths, or null bytes). This is the primary path-traversal defense shared by every storage provider.","triggerScenarios":"Calling a storage method with an empty fileName, a fileName containing `..` segments, a leading `/`, a Windows drive/root, or embedded NUL characters. The guard is `!filename || isUnsafeFilePath(filename)` at BaseStorageProvider.ts:47.","commonSituations":"User-supplied upload filenames that include traversal sequences; a buggy caller passing an undefined/empty name; tampered requests attempting to escape the storage root.","solutions":["Ensure fileName is a non-empty basename with no path separators before calling storage APIs.","Strip or reject `..`, leading slashes, and NUL bytes upstream (e.g. via multer's filename sanitization).","If the name legitimately contains such characters, generate a safe derived name (UUID) instead of passing it through."],"exampleFix":"// before\nawait provider.streamStorageFile(chatflowId, chatId, '../etc/passwd', orgId)\n// after\nconst safeName = path.basename(fileName).replace(/\\.+/g, '')\nawait provider.streamStorageFile(chatflowId, chatId, safeName, orgId)","handlingStrategy":"validation","validationCode":"import path from 'path'\nfunction preSanitizeFilename(filename: string): string {\n  if (!filename || /[\\x00/\\\\]|\\.\\./.test(filename)) {\n    throw new Error('Invalid or unsafe fileName detected')\n  }\n  return path.basename(filename)\n}","typeGuard":"function isSafeFilename(filename: unknown): filename is string {\n  return typeof filename === 'string' && filename.length > 0 && !/[\\x00/\\\\]|\\.\\./.test(filename)\n}","tryCatchPattern":"try {\n  await provider.streamStorageFile(chatflowId, chatId, fileName, orgId)\n} catch (e) {\n  if (/Invalid or unsafe fileName/.test(e.message)) return res.status(400).send('invalid filename')\n  throw e\n}","preventionTips":["Always pass a basename with no separators as fileName.","Reject filenames containing '..', NUL, '/', or '\\\\' at the request boundary.","Generate UUID filenames for untrusted uploads."],"tags":["security","path-traversal","storage","validation"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}