{"record":{"id":"5e8f01b55b18b354","repo":"lingochamp/FileDownloader","slug":"the-filename-s-from-the-response-is-not-allowab","errorCode":null,"errorMessage":"The filename [%s] from the response is not allowable, because it contains '../', which can raise the directory traversal vulnerability","messagePattern":"The filename \\[(.+?)\\] from the response is not allowable, because it contains '\\.\\./', which can raise the directory traversal vulnerability","errorType":"validation","errorClass":"FileDownloadSecurityException","httpStatus":null,"severity":"critical","filePath":"library/src/main/java/com/liulishuo/filedownloader/util/FileDownloadUtils.java","lineNumber":671,"sourceCode":"            FileDownloadLog.e(FileDownloadUtils.class, e, \"parse content length\"\n                    + \" from content range error\");\n        }\n        return -1;\n    }\n\n    public static String findFilename(FileDownloadConnection connection, String url)\n            throws FileDownloadSecurityException {\n        String filename = FileDownloadUtils.parseContentDisposition(connection.\n                getResponseHeaderField(\"Content-Disposition\"));\n\n        if (TextUtils.isEmpty(filename)) {\n            filename = findFileNameFromUrl(url);\n        }\n\n        if (TextUtils.isEmpty(filename)) {\n            filename = FileDownloadUtils.generateFileName(url);\n        } else if (filename.contains(\"../\")) {\n            throw new FileDownloadSecurityException(FileDownloadUtils.formatString(\n                    \"The filename [%s] from the response is not allowable, because it contains \"\n                            + \"'../', which can raise the directory traversal vulnerability\",\n                    filename));\n        }\n\n        return filename;\n    }\n\n    public static FileDownloadOutputStream createOutputStream(final String path)\n            throws IOException {\n\n        if (TextUtils.isEmpty(path)) {\n            throw new RuntimeException(\"found invalid internal destination path, empty\");\n        }\n\n        //noinspection ConstantConditions\n        if (!FileDownloadUtils.isFilenameValid(path)) {\n            throw new RuntimeException(","sourceCodeStart":653,"sourceCodeEnd":689,"githubUrl":"https://github.com/lingochamp/FileDownloader/blob/6237a8cac174bcc916e4342b14ab1ab72a5768d4/library/src/main/java/com/liulishuo/filedownloader/util/FileDownloadUtils.java#L653-L689","documentation":"findFilename derives the target filename from the response's Content-Disposition header, the URL, or a generated hash. If a server-supplied filename contains '../', using it would let the download escape its intended directory (directory traversal), so the library throws FileDownloadSecurityException to block the attack.","triggerScenarios":"A download response's Content-Disposition filename (or URL-derived filename) contains the substring '../', e.g. 'Content-Disposition: attachment; filename=\"../../data/file\"'.","commonSituations":"Downloading from untrusted or compromised servers; malicious CDN/proxy injecting hostile filenames; security testing against apps using FileDownloader with server-driven filenames.","solutions":["Do not rely on server filenames: set an explicit safe path via task.setPath(...) so the response filename is ignored.","Sanitize/validate the server-provided filename before initiating the download, rejecting any name containing path separators or '..'.","Only download from trusted servers; treat this exception as evidence the remote is hostile and block it.","If you need the server filename, strip directory components yourself (e.g. use only the substring after the last '/')."],"exampleFix":"// before\nrequest.setPath(dir + File.separator + responseFilename); // responseFilename = \"../../evil\"\n\n// after\nString safe = new File(responseFilename).getName();\nif (safe.contains(\"..\") || safe.contains(\"/\")) {\n    safe = FileDownloadUtils.generateFileName(url);\n}\nrequest.setPath(dir + File.separator + safe);","handlingStrategy":"validation","validationCode":"String name = headerFilename; // from Content-Disposition\nif (name != null && (name.contains(\"../\") || name.contains(\"/\") || name.contains(\"\\\\\"))) {\n    name = FileDownloadUtils.generateFileName(url); // reject hostile name\n}","typeGuard":"boolean isSafeFilename(String f) {\n    return f != null && !f.isEmpty() && !f.contains(\"../\") && !f.contains(\"/\") && !f.contains(\"\\\\\")\n        && !\"..\".equals(f);\n}","tryCatchPattern":"try {\n    downloader.create(url).setPath(safePath).start();\n} catch (FileDownloadSecurityException e) {\n    // server supplied a traversal filename: block host and alert\n    blockHost(url);\n}","preventionTips":["Always set an explicit local path so server filenames are never used directly.","Treat this exception as a signal the remote server is hostile; log and block it.","Sanitize any header-derived name to its basename before use."],"tags":["android","security","path-traversal","http","filedownloader"],"backgroundTag":"path-traversal-blocked","analyzedSha":"6237a8cac174bcc916e4342b14ab1ab72a5768d4","analyzedAt":"2026-09-08T23:50:48.168Z","contentChangedAt":"2026-09-08T23:50:48.168Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}