FlowiseAI/Flowise · error · Error

Invalid filename after sanitization

Error message

Invalid filename after sanitization

What it means

Second guard in sanitizeFilename, run after the `sanitize()` library call and after stripping leading dots. It catches filenames that became empty or still contain a path separator after sanitization — i.e. inputs that survived the first check but are still unsafe to use as a single path component.

Source

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

    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')

        if (!fs.existsSync(storagePath)) {
            fs.mkdirSync(storagePath, { recursive: true })
        }
        return storagePath
    }

View on GitHub (pinned to abe4a8601a)

Solutions

  1. Validate that the caller-supplied filename yields a non-empty basename with no separators before invoking storage.
  2. Fall back to a generated safe name (e.g. a UUID) when the sanitized result is empty.
  3. Treat this as an attack signal and log/reject the request upstream.

Example fix

// before
const name = '....'
// after
const name = sanitizeUserFileName(fileName) || crypto.randomUUID()
Defensive patterns

Strategy: validation

Validate before calling

import sanitize from 'sanitize-filename'
function safeFilenameOrUuid(filename: string, fallback: string): string {
  const cleaned = sanitize(filename).replace(/^(\.+)/, '')
  if (!cleaned || cleaned.includes('/') || cleaned.includes('\\')) return fallback
  return cleaned
}

Type guard

function isNonEmptySanitized(name: string): boolean {
  const c = name.replace(/^(\.+)/, '')
  return c.length > 0 && !c.includes('/') && !c.includes('\\')
}

Try / catch

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

Prevention

When it happens

Trigger: A filename composed entirely of dot/special characters that sanitize() reduces to an empty string, or an input whose sanitized form still contains `/` or `\`. The guard is `!cleaned || cleaned.includes('/') || cleaned.includes('\\')` at BaseStorageProvider.ts:53.

Common situations: Filenames like `....`, `...//`, or strings of only forbidden characters; locale/encoding edge cases that defeat the sanitizer.

Related errors


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