jeecgboot/JeecgBoot · warning · JeecgBootException

非法URL:地址为空

Error message

非法URL:地址为空

What it means

Thrown by SsrfFileTypeFilter.checkSsrfHttpUrl() when the provided HTTP download URL is null, empty, or whitespace-only. This is the first guard in the SSRF protection chain (added for issues/9553) — it validates any URL the platform fetches server-side before opening a connection. The method is called from FileDownloadUtils, HttpFileToMultipartFileUtil, AiragChatServiceImpl, and WordUtil whenever the server downloads a remote resource.

Source

Thrown at jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/filter/SsrfFileTypeFilter.java:324

        String fileLower = filePath.toLowerCase();
        if (fileLower.contains("%2e")) {
            throw new JeecgBootException("文件路径包含非法字符");
        }
    }

    //update-begin---author:zhangdaihao ---date:2026-04-15  for:【issues/9553】修复二次SSRF漏洞,对HTTP下载URL进行安全校验-----------
    /**
     * 校验HTTP(S) URL,防止SSRF攻击(最小化拦截,只挡真正危险的目标)。
     * 规则:
     * 1. 仅允许 http / https 协议;
     * 2. 解析主机IP,拒绝 loopback(127.x / ::1)和 link-local(169.254.x,含云元数据 169.254.169.254 / fe80:);
     * 注意:RFC1918 私网段(10/172.16/192.168)允许通过,兼容企业内网 MinIO/OSS/文件服务等合法用途。
     *
     * @param fileUrl HTTP(S) URL
     */
    public static void checkSsrfHttpUrl(String fileUrl) {
        if (StringUtils.isBlank(fileUrl)) {
            throw new JeecgBootException("非法URL:地址为空");
        }
        URI uri;
        try {
            uri = new URI(fileUrl);
        } catch (URISyntaxException e) {
            throw new JeecgBootException("非法URL:格式错误");
        }
        String scheme = uri.getScheme();
        if (scheme == null || !(scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https"))) {
            throw new JeecgBootException("非法URL:仅允许 http / https 协议");
        }
        String host = uri.getHost();
        if (StringUtils.isBlank(host)) {
            throw new JeecgBootException("非法URL:主机名为空");
        }
        // 去掉 IPv6 的中括号
        if (host.startsWith("[") && host.endsWith("]")) {
            host = host.substring(1, host.length() - 1);

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. Check for blank/null URL before calling checkSsrfHttpUrl and skip the download gracefully when the field is optional.
  2. Ensure the front-end form or API contract requires a non-empty URL for fields that trigger server-side downloads.
  3. If the URL comes from a comma-separated batch list, filter out blank entries before iterating (as checkPathTraversalBatch already does).

Example fix

// before
SsrfFileTypeFilter.checkSsrfHttpUrl(fileUrl);

// after
if (oConvertUtils.isNotEmpty(fileUrl)) {
    SsrfFileTypeFilter.checkSsrfHttpUrl(fileUrl);
}
Defensive patterns

Strategy: validation

Validate before calling

if (oConvertUtils.isEmpty(fileUrl)) {
    // skip download or return early — do not call checkSsrfHttpUrl
    return;
}

Try / catch

try {
    SsrfFileTypeFilter.checkSsrfHttpUrl(fileUrl);
} catch (JeecgBootException e) {
    log.warn("SSRF URL validation failed: {}", e.getMessage());
    return Result.error(e.getMessage());
}

Prevention

When it happens

Trigger: Calling checkSsrfHttpUrl with null, "", or a whitespace-only string; upstream callers passing a user-supplied fileUrl field that was not populated (e.g., empty form field in an online report image URL, AIRAG chat attachment, or word template image).

Common situations: Front-end submits an image/resource reference field that the user left blank; a JSON payload omits the url field and Java deserializes it to null; a CSV/Excel import column for URLs has an empty row that gets processed as a download URL.

Related errors


AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14). Data as JSON: /api/errors/4cf9027f43207f40. Report an issue: GitHub.