jeecgboot/JeecgBoot · error · JeecgBootException

非法业务路径,禁止访问上传目录之外的路径: ${bizPath}

Error message

非法业务路径,禁止访问上传目录之外的路径: ${bizPath}

What it means

A CWE-22 path-traversal guard inside uploadLocal: both the configured upload root (uploadpath) and the target folder (uploadpath/bizPath) are canonicalized via getCanonicalFile(), and if the target path does not start with the upload root, the request is rejected. This catches ../ escapes, absolute-path tricks, and symlinked targets that resolve outside the upload directory.

Source

Thrown at jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysCommentServiceImpl.java:361

     * @return
     */
    private String uploadLocal(MultipartFile mf, String bizPath) {
        try {
            // 文件安全校验,防止上传漏洞文件
            SsrfFileTypeFilter.checkUploadFileType(mf, bizPath);
        } catch (Exception e) {
            throw new JeecgBootException(e);
        }
        
        try {
            String ctxPath = uploadpath;
            String fileName = null;
            //update-begin---author:liusq ---date:2026-03-30  for:【issues/9427】修复uploadLocal bizPath路径遍历漏洞(CWE-22)-----------
            // 路径遍历校验:规范化后确保目标目录在uploadpath内
            File uploadDir = new File(ctxPath).getCanonicalFile();
            File file = new File(ctxPath + File.separator + bizPath + File.separator).getCanonicalFile();
            if (!file.toPath().startsWith(uploadDir.toPath())) {
                throw new JeecgBootException("非法业务路径,禁止访问上传目录之外的路径: " + bizPath);
            }
            //update-end---author:liusq ---date:2026-03-30  for:【issues/9427】修复uploadLocal bizPath路径遍历漏洞(CWE-22)-----------
            if (!file.exists()) {
                file.mkdirs();// 创建文件根目录
            }
            String orgName = mf.getOriginalFilename();// 获取文件名
            orgName = CommonUtils.getFileName(orgName);
            if (orgName.indexOf(".") != -1) {
                fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.indexOf("."));
            } else {
                fileName = orgName + "_" + System.currentTimeMillis();
            }
            String savePath = file.getPath() + File.separator + fileName;
            File savefile = new File(savePath);
            FileCopyUtils.copy(mf.getBytes(), savefile);
            String dbpath = null;
            if (oConvertUtils.isNotEmpty(bizPath)) {
                dbpath = bizPath + File.separator + fileName;

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. Ensure bizPath is a simple relative subfolder (e.g. 'temp', 'avatar', 'dict').
  2. Strip any '../', leading '/', and backslashes before calling uploadLocal.
  3. Never pass raw user input as bizPath; resolve it from a server-side allowlist.

Example fix

// before
String bizPath = request.getParameter("biz"); // attacker: ../../etc
savePath = uploadLocal(file, bizPath); // throws 非法业务路径...
// after
String bizPath = ALLOWED_BIZ.getOrDefault(request.getParameter("biz"), "upload");
// ALLOWED_BIZ is a fixed map of safe folder names
savePath = uploadLocal(file, bizPath);
Defensive patterns

Strategy: validation

Validate before calling

// Normalize bizPath and confirm it stays within uploadpath BEFORE writing.
File root = new File(uploadpath).getCanonicalFile();
File target = new File(uploadpath + File.separator + bizPath).getCanonicalFile();
if (!target.toPath().startsWith(root.toPath())) {
    throw new IllegalArgumentException("非法业务路径: " + bizPath);
}

Type guard

public boolean isBizPathSafe(String bizPath, String uploadpath) {
    try {
        File root = new File(uploadpath).getCanonicalFile();
        File target = new File(uploadpath + File.separator + bizPath + File.separator).getCanonicalFile();
        return target.toPath().startsWith(root.toPath());
    } catch (IOException e) { return false; }
}

Try / catch

try {
    return uploadLocal(file, bizPath);
} catch (JeecgBootException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("非法业务路径")) {
        log.warn("路径遍历拦截: bizPath={}", bizPath);
        return Result.error("非法的存储路径");
    }
    throw e;
}

Prevention

When it happens

Trigger: bizPath like '../../etc', '/etc', '..\\..\\windows'; absolute paths; symlinked folders resolving outside uploadpath; bizPath crafted to escape via OS-specific separators.

Common situations: Client-supplied bizPath not sanitized; legacy callers passing user-controlled paths directly; OS differences in canonicalization; misconfigured uploadpath differing between nodes.

Related errors


AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14). Data as JSON: /api/errors/e6e744201234f086. Report an issue: GitHub.