{"record":{"id":"34d89fb48c85e18f","repo":"Dolibarr/dolibarr","slug":"errorfilenameinvalid-original-file","errorCode":null,"errorMessage":"ErrorFileNameInvalid: ${original_file}","messagePattern":"ErrorFileNameInvalid: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"htdocs/document.php","lineNumber":339,"sourceCode":"\t\t\t\tif ($num > 0) {\n\t\t\t\t\t$accessallowed = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Security:\n// Limit access if permissions are wrong\nif (!$accessallowed) {\n\taccessforbidden();\n}\n\n// Security:\n// We refuse directory transversal change and pipes in file names\nif (preg_match('/\\.\\./', $fullpath_original_file) || preg_match('/[<>|]/', $fullpath_original_file)) {\n\tdol_syslog(\"Refused to deliver file \".$fullpath_original_file);\n\tprint \"ErrorFileNameInvalid: \".dol_escape_htmltag($original_file);\n\texit;\n}\n\n\nclearstatcache();\n\n$filename = basename($fullpath_original_file);\n$filename = preg_replace('/\\.noexe$/i', '', $filename);\n\n// Output file on browser\ndol_syslog(\"document.php download $fullpath_original_file filename=$filename content-type=$type\");\n$fullpath_original_file_osencoded = dol_osencode($fullpath_original_file); // New file name encoded in OS encoding charset\n\n// This test if file exists should be useless. We keep it to find bug more easily\nif (!file_exists($fullpath_original_file_osencoded)) {\n\tdol_syslog(\"ErrorFileDoesNotExists: \".$fullpath_original_file);\n\tprint $langs->trans(\"ErrorFileDoesNotExists\") . ' : ' . dol_escape_htmltag($original_file);\n\texit;","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/Dolibarr/dolibarr/blob/598aa4bdada683d17ca04b1842548821ff0eb6c6/htdocs/document.php#L321-L357","documentation":"document.php refuses to deliver a file whose path contains directory-traversal sequences ('..') or pipe/redirection characters ('<', '>','|'). It prints 'ErrorFileNameInvalid' followed by the HTML-escaped requested filename and exits. This is a security guard against path traversal and command-injection-style filenames when serving documents from htdocs/document.php:332-336.","triggerScenarios":"GET/POST to document.php with original_file (or the resolved $fullpath_original_file) containing '..' segments or the characters <, >, or |; e.g. original_file=../../conf/conf.php or a filename containing a pipe character.","commonSituations":"Malformed or hand-crafted download links; applications building original_file by concatenating user input; storage backends (e.g. some external storages) that re-derive relative paths with ../; legacy clients URL-encoding filenames that contain pipes.","solutions":["Fix the caller so original_file is a clean module-relative path (no leading slashes, no '..')","Sanitize the filename server-side before redirecting to document.php (strip '..' and forbidden characters with dol_sanitizeFileName)","If the file legitimately lives outside the module dir, use the ecm/directory hash (hashp) mechanism instead of a relative traversal path","Check for double-encoding: decode the URL once and re-verify the path does not contain '..' after decoding"],"exampleFix":"// before\n$url = DOL_URL_ROOT.'/document.php?modulepart=facture&original_file=../../'.$relative;\n// after\n$clean = str_replace('..', '', dol_sanitizeFileName($relative));\n$url = DOL_URL_ROOT.'/document.php?modulepart=facture&original_file='.urlencode($clean);","handlingStrategy":"validation","validationCode":"if (preg_match('/\\.\\./', $path) || preg_match('/[<>|]/', $path)) { throw new InvalidArgumentException('Invalid file path'); }","typeGuard":"function isSafeRelativePath(string $p): bool { return $p !== '' && strpos($p, '..') === false && !preg_match('/[<>|]/', $p) && strpos($p, \"\\0\") === false; }","tryCatchPattern":null,"preventionTips":["Always build original_file from module-relative paths, never concatenate user input","Run filenames through dol_sanitizeFileName before storing or linking","URL-encode the file parameter exactly once and avoid double decoding","Prefer hashp-based links for files outside the standard module tree"],"tags":["security","path-traversal","file-download","dolibarr"],"backgroundTag":"path-traversal-blocked","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"}