{"record":{"id":"de69679a6e237885","repo":"FlowiseAI/Flowise","slug":"file-type-not-allowed-files-must-have-a-valid-fil","errorCode":null,"errorMessage":"File type not allowed: files must have a valid file extension","messagePattern":"File type not allowed: files must have a valid file extension","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/components/src/validator.ts","lineNumber":153,"sourceCode":" * It ensures that the file extension matches the declared MIME type, preventing\n * attackers from uploading malicious files (e.g., .js file with text/plain MIME type).\n *\n * @param {string} filename The original filename\n * @param {string} mimetype The declared MIME type\n * @returns {void} Throws an error if validation fails\n */\nexport const validateMimeTypeAndExtensionMatch = (filename: string, mimetype: string): void => {\n    validateFilename(filename)\n\n    if (!mimetype || typeof mimetype !== 'string') {\n        throw new Error('Invalid MIME type: MIME type is required and must be a string')\n    }\n\n    const normalizedExt = extractFileExtension(filename)\n\n    if (!normalizedExt) {\n        // Files without extensions are rejected for security\n        throw new Error('File type not allowed: files must have a valid file extension')\n    }\n\n    // Get the expected extension from mapMimeTypeToExt (returns extension without dot)\n    const expectedExt = mapMimeTypeToExt(mimetype)\n\n    if (!expectedExt) {\n        // If mapMimeTypeToExt doesn't recognize the MIME type, it's not supported\n        throw new Error(`MIME type \"${mimetype}\" is not supported or does not have a valid file extension mapping`)\n    }\n\n    // Ensure the file extension matches the expected extension for the MIME type\n    if (normalizedExt !== expectedExt) {\n        throw new Error(\n            `MIME type mismatch: file extension \"${normalizedExt}\" does not match declared MIME type \"${mimetype}\". Expected: ${expectedExt}`\n        )\n    }\n}\n","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/src/validator.ts#L135-L171","documentation":"Thrown by validateMimeTypeAndExtensionMatch when extractFileExtension returns '' — i.e. the filename has no dot or nothing after the last dot. Files without extensions are rejected for security because there is no extension to match against the declared MIME type, defeating the spoofing mitigation (CVE-2025-61687).","triggerScenarios":"Uploader sends filename='receipt' (no extension) or filename='receipt.' (trailing dot, empty final segment); a renamed file stripped of its extension; a generated/temporary filename like 'tmp-12345'.","commonSituations":"Mobile clients that strip extensions; temp file uploads; CSV/JSON content uploaded as extensionless 'data'; legacy systems storing files by ID only.","solutions":["Require clients to include a file extension; reject extensionless uploads with a 400.","If extensionless uploads must be supported, derive the extension from the declared MIME type and append it before storage (and document the security trade-off).","Update the uploader to send the original filename with extension."],"exampleFix":"// before\nif (!normalizedExt) throw new Error('File type not allowed: files must have a valid file extension')\n\n// after — auto-append extension from MIME when policy allows extensionless uploads\nif (!normalizedExt) {\n  const derived = mapMimeTypeToExt(mimetype)\n  if (derived) {\n    filename = `${filename}.${derived}`\n  } else {\n    throw new Error('File type not allowed: files must have a valid file extension')\n  }\n}","handlingStrategy":"validation","validationCode":"function filenameHasExtension(filename: string): boolean {\n  const parts = filename.split('.')\n  return parts.length > 1 && parts[parts.length - 1].length > 0\n}","typeGuard":"function hasFileExtension(filename: string): boolean {\n  const parts = filename.split('.')\n  return parts.length > 1 && parts[parts.length - 1].trim().length > 0\n}","tryCatchPattern":"if (!hasFileExtension(filename)) {\n  throw new Error('File type not allowed: files must have a valid file extension')\n}","preventionTips":["Require clients to send the original filename with extension.","Reject extensionless uploads at the handler boundary with a 400.","If extensionless uploads are required by policy, derive the extension from MIME and append it."],"tags":["validation","file-upload","mime","extension","security"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}