{"record":{"id":"db6524965a5dc9e8","repo":"dromara/Sa-Token","slug":"path-requestpath-db6524","errorCode":null,"errorMessage":"请求 path 包含禁止字符 %：{requestPath}","messagePattern":"请求 path 包含禁止字符 %：(.+?)","errorType":"exception","errorClass":"RequestPathInvalidException","httpStatus":null,"severity":"error","filePath":"sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForPathBannedCharacter.java","lineNumber":64,"sourceCode":"        this.bannedPercentage = bannedPercentage;\n    }\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        // 非可打印 ASCII 字符检查\n        String requestPath = req.getRequestPath();\n        if(SaFoxUtil.hasNonPrintableASCII(requestPath)) {\n            throw new RequestPathInvalidException(\"请求 path 包含禁止字符：\" + requestPath, requestPath);\n        }\n        if(bannedPercentage && requestPath.contains(\"%\")) {\n            throw new RequestPathInvalidException(\"请求 path 包含禁止字符 %：\" + requestPath, requestPath);\n        }\n    }\n\n}\n","sourceCodeStart":46,"sourceCodeEnd":69,"githubUrl":"https://github.com/dromara/Sa-Token/blob/ac2c7f6e94a78573cf0bcb932dd8b04e68fad189/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForPathBannedCharacter.java#L46-L69","documentation":"The second check in SaFirewallCheckHookForPathBannedCharacter: when config bannedPercentage is true (the default), any '%' character in the request path throws RequestPathInvalidException. Percent-encoding attacks (%2e%2e for '..') bypass naive path checks, so sa-token blocks raw percent signs in paths by default. Legitimately encoded path segments therefore fail this check.","triggerScenarios":"A request whose path contains '%', e.g. /files/report%20final.pdf or /search/%E4%B8%AD — i.e. any percent-encoded space, CJK character, or reserved char in the path — while firewall.banned-percentage is not set to false.","commonSituations":"Serving user-uploaded files with unicode or spaces in names; browsers auto-encoding non-ASCII path segments; enabling the default firewall on an API that already relies on encoded path variables.","solutions":["If your API legitimately uses encoded path segments, disable it: sa-token.firewall.banned-percentage=false","Prefer query parameters (?name=a%20b) over encoded path segments for user-supplied data","Normalize/decode URLs at the gateway so the app sees decoded paths without '%'"],"exampleFix":"# before\nsa-token:\n  firewall:\n    banned-percentage: true  # default; /files/a%20b.pdf blocked\n\n# after\nsa-token:\n  firewall:\n    banned-percentage: false","handlingStrategy":"validation","validationCode":"String path = SaHolder.getRequest().getRequestPath();\nboolean banned = SaManager.getConfig().getFirewall().getBannedPercentage();\nif (banned && path.contains(\"%\")) {\n    // either decode at the gateway, move data to query params, or disable banned-percentage in config\n}","typeGuard":null,"tryCatchPattern":"try {\n    chain.doFilter(req, res);\n} catch (RequestPathInvalidException e) {\n    res.setStatus(400);\n}","preventionTips":["If your URLs contain encoded unicode/spaces, set firewall.banned-percentage=false deliberately and document why","Prefer query parameters over encoded path segments for user-supplied text","Test representative URLs against the firewall after upgrading sa-token"],"tags":["sa-token","firewall","security","url-encoding","request-path"],"backgroundTag":null,"analyzedSha":"ac2c7f6e94a78573cf0bcb932dd8b04e68fad189","analyzedAt":"2026-08-14T14:36:10.271Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}