{"record":{"id":"fd711b7bb4ca52b7","repo":"Dolibarr/dolibarr","slug":"this-file-extension-is-not-qualified-for-preview","errorCode":null,"errorMessage":"This file extension is not qualified for preview","messagePattern":"This file extension is not qualified for preview","errorType":"http","errorClass":null,"httpStatus":403,"severity":"error","filePath":"htdocs/viewimage.php","lineNumber":280,"sourceCode":"if (preg_match('/\\.noexe$/i', $original_file)) {\n\thttponly_accessforbidden('Error: Using the image wrapper to output a file ending with .noexe is not allowed.');\n}\n\n// Security: Delete string ../ or ..\\ into $original_file\n$original_file = preg_replace('/\\.\\.+/', '..', $original_file);\t// Replace '... or more' with '..'\n$original_file = str_replace('../', '/', $original_file);\n$original_file = str_replace('..\\\\', '/', $original_file);\n\n// Find the subdirectory name as the reference\n$refname = basename(dirname($original_file).\"/\");\nif ($refname == 'thumbs') {\n\t// If we get the thumbs directory, we must go one step higher. For example original_file='10/thumbs/myfile_small.jpg' -> refname='10'\n\t$refname = basename(dirname(dirname($original_file)).\"/\");\n}\n\n// Check that file is allowed for view with viewimage.php\nif (!empty($original_file) && !dolIsAllowedForPreview($original_file)) {\n\thttponly_accessforbidden('This file extension is not qualified for preview', 403);\n}\n\n// Security check\nif (empty($modulepart)) {\n\thttponly_accessforbidden('Bad value for parameter modulepart', 400);\n}\n\n// When logged in a different entity, medias cannot be accessed because $conf->$module->multidir_output\n// is not set on the requested entity, but they are public documents, so reset entity\nif ($modulepart === 'medias' && $entity != $conf->entity) {\n\t$conf->entity = $entity;\n\t$conf->setValues($db);\n}\n\n$check_access = dol_check_secure_access_document($modulepart, $original_file, $entity, $user, $refname);\n$accessallowed              = $check_access['accessallowed'];\n$sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals'];\n$fullpath_original_file     = $check_access['original_file']; // $fullpath_original_file is now a full path name","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/Dolibarr/dolibarr/blob/598aa4bdada683d17ca04b1842548821ff0eb6c6/htdocs/viewimage.php#L262-L298","documentation":"The wrapper rejects any requested file whose name ends with .noexe. .noexe is a Dolibarr convention for files that must never be executed or rendered (e.g. renamed executables stored in the documents tree), so serving one via viewimage.php is blocked regardless of its apparent MIME type.","triggerScenarios":"Thrown at htdocs/viewimage.php:280 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Do not request .noexe files through viewimage.php; strip or rename the extension only after verifying content safety","Serve the file through the intended download endpoint if it is meant to be downloaded, not previewed","Remove the .noexe suffix server-side once the file has been verified safe","Fix the calling code or URL that points the image wrapper at a .noexe file"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"598aa4bdada683d17ca04b1842548821ff0eb6c6","analyzedAt":"2026-09-14T11:12:15.309Z","contentChangedAt":"2026-09-14T11:12:15.309Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}