jeecgboot/JeecgBoot · error · JeecgBootBizTipException
原始接口路径不允许嵌套 file/ftp/gopher/jar/netdoc 等协议
Error message
原始接口路径不允许嵌套 file/ftp/gopher/jar/netdoc 等协议
What it means
Thrown in the full-http-URL branch when the substring after '://' still embeds a dangerous scheme token (file:, ftp:, etc.). This defeats bypass tricks like 'http://x@file:/path' or 'http://evil.com/?next=ftp://...' where a nested scheme could be re-resolved downstream.
Source
Thrown at jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/controller/OpenApiController.java:280
String lower = decoded.toLowerCase();
boolean isFullHttpUrl = lower.startsWith("http://") || lower.startsWith("https://");
if (!isFullHttpUrl) {
if (!decoded.startsWith("/")) {
throw new JeecgBootBizTipException("原始接口路径必须以 / 开头,或填写完整的 http(s) URL");
}
if (decoded.startsWith("//") || decoded.startsWith("/\\")) {
throw new JeecgBootBizTipException("原始接口路径不能以 // 或 /\\ 开头");
}
if (lower.contains("://") || lower.startsWith("file:") || lower.startsWith("ftp:") || lower.startsWith("gopher:")
|| lower.startsWith("jar:") || lower.startsWith("netdoc:")) {
throw new JeecgBootBizTipException("原始接口路径仅支持相对路径或 http(s) 完整URL");
}
} else {
// 即便是完整URL,也禁止其它危险协议(防止 http://x@file:/... 之类的绕过场景)
String afterScheme = lower.substring(lower.indexOf("://") + 3);
if (afterScheme.contains("file:") || afterScheme.contains("ftp:") || afterScheme.contains("gopher:")
|| afterScheme.contains("jar:") || afterScheme.contains("netdoc:")) {
throw new JeecgBootBizTipException("原始接口路径不允许嵌套 file/ftp/gopher/jar/netdoc 等协议");
}
}
if (decoded.contains("..")) {
throw new JeecgBootBizTipException("原始接口路径不能包含 ..");
}
//update-end---author:scott ---date:20260429 for:【issues/9590】微服务nginx部署openApi接口访问不到-----------
}
@GetMapping("/json")
public SwaggerModel swaggerModel() {
SwaggerModel swaggerModel = new SwaggerModel();
swaggerModel.setSwagger("2.0");
swaggerModel.setInfo(swaggerInfo());
swaggerModel.setHost("jeecg.com");
swaggerModel.setBasePath("/jeecg-boot");
swaggerModel.setSchemes(Lists.newArrayList("http", "https"));
View on GitHub (pinned to 96fb33f5ec)
Solutions
- Strip the nested dangerous scheme from the URL; if it is only in a query param, consider whether it is necessary.
- Use a clean http(s) URL with no secondary scheme keywords anywhere in the string.
- If a legitimate parameter must contain the substring 'ftp:' etc., route it through a different field, not originUrl.
Example fix
// before: originUrl = "http://gateway/r?u=ftp://internal" // after: originUrl = "http://gateway/r" // pass 'u' via a separate signed param
Defensive patterns
Strategy: validation
Validate before calling
// For full http(s) URLs, ensure no nested dangerous scheme anywhere after '://'
private static boolean isSafeHttpUrl(String s) {
String l = s == null ? "" : s.toLowerCase();
if (!(l.startsWith("http://") || l.startsWith("https://"))) return false;
String rest = l.substring(l.indexOf("://") + 3);
return !rest.contains("file:") && !rest.contains("ftp:") && !rest.contains("gopher:")
&& !rest.contains("jar:") && !rest.contains("netdoc:");
} Prevention
- Audit full http(s) origin URLs for embedded scheme keywords in query/path.
- Pass secondary redirect targets through a separate signed parameter, not originUrl.
- Treat nested schemes as SSRF attempts in review.
When it happens
Trigger: origin_url such as 'http://attacker.com/redirect?to=file:/etc/passwd', 'https://x@ftp://internal', or any full URL whose authority/query/path contains one of the blocked scheme keywords.
Common situations: SSRF payloads crafted to pass the outer http(s) check; legitimate URLs that happen to include 'ftp:' in a query string or path segment (rare but possible in proxy/redirect configs).
Related errors
AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14).
Data as JSON: /api/errors/875c42d46540bb0b.
Report an issue: GitHub.