FlowiseAI/Flowise · error · Error

Invalid or unsafe fileName detected

Error message

Invalid or unsafe fileName detected

What it means

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.

Source

Thrown at packages/components/src/storage/BaseStorageProvider.ts:48

        chatflowId: string,
        chatId: string,
        fileName: string,
        orgId: string
    ): Promise<fs.ReadStream | Buffer | undefined>
    abstract removeFilesFromStorage(...paths: string[]): Promise<StorageSizeResult>
    abstract removeSpecificFileFromUpload(filePath: string): Promise<void>
    abstract removeSpecificFileFromStorage(...paths: string[]): Promise<StorageSizeResult>
    abstract removeFolderFromStorage(...paths: string[]): Promise<StorageSizeResult>
    abstract getStorageSize(orgId: string): Promise<number>
    abstract getMulterStorage(): any
    abstract getLoggerTransports(logType: 'server' | 'error' | 'requests' | 'audit', config?: any): any[]

    /**
     * Shared utility for sanitizing filenames to prevent path traversal and other issues
     */
    protected sanitizeFilename(filename: string): string {
        if (!filename || isUnsafeFilePath(filename)) {
            throw new Error('Invalid or unsafe fileName detected')
        }
        const sanitizedFilename = sanitize(filename)
        // Remove leading dots to prevent hidden files or relative path jumps
        const cleaned = sanitizedFilename.replace(/^\.+/, '')
        if (!cleaned || cleaned.includes('/') || cleaned.includes('\\')) {
            throw new Error('Invalid filename after sanitization')
        }
        return cleaned
    }

    /**
     * Shared utility for getting the base storage path
     */
    protected getStoragePath(): string {
        const storagePath = process.env.BLOB_STORAGE_PATH
            ? path.join(process.env.BLOB_STORAGE_PATH)
            : path.join(getUserHome(), '.flowise', 'storage')

View on GitHub (pinned to abe4a8601a)

Solutions

  1. Ensure fileName is a non-empty basename with no path separators before calling storage APIs.
  2. Strip or reject `..`, leading slashes, and NUL bytes upstream (e.g. via multer's filename sanitization).
  3. If the name legitimately contains such characters, generate a safe derived name (UUID) instead of passing it through.

Example fix

// before
await provider.streamStorageFile(chatflowId, chatId, '../etc/passwd', orgId)
// after
const safeName = path.basename(fileName).replace(/\.+/g, '')
await provider.streamStorageFile(chatflowId, chatId, safeName, orgId)
Defensive patterns

Strategy: validation

Validate before calling

import path from 'path'
function preSanitizeFilename(filename: string): string {
  if (!filename || /[\x00/\\]|\.\./.test(filename)) {
    throw new Error('Invalid or unsafe fileName detected')
  }
  return path.basename(filename)
}

Type guard

function isSafeFilename(filename: unknown): filename is string {
  return typeof filename === 'string' && filename.length > 0 && !/[\x00/\\]|\.\./.test(filename)
}

Try / catch

try {
  await provider.streamStorageFile(chatflowId, chatId, fileName, orgId)
} catch (e) {
  if (/Invalid or unsafe fileName/.test(e.message)) return res.status(400).send('invalid filename')
  throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: User-supplied upload filenames that include traversal sequences; a buggy caller passing an undefined/empty name; tampered requests attempting to escape the storage root.

Related errors


AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12). Data as JSON: /api/errors/9acf1aa418f6cda9. Report an issue: GitHub.