{"record":{"id":"9c68bb953cfe255d","repo":"dromara/Sa-Token","slug":"requestpath-9c68bb","errorCode":null,"errorMessage":"非法请求：{requestPath}","messagePattern":"非法请求：\\{requestPath\\}","errorType":"exception","errorClass":"RequestPathInvalidException","httpStatus":null,"severity":"error","filePath":"sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForDirectoryTraversal.java","lineNumber":46,"sourceCode":"public class SaFirewallCheckHookForDirectoryTraversal implements SaFirewallCheckHook {\n\n    /**\n     * 默认实例\n     */\n    public static SaFirewallCheckHookForDirectoryTraversal instance = new SaFirewallCheckHookForDirectoryTraversal();\n\n    /**\n     * 执行的方法\n     *\n     * @param req 请求对象\n     * @param res 响应对象\n     * @param extArg 预留扩展参数\n     */\n    @Override\n    public void execute(SaRequest req, SaResponse res, Object extArg) {\n        String requestPath = req.getRequestPath();\n        if(!isPathValid(requestPath)) {\n            throw new RequestPathInvalidException(\"非法请求：\" + requestPath, requestPath);\n        }\n    }\n\n    /**\n     * 检查路径是否有效\n     * @param path /\n     * @return /\n     */\n    public static boolean isPathValid(String path) {\n        if (path == null || path.isEmpty()) {\n            return false;\n        }\n\n        // 必须以 '/' 开头\n        if (path.charAt(0) != '/') {\n            return false;\n        }\n","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/dromara/Sa-Token/blob/ac2c7f6e94a78573cf0bcb932dd8b04e68fad189/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForDirectoryTraversal.java#L28-L64","documentation":"The DirectoryTraversal firewall hook validates the raw request path with SaFirewallCheckHookForDirectoryTraversal.isPathValid: the path must be non-empty, start with '/', contain no '.' or '..' path components, and contain no empty components (i.e. no '//' inside or at the end). Any violation throws RequestPathInvalidException, blocking classic '../' traversal payloads before they reach your controller.","triggerScenarios":"Requests like /user/info/.., /a/./b, /static//file.css (double slash), a path not starting with '/', an empty path, or a trailing '/.' — anything where splitting on '/' yields a '.', '..' or interior empty component.","commonSituations":"Client SDKs or proxies appending a trailing double slash; URL builders that join segments with a duplicate '/'; attackers probing with ../etc/passwd style paths; a misconfigured gateway forwarding a path without a leading slash.","solutions":["Fix the client/proxy to normalize the URL before sending (collapse '//' and resolve '.'/'..' segments)","If double slashes are legitimate for you, disable or customize the hook: SaManager.getSaFirewallStrategy().removeCheck(\"directory-traversal\") or replace it with a tolerant implementation","Log the offending path in a global exception handler to find which upstream produces malformed URLs"],"exampleFix":"// before: upstream sends /static//app.js or /files/../secret\n// after: normalize the path before forwarding\nString normalized = req.getRequestPath().replaceAll(\"/+\", \"/\");","handlingStrategy":"validation","validationCode":"String path = SaHolder.getRequest().getRequestPath();\nif (!SaFirewallCheckHookForDirectoryTraversal.isPathValid(path)) {\n    // reject / normalize before the firewall hook runs\n}","typeGuard":null,"tryCatchPattern":"try {\n    chain.doFilter(req, res);\n} catch (RequestPathInvalidException e) {\n    res.setStatus(400);\n    res.getWriter().write(\"malformed path\");\n}","preventionTips":["Build URLs with a join utility that never emits '//', '/./' or '/..'","Normalize client-supplied paths before they reach the firewall","Treat traversal-shaped paths as attack traffic: log and alert, don't just 400"],"tags":["sa-token","firewall","security","directory-traversal","request-path"],"backgroundTag":null,"analyzedSha":"ac2c7f6e94a78573cf0bcb932dd8b04e68fad189","analyzedAt":"2026-08-14T14:36:10.271Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}