alibaba/canal · error · IllegalArgumentException
Invalid destination path
Error message
Invalid destination path
What it means
Thrown by FileUtils.validateFileName() as a path-traversal guard. It resolves both baseDir and the combined baseDir+destination to their canonical (absolute, symlink-resolved) paths, then checks that the full path starts with basePath + File.separator. If the destination contains `../` sequences or symlinks that escape the base directory, the check fails and this exception is thrown.
Source
Thrown at common/src/main/java/com/alibaba/otter/canal/common/utils/FileUtils.java:107
return res.toString();
}
/**
* 校验自定义的文件名,是否在允许的基目录范围内,如何合法就返回全路径,否则就直接报错
*
* @param baseDir
* @param destination
* @return
*/
public static String validateFileName(String baseDir, String destination) {
try {
// 验证 destination 是否在允许的基目录范围内
String basePath = new File(baseDir).getCanonicalPath();
String fullPath = new File(basePath, destination).getCanonicalPath();
// 检查 fullPath 是否以 basePath 开头
if (!fullPath.startsWith(basePath + File.separator)) {
throw new IllegalArgumentException("Invalid destination path");
}
return fullPath;
} catch (IOException e) {
throw new RuntimeException("Failed to read file", e);
}
}
public static void main(String[] args) throws IOException {
String fullPath = validateFileName("/tmp/", "1.txt");
System.out.println(fullPath);
System.out.println(org.apache.commons.io.FileUtils.readLines(new File(fullPath)));
fullPath = validateFileName("/tmp/", "test");
fullPath = validateFileName(fullPath,"1.txt");
System.out.println(fullPath);
System.out.println(org.apache.commons.io.FileUtils.readLines(new File(fullPath)));
View on GitHub (pinned to 87be50e876)
Solutions
- Ensure the destination parameter contains no `../` sequences or absolute path prefixes.
- Verify that no symlinks within the base directory tree resolve to locations outside baseDir.
- Pass an absolute, canonical baseDir to avoid ambiguity in path resolution.
- Sanitize user/config-provided path components by rejecting any input containing `..` or starting with `/`.
Example fix
// before — user input used directly as destination
String dest = request.getParam("name"); // could be "../../etc/passwd"
String path = FileUtils.validateFileName(baseDir, dest);
// after — sanitize input
String dest = request.getParam("name");
if (dest.contains("..") || dest.startsWith("/")) {
throw new IllegalArgumentException("Invalid name");
}
String path = FileUtils.validateFileName(baseDir, dest); Defensive patterns
Strategy: validation
Validate before calling
// Sanitize destination before calling validateFileName
if (destination == null || destination.contains("..") || destination.startsWith("/")
|| destination.contains(File.separator + "..")) {
throw new IllegalArgumentException("Invalid destination: path traversal detected");
}
String safePath = FileUtils.validateFileName(baseDir, destination); Type guard
null
Try / catch
try {
String path = FileUtils.validateFileName(baseDir, destination);
} catch (IllegalArgumentException e) {
if ("Invalid destination path".equals(e.getMessage())) {
logger.warn("Rejected path traversal attempt: baseDir={}, dest={}", baseDir, destination);
}
throw e;
} Prevention
- Reject any user/config-supplied path containing `..` or starting with `/`.
- Prefer whitelisting allowed characters in file name components.
- Use absolute baseDir paths to reduce ambiguity.
- Never trust client-supplied paths without canonicalization and containment checks.
When it happens
Trigger: Calling validateFileName(baseDir, destination) where destination resolves outside baseDir — e.g. destination contains `../` that escapes, or a symlink within the path points outside baseDir, or destination is an absolute path pointing elsewhere.
Common situations: User-supplied or config-supplied file paths are used without sanitization; canal destination or instance name contains traversal characters; a symlink in the data directory resolves outside the allowed base; the baseDir itself is relative and resolves unexpectedly.
Related errors
- {} has startup , don't repeat start
- {} isn't start , please check
- Failed to read file
- ERROR # The kafka kerberos configuration file does not exist
- can't encrypt password that will be sent to MySQL server.
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/e93618f671d4d140.
Report an issue: GitHub.