{"record":{"id":"6af12f9d1e33dc21","repo":"FlowiseAI/Flowise","slug":"invalid-file-name-name-is-required","errorCode":null,"errorMessage":"Invalid file name: name is required","messagePattern":"Invalid file name: name is required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/src/validator.ts","lineNumber":410,"sourceCode":"    if (!/^(SELECT|WITH)\\b/i.test(trimmed)) {\n        throw new Error('Invalid SQL statement: only read-only SELECT/WITH statements are allowed')\n    }\n\n    if (/load_extension\\s*\\(/i.test(trimmed)) {\n        throw new Error('Invalid SQL statement: load_extension is not allowed')\n    }\n}\n\n/**\n * Sanitize a file name to prevent path traversal attacks.\n * Strips common storage prefixes, extracts the basename, runs it through\n * the `sanitize-filename` package, and rejects anything that still looks unsafe.\n *\n * @param {string} name The file name to sanitize\n */\nexport const sanitizeFileName = (name: string): string => {\n    if (!name || typeof name !== 'string') {\n        throw new Error('Invalid file name: name is required')\n    }\n    // Strip the FILE-STORAGE:: prefix if present\n    let stripped = name.replace(/^FILE-STORAGE::/, '')\n    // Decode percent-encoded traversal sequences before basename extraction\n    try {\n        stripped = decodeURIComponent(stripped)\n    } catch (_) {\n        // If decoding fails the raw string is fine — basename will still strip dirs\n    }\n    // Normalize backslashes to forward slashes so path.basename works on all\n    // platforms (on Linux, path.basename does not treat \\ as a separator)\n    stripped = stripped.replace(/\\\\/g, '/')\n    // Extract only the base filename — removes all directory components\n    let baseName = path.basename(stripped)\n    // Run through sanitize-filename to strip OS-reserved chars, control chars, etc.\n    baseName = sanitize(baseName)\n    // Remove leading dots to prevent hidden files or relative path references\n    baseName = baseName.replace(/^\\.+/, '')","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/src/validator.ts#L392-L428","documentation":"Thrown by sanitizeFileName() in the Flowise validator when the `name` argument is missing (undefined/null/empty) or not a string. sanitizeFileName is the security gate that strips path-traversal payloads from untrusted file names before they reach storage, so it refuses to operate on input it cannot safely reason about. The guard runs before any prefix-stripping, decoding, or basename extraction, meaning no normalization occurs until the argument passes a type+truthiness check.","triggerScenarios":"Calling sanitizeFileName(undefined), sanitizeFileName(null), sanitizeFileName(''), sanitizeFileName(123), or sanitizeFileName(<an object>) directly. Also reached indirectly when a storage provider or upload handler forwards a missing req.file.originalname / form field value into this function without first checking it.","commonSituations":"An upload endpoint where the client omitted the filename field; a storage provider that reads a key from a payload whose schema changed; a migration that introduced sanitizeFileName into a code path that previously tolerated undefined names; test fixtures that call the function with no argument.","solutions":["Ensure the caller passes a non-empty string: validate filename presence at the request boundary (e.g. in the multer field config or controller) before forwarding to sanitizeFileName.","Default to a generated safe name when the upstream source has none, e.g. `name = name || crypto.randomUUID()`.","If the value is genuinely optional, branch around the call instead of letting it reach the guard.","Add a TypeScript type annotation or runtime check so non-string values are caught at the caller, not inside the sanitizer."],"exampleFix":"// before\nconst safe = sanitizeFileName(req.body.fileName) // req.body.fileName may be undefined\n\n// after\nif (!req.body.fileName || typeof req.body.fileName !== 'string') {\n    return res.status(400).json({ message: 'fileName is required' })\n}\nconst safe = sanitizeFileName(req.body.fileName)","handlingStrategy":"validation","validationCode":"if (!name || typeof name !== 'string' || name.length === 0) {\n    return res.status(400).json({ message: 'A non-empty file name is required' })\n}\nconst safe = sanitizeFileName(name)","typeGuard":"const isNonEmptyString = (v: unknown): v is string =>\n    typeof v === 'string' && v.length > 0","tryCatchPattern":"try {\n    const safe = sanitizeFileName(name)\n} catch (e) {\n    // name was missing/non-string — reject the request, do not retry with the same input\n    return res.status(400).json({ message: (e as Error).message })\n}","preventionTips":["Validate filename presence at the request boundary before forwarding to storage logic.","Type the upstream source (req.body.fileName: string) so undefined is a compile-time catch.","Never pass req.file?.originalname directly without a null/type check."],"tags":["validation","typescript","filename","security","input-validation"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}