{"record":{"id":"c6540fa8e75c4b3f","repo":"gitroomhq/postiz-app","slug":"unsupported-file-type-c6540f","errorCode":null,"errorMessage":"Unsupported file type.","messagePattern":"Unsupported file type\\.","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"libraries/nestjs-libraries/src/upload/custom.upload.validation.ts","lineNumber":38,"sourceCode":"@Injectable()\nexport class CustomFileValidationPipe implements PipeTransform {\n  async transform(value: any) {\n    if (!value || typeof value !== 'object') {\n      return value;\n    }\n\n    // Skip non-file parameters (org, body, query, etc.)\n    if (!('buffer' in value) && !('mimetype' in value) && !('fieldname' in value)) {\n      return value;\n    }\n\n    if (!value.buffer || !Buffer.isBuffer(value.buffer)) {\n      throw new BadRequestException('Invalid file upload.');\n    }\n\n    const detected = await fileTypeFromBuffer(value.buffer);\n    if (!detected || !ALLOWED_MIME_TYPES.has(detected.mime)) {\n      throw new BadRequestException('Unsupported file type.');\n    }\n\n    const maxSize = getMaxSize(detected.mime);\n    if (value.size > maxSize) {\n      throw new BadRequestException(\n        `File size exceeds the maximum allowed size of ${maxSize} bytes.`\n      );\n    }\n\n    value.mimetype = detected.mime;\n    const safeBase = (value.originalname || 'upload')\n      .replace(/\\.[^./\\\\]*$/, '')\n      .replace(/[\\\\/]/g, '_')\n      .slice(0, 100) || 'upload';\n    value.originalname = `${safeBase}.${detected.ext}`;\n\n    return value;\n  }","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/gitroomhq/postiz-app/blob/0f1647f7491a217d43eb5ae7a480484bdf0aff3e/libraries/nestjs-libraries/src/upload/custom.upload.validation.ts#L20-L56","documentation":"The upload validation pipe sniffs the real content type from the bytes via fileTypeFromBuffer and rejects anything whose detected MIME is not in ALLOWED_MIME_TYPES. Client-declared mimetype and file extension are ignored, so renaming a file or spoofing the Content-Type header will not bypass it.","triggerScenarios":"Uploading a file whose magic bytes don't match a known signature (text files, SVGs, HEIC, docs, executables), an empty/truncated buffer, or a supported extension whose actual content is different (e.g. an .exe renamed to .png).","commonSituations":"SVG logo uploads (SVG has no magic-byte signature file-type recognizes in many versions); HEIC photos from iPhones; uploading PDFs or zip archives where only images/video are allowed; corrupted files from a failed download.","solutions":["Verify the real content with `file` command or a hex dump of the first bytes","Convert the file to an allowed format (png/jpeg/webp/gif or allowed video) before upload","If the format should be supported, add it to ALLOWED_MIME_TYPES in custom.upload.validation.ts and redeploy","For SVG, consider sanitizing then serving with a safe Content-Type rather than allowing raw upload"],"exampleFix":"// before\nform.append('file', new File([svgText], 'logo.svg', { type: 'image/svg+xml' })); // rejected\n\n// after: rasterize to png first\nconst png = await rasterizeSvg(svgText);\nform.append('file', new File([png], 'logo.png', { type: 'image/png' }));","handlingStrategy":"validation","validationCode":"import { fileTypeFromBuffer } from 'file-type';\nasync function assertAllowed(buffer: Buffer, allow: Set<string>) {\n  const t = await fileTypeFromBuffer(buffer);\n  if (!t || !allow.has(t.mime)) throw new Error(`Rejecting ${t?.mime ?? 'unknown'} file`);\n}","typeGuard":"const isSupportedUpload = async (b: Buffer) => { const t = await fileTypeFromBuffer(b); return !!t && ALLOWED_MIME_TYPES.has(t.mime); };","tryCatchPattern":"try { await api.upload(form); } catch (e) { if (/Unsupported file type/.test(String(e))) notify('Convert to PNG/JPEG/GIF/WebP or MP4 and retry'); else throw e; }","preventionTips":["Convert exotic formats (SVG, HEIC) before upload","Never trust extension or client Content-Type","Maintain one shared allow-list across upload paths"],"tags":["upload","validation","file-type","mime-sniffing"],"backgroundTag":"unsupported-file-type","analyzedSha":"0f1647f7491a217d43eb5ae7a480484bdf0aff3e","analyzedAt":"2026-08-27T12:09:55.020Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}