jeecgboot/JeecgBoot · error · JeecgBootException
非法存储路径,路径包含遍历字符: {storePath}
Error message
非法存储路径,路径包含遍历字符: {storePath} What it means
Thrown by FileDownloadUtils.download2DiskFromNet when the computed canonical path of storePath does not equal its absolute path. This is a CWE-22 path-traversal guard added for issue 9437: it runs after SsrfFileTypeFilter.checkPathTraversal and confirms the path contains no '../' traversal or symlink resolution that escapes the intended directory. The JeecgBootException signals the caller passed an unsafe storage path.
Source
Thrown at jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/FileDownloadUtils.java:141
}
/**
* 下载网络资源到磁盘
*
* @param fileUrl
* @param storePath
* @author chenrui
* @date 2024/1/19 10:09
*/
public static String download2DiskFromNet(String fileUrl, String storePath) {
//update-begin---author:liusq ---date:2026-03-30 for:【issues/9437】修复download2DiskFromNet storePath路径遍历漏洞(CWE-22)-----------
// 路径遍历校验:拦截 ../ 等遍历字符,并确保规范化路径与原始路径一致
SsrfFileTypeFilter.checkPathTraversal(storePath);
try {
String canonicalPath = new File(storePath).getCanonicalPath();
String absolutePath = new File(storePath).getAbsolutePath();
if (!canonicalPath.equals(absolutePath)) {
throw new JeecgBootException("非法存储路径,路径包含遍历字符: " + storePath);
}
} catch (IOException e) {
throw new JeecgBootException("存储路径校验失败: " + storePath, e);
}
//update-end---author:liusq ---date:2026-03-30 for:【issues/9437】修复download2DiskFromNet storePath路径遍历漏洞(CWE-22)-----------
//update-begin---author:zhangdaihao ---date:2026-04-15 for:【issues/9553】下载网络资源前增加SSRF校验-----------
SsrfFileTypeFilter.checkSsrfHttpUrl(fileUrl);
//update-end---author:zhangdaihao ---date:2026-04-15 for:【issues/9553】下载网络资源前增加SSRF校验-----------
try {
URL url = new URL(fileUrl);
URLConnection conn = url.openConnection();
// 设置超时间为3秒
conn.setConnectTimeout(3 * 1000);
// 防止屏蔽程序
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
// 确保目录存在
File file = ensureDestFileDir(storePath);
try (InputStream inStream = conn.getInputStream();View on GitHub (pinned to 96fb33f5ec)
Solutions
- Pass a clean, pre-normalized absolute path as storePath — compute it with Paths.get(baseDir, fileName).normalize().toAbsolutePath() and confirm it startsWith(baseDir) before calling download2DiskFromNet.
- Strip any '../' or '.\' sequences from the storePath and re-derive it from a trusted base directory constant.
- If the mismatch is caused by a symlinked storage volume, point the storage config at the real (canonical) path so absolute == canonical.
- At the calling controller, validate the storePath/fileName with a whitelist regex (e.g. no path separators in the filename portion) before it reaches this method.
Example fix
// before
String storePath = uploadDir + "/" + request.getParameter("fileName");
FileDownloadUtils.download2DiskFromNet(fileUrl, storePath);
// after
Path base = Paths.get(uploadDir).toAbsolutePath().normalize();
Path resolved = base.resolve(request.getParameter("fileName")).normalize();
if (!resolved.startsWith(base)) {
throw new IllegalArgumentException("Invalid file path");
}
FileDownloadUtils.download2DiskFromNet(fileUrl, resolved.toString()); Defensive patterns
Strategy: validation
Validate before calling
Path base = Paths.get(uploadDir).toAbsolutePath().normalize();
Path resolved = base.resolve(fileName).normalize();
if (!resolved.startsWith(base)) {
throw new IllegalArgumentException("storePath escapes base directory: " + resolved);
}
FileDownloadUtils.download2DiskFromNet(fileUrl, resolved.toString()); Type guard
null
Try / catch
try {
FileDownloadUtils.download2DiskFromNet(fileUrl, resolved.toString());
} catch (JeecgBootException e) {
log.warn("下载失败,路径校验未通过: {}", e.getMessage());
return Result.error("文件路径不合法");
} Prevention
- Never build storePath by concatenating raw request parameters onto a base directory.
- Always normalize and confine paths under a known base directory before file operations.
- Configure storage directories as absolute paths to avoid symlink/canonical divergence.
When it happens
Trigger: Calling FileDownloadUtils.download2DiskFromNet(fileUrl, storePath) where storePath contains '../', '.' segments, or resolves through symlinks so that new File(storePath).getCanonicalPath() differs from getAbsolutePath(). Any storePath sourced from user input or request parameters without sanitization.
Common situations: Upload/download directory configured with a relative path containing '..'; storage base directory is a symlink; storePath is built by concatenating untrusted user input (filename from upload) onto a base dir without normalization; path constructed on Windows with case differences that make canonical != absolute.
Related errors
- 文件路径包含非法字符
- Illegal access to path outside of base directory.
- 非法业务路径,禁止访问上传目录之外的路径: ${bizPath}
- 存储路径校验失败: {storePath}
- 上传业务路径包含非法字符!
AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14).
Data as JSON: /api/errors/20fd85ef03f16905.
Report an issue: GitHub.