{"record":{"id":"6a2709b170c5ee4f","repo":"jeecgboot/JeecgBoot","slug":"error-6a2709","errorCode":null,"errorMessage":"上传业务路径深度超出限制！","messagePattern":"上传业务路径深度超出限制！","errorType":"validation","errorClass":"JeecgBootException","httpStatus":null,"severity":"error","filePath":"jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/filter/SsrfFileTypeFilter.java","lineNumber":284,"sourceCode":"     * 路径安全校验\n     */\n    private static void validatePathSecurity(String customPath) throws JeecgBootException {\n        if (customPath == null || customPath.trim().isEmpty()) {\n            return;\n        }\n\n        // 统一分隔符为 /\n        String normalized = customPath.replace(\"\\\\\", \"/\");\n\n        // 1. 防止路径遍历攻击\n        if (normalized.contains(\"..\") || normalized.contains(\"~\")) {\n            throw new JeecgBootException(\"上传业务路径包含非法字符！\");\n        }\n\n        // 2. 限制路径深度\n        int depth = normalized.split(\"/\").length;\n        if (depth > 5) {\n            throw new JeecgBootException(\"上传业务路径深度超出限制！\");\n        }\n\n        // 3. 限制字符集（只允许字母、数字、下划线、横线、斜杠）\n        if (!normalized.matches(\"^[a-zA-Z0-9/_-]+$\")) {\n            throw new JeecgBootException(\"上传业务路径包含非法字符！\");\n        }\n    }\n\n    /**\n     * 校验文件路径安全性，防止路径遍历攻击\n     * @param filePath 文件路径\n     */\n    public static void checkPathTraversal(String filePath) {\n        if (StringUtils.isBlank(filePath)) {\n            return;\n        }\n        // 1. 防止路径遍历：不允许 ..\n        if (filePath.contains(\"..\")) {","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/filter/SsrfFileTypeFilter.java#L266-L302","documentation":"Thrown by validatePathSecurity when the normalized customPath has more than 5 segments after split('/'). This caps folder nesting for uploaded files to prevent excessively deep (or DoS-inducing) paths and to keep uploaded content within a predictable tree.","triggerScenarios":"An upload request whose customPath is something like 'a/b/c/d/e/f/file' (6+ segments), or a path with leading/trailing slashes that inflate the split count, or a generated path stacking tenant/year/month/category/subcat/subsub.","commonSituations":"A path generator concatenates too many hierarchy levels; trailing slash makes split produce an empty first element raising the count; migration from a system that used deep folder structures.","solutions":["Reduce customPath to <= 5 segments, e.g. 'tenant/module/category'.","Trim leading/trailing slashes before counting: customPath.replaceAll('^/+|/+$','').","Move deep nesting into the server's storage logic, not the client-supplied customPath.","If deeper paths are genuinely needed, raise the cap and review the storage layout."],"exampleFix":"// before\ncustomPath = \"/a/b/c/d/e/f/\"; // 8 segments after split\n\n// after\ncustomPath = \"a/b/c\";","handlingStrategy":"validation","validationCode":"String n = customPath.replaceAll(\"^/+|/+$\",\"\");\nif (n.split(\"/\").length > 5) throw new IllegalArgumentException(\"too deep\");","typeGuard":"public static boolean pathDepthOk(String p){\n    String n = p == null ? \"\" : p.replaceAll(\"^/+|/+$\",\"\");\n    return n.split(\"/\").length <= 5;\n}","tryCatchPattern":"try { SsrfFileTypeFilter.checkUploadFileType(file, customPath); }\ncatch (JeecgBootException e) { if (e.getMessage().contains(\"深度\")) badRequest(e.getMessage()); }","preventionTips":["Trim leading/trailing slashes before counting segments.","Move deep nesting server-side.","Use <= 3 segments by convention."],"tags":["file-upload","path-traversal","validation","configuration","jeecg-boot"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}