{"record":{"id":"8fb3955752339494","repo":"jeecgboot/JeecgBoot","slug":"path","errorCode":null,"errorMessage":"Path参数包含非法字符: ","messagePattern":"Path参数包含非法字符: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"critical","filePath":"jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/llm/handler/PluginToolBuilder.java","lineNumber":285,"sourceCode":"                JSONObject param = parameters.getJSONObject(i);\n                if (param == null) {\n                    continue;\n                }\n                String paramName = param.getString(\"name\");\n                String paramLocation = param.getString(\"location\");\n\n                if (!\"Path\".equalsIgnoreCase(paramLocation)) {\n                    continue;\n                }\n\n                Object value = args.get(paramName);\n                if (value != null) {\n                    //update-begin---author:wangshuai---date:2026-03-30---for:【issues/9421】buildUrl路径遍历漏洞修复---\n                    String paramValue = value.toString();\n                    // 防止路径遍历注入：拒绝包含 ..、/ 、\\ 的路径参数\n                    if (paramValue.contains(\"..\") || paramValue.contains(\"/\") || paramValue.contains(\"\\\\\")\n                            || paramValue.toLowerCase().contains(\"%2e\") || paramValue.toLowerCase().contains(\"%2f\")) {\n                        throw new IllegalArgumentException(\"Path参数包含非法字符: \" + paramName);\n                    }\n                    url = url.replace(\"{\" + paramName + \"}\", paramValue);\n                    //update-end---author:wangshuai---date:2026-03-30---for:【issues/9421】buildUrl路径遍历漏洞修复---\n                }\n            }\n        }\n\n        return url;\n    }\n\n    /**\n     * 构建请求头\n     */\n    private static HttpHeaders buildHttpHeaders(JSONArray parameters, JSONObject args, Map<String, String> defaultHeaders) {\n        HttpHeaders httpHeaders = new HttpHeaders();\n\n        // 添加默认请求头\n        if (defaultHeaders != null) {","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/llm/handler/PluginToolBuilder.java#L267-L303","documentation":"Thrown by PluginToolBuilder.buildUrl() when a Path-type URL parameter contains path traversal or path separator characters: '..', '/', '\\', '%2e', or '%2f' (case-insensitive). This prevents path traversal injection when building REST API URLs from OpenAPI/plugin parameter definitions (issue #9421).","triggerScenarios":"An AI agent calls a plugin/tool whose OpenAPI spec defines a Path parameter, and the argument value contains '..', '/', '\\', or URL-encoded equivalents. For example: a plugin with path '/api/files/{id}' receives id='../../etc/passwd' or id='foo/bar'.","commonSituations":"An LLM-generated function call includes a path-traversal payload in a Path parameter; a plugin is misconfigured to accept free-form path segments; URL-encoded traversal attempts (%2e%2e%2f) are passed.","solutions":["Ensure Path parameter values are simple identifiers (UUIDs, numeric IDs) without slashes or dots.","If the parameter legitimately needs sub-paths, restructure the API spec to use separate path segments or query parameters.","Validate LLM-generated tool call arguments before invoking the plugin."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Validate Path parameters before calling buildUrl\nfor (Map.Entry<String, Object> entry : args.entrySet()) {\n    String val = entry.getValue() == null ? \"\" : entry.getValue().toString();\n    if (val.contains(\"..\") || val.contains(\"/\") || val.contains(\"\\\\\")\n            || val.toLowerCase().contains(\"%2e\") || val.toLowerCase().contains(\"%2f\")) {\n        throw new IllegalArgumentException(\"参数\" + entry.getKey() + \"包含非法字符\");\n    }\n}","typeGuard":"private static boolean isSafePathParam(String value) {\n    if (value == null) return true;\n    String lower = value.toLowerCase();\n    return !value.contains(\"..\") && !value.contains(\"/\") && !value.contains(\"\\\\\")\n        && !lower.contains(\"%2e\") && !lower.contains(\"%2f\");\n}","tryCatchPattern":"try {\n    String url = buildUrl(baseUrl, path, parameters, args);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Path参数包含非法字符\")) {\n        log.warn(\"Plugin path parameter rejected: {}\", e.getMessage());\n        throw new JeecgBootException(\"插件参数包含非法路径字符\");\n    }\n    throw e;\n}","preventionTips":["Design plugin APIs to use simple identifier Path parameters (UUIDs, numeric IDs).","Validate LLM-generated tool call arguments before invoking plugins.","URL-decode parameter values before checking for encoded traversal sequences.","Restrict which plugins can be called with user-supplied Path arguments."],"tags":["security","path-traversal","ssrf","plugin","url-injection"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}