modelscope.cn

java-security-scan-fixes

Java / Spring Boot 项目安? (1) 编写或修改? (2) 拼接用户传? (3) 收到代码扫描报告(fxnk、Fortify、Checkmarx、SonarQube)需要修复中危/高危缺陷; (4) 需要预防或修复信息泄露、HTTP 响应截断、流资源未释放、路径遍历、不安? (5) 需要预防或修复 SQL 注? 技术栈:Spring MVC + MyBatis + Apache POI。?

Installation

$ npx skills add https://modelscope.cn

Also in this package

Other skills from modelscope.cn · top by installs.

npx skills add https://modelscope.cn

Browse all from modelscope.cn

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Skill metadata

Parsed from SKILL.md frontmatter.

Version1.0.0
Declared agents claude-code

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 13,770 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

Java 安全扫描中高危等级缺陷修复指南

Problem

Java / Spring Boot 项目在安全代码扫描后,通常会产生数百到数千个中高等级缺陷,涵盖信息泄露、HTTP响应截断、流泄漏、路径遍历、不安全的框架绑定、SQL 注入、XSS 等类别。需要系统性地分类、制定计划、实施修复并验证编译。

Context / Trigger Conditions

编码/审查时(预防与修复均可触发):

  • 编写或修改 GlobalExceptionHandler 等全局异常处理器
  • 设置 HTTP 响应头(Content-DispositionContent-TypeSet-Cookie 等)且值来自用户输入
  • 拼接用户传入的文件路径进行文件读写、移动、复制、删除操作
  • 使用 FileInputStreamFileOutputStreamXSSFWorkbookPdfWriterServletOutputStream 等流对象
  • Spring MVC Controller 方法直接使用 Bean/VO 接收请求参数(public String add(User user)
  • 处理 ZIP 解压、文件上传 MultipartFile、Base64 转文件等场景
  • 对密码/密钥/随机数进行编码或加密操作
  • 编写或修改 MyBatis Mapper XML / @Select / @Update,使用 ${} 拼接参数
  • 将用户输入写入 Excel、HTML、PDF 或前端页面(存在 XSS 风险)
  • Controller 方法直接将用户输入回显到响应或视图(反射型 XSS)
  • 技术栈:Spring Boot + Spring MVC + MyBatis + Apache POI

收到扫描报告时:

  • 代码扫描报告(常见格式:Word .docx、PDF、HTML)
  • 扫描工具:fxnk、Fortify、Checkmarx、SonarQube 等
  • 中危缺陷数量通常在 1000+,需要分阶段实施

Solution

0. 预防性安全编码规范(写代码时直接遵循)

在生成或修改代码时,直接应用以下规范以避免中危缺陷:

场景 安全规范
全局异常处理 通用 Exception 捕获后返回固定模糊提示(如 "系统繁忙,请稍后重试"),禁止返回 e.getMessage() 给前端
HTTP 响应头 用户传入的字符串写入响应头前,必须过滤 \r\nvalue.replaceAll("[\\r\\n]", "")
文件流操作 所有 FileInputStream / FileOutputStream / Workbook / PdfWriter 必须使用 try-with-resources
文件路径拼接 用户传入的路径使用 getCanonicalPath() 校验,确保结果路径在允许的根目录范围内
Spring MVC 参数绑定 公共基类的 @InitBinder 中禁用敏感字段:binder.setDisallowedFields(...)
文件上传 校验 MIME Type、扩展名白名单、文件头 Magic Number,上传后重命名为随机文件名
SQL 查询 MyBatis 中禁止 ${} 拼接用户输入,统一使用 #{} 参数化查询;动态表名列名需先做白名单校验
XSS 防护 输出到 Excel/HTML/页面的用户数据先做 HTML 转义;前端输入做白名单校验,禁止直接回显未过滤的用户输入

1. 读取 .docx 扫描报告

若报告为 .docx 二进制文件,用 ZIP + XML 提取文本:

$temp = [IO.Path]::GetTempPath() + [Guid]::NewGuid().ToString()
[System.IO.Compression.ZipFile]::ExtractToDirectory('report.docx', $temp)
$xml = [xml](Get-Content "$temp\word\document.xml" -Encoding UTF8 -Raw)
$ns = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
$ns.AddNamespace('w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main')
$text = ($xml.SelectNodes('//w:t', $ns) | ForEach-Object { $_.InnerText }) -join ''

2. 缺陷分类与优先级排序

按风险影响 + 修复难度排序:

优先级 缺陷类别 典型数量 修复难度
P0 SQL 注入 + 存储型 XSS + 反射型 XSS + 高危路径遍历 ~500+
P1 信息泄露 + HTTP响应截断 ~10
P2 流资源未释放 + 路径遍历 ~70
P3 框架绑定 / Mass Assignment ~300+
P4 数据库访问控制 ~900+ 高(需评估误报)
P5 密码管理 / 加密算法 ~30 高(需兼容评估)

3. 常见缺陷修复代码模式

3.1 信息泄露(全局异常处理器)

问题handleException(Exception.class) 返回 e.getMessage(),可能暴露堆栈/SQL。 修复:返回统一模糊提示,详细异常只记录日志。

@ExceptionHandler(Exception.class)
public AjaxResult handleException(Exception e) {
    log.error(e.getMessage(), e);
    return AjaxResult.error("系统繁忙,请稍后重试");
}

3.2 HTTP 响应截断(Content-Disposition)

问题:用户可控文件名直接拼接到响应头,未过滤 \r\n修复:在编码前过滤换行符。

fileName = fileName.replaceAll("[\\r\\n]", "");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

3.3 流资源未释放

问题FileInputStream / FileOutputStream / Workbook 等未在 finally 中关闭。 修复:统一使用 try-with-resources

// 修复前
FileInputStream fis = new FileInputStream(file);
XSSFWorkbook wb = new XSSFWorkbook(fis);
// ... 业务逻辑 ...
// 缺少关闭

// 修复后
try (FileInputStream fis = new FileInputStream(file);
     XSSFWorkbook wb = new XSSFWorkbook(fis)) {
    // ... 业务逻辑 ...
}

关键类需检查:FileUtilsExcelUtilsPdfUtilsHtmlUtilsCsvUtils

3.4 路径遍历

问题:用户传入的路径直接拼接根目录,可能导致 ../../etc/passwd修复:使用 getCanonicalPath() 校验结果路径必须在根目录内。

private void validatePath(String path) {
    try {
        File file = new File(rootPath, path);
        String canonicalPath = file.getCanonicalPath();
        String canonicalRoot = new File(rootPath).getCanonicalPath();
        if (!canonicalPath.startsWith(canonicalRoot)) {
            throw new BaseException("非法文件路径");
        }
    } catch (IOException e) {
        throw new BaseException("文件路径校验失败");
    }
}

3.5 Spring MVC 不安全的框架绑定(Mass Assignment)

问题:Controller 直接绑定请求参数到 Bean,攻击者可批量赋值敏感字段(如 admin=true)。 修复:在公共基类的 @InitBinder 中全局禁用敏感字段。

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.setDisallowedFields("admin", "role", "password", "createTime",
            "updateTime", "createBy", "updateBy", "deleted", "delFlag", "tenantId");
    // ... 其他类型转换注册
}

3.6 SQL 注入(MyBatis 动态 SQL)

问题:MyBatis Mapper 中使用 ${} 拼接用户输入,攻击者可注入任意 SQL。 修复:将 ${} 替换为 #{} 参数化查询;动态表名/列名必须走白名单校验。

// 修复前(危险)
@Select("SELECT * FROM ${tableName} WHERE id = ${id}")
User selectById(String tableName, Long id);

// 修复后
@Select("SELECT * FROM #{tableName} WHERE id = #{id}")  // 错误:#{} 不能用于表名
// 正确做法:表名走白名单,值用 # {}
private static final Set<String> ALLOWED_TABLES = Set.of("sys_user", "sys_dept");
public User selectById(String tableName, Long id) {
    if (!ALLOWED_TABLES.contains(tableName)) {
        throw new BaseException("非法表名");
    }
    return sqlSession.selectOne("SELECT * FROM " + tableName + " WHERE id = #{id}", id);
}

3.7 存储型 XSS(导出/模板渲染场景)

问题:将用户输入的数据直接写入 Excel、HTML、PDF,前端再次展示时触发脚本执行。 修复:在写入前对用户数据进行 HTML 转义,或设置 Excel 单元格为纯文本类型。

// 修复前
row.createCell(0).setCellValue(user.getRemark()); // 用户输入可能含 <script>

// 修复后
String safeRemark = HtmlUtils.htmlEscape(user.getRemark());
row.createCell(0).setCellValue(safeRemark);

// 或者设置单元格类型为 STRING,避免公式执行
Cell cell = row.createCell(0);
cell.setCellValue(user.getRemark());
cell.setCellType(CellType.STRING);

3.8 反射型 XSS(参数回显场景)

问题:Controller 直接将用户输入回显到页面/响应,未做过滤或转义。 修复:对回显参数做输入校验 + 输出编码,Spring Boot 可开启默认 HTML 转义。

// 修复前
@GetMapping("/search")
public String search(String keyword, Model model) {
    model.addAttribute("keyword", keyword); // 直接回显
    return "searchResult";
}

// 修复后
@GetMapping("/search")
public String search(@RequestParam String keyword, Model model) {
    // 白名单校验:仅允许中文、英文、数字、空格
    if (!keyword.matches("^[\\u4e00-\\u9fa5a-zA-Z0-9\\s]+$")) {
        throw new BaseException("搜索关键字包含非法字符");
    }
    model.addAttribute("keyword", keyword);
    return "searchResult";
}

3.9 高危路径遍历(文件名/存储路径校验)

问题:用户传入的 storeNamefileName 等直接作为文件路径或文件名,未校验 ../ 或绝对路径。 修复:对文件名提取后校验,禁止路径分隔符;完整路径使用 getCanonicalPath() 校验。

private void validateFileName(String fileName) {
    if (fileName == null || fileName.contains("..") || fileName.contains("/") || fileName.contains("\\")) {
        throw new BaseException("非法文件名");
    }
}

private void validatePath(String rootPath, String path) {
    try {
        File file = new File(rootPath, path);
        String canonicalPath = file.getCanonicalPath();
        String canonicalRoot = new File(rootPath).getCanonicalPath();
        if (!canonicalPath.startsWith(canonicalRoot)) {
            throw new BaseException("非法文件路径");
        }
    } catch (IOException e) {
        throw new BaseException("文件路径校验失败");
    }
}

4. 验证方式

修复后必须执行:

mvn clean compile -DskipTests

重点关注:文件上传/下载、Excel 导出、PDF 生成等核心流程的回归测试。

Verification

  • mvn clean compile -DskipTests 编译通过,无新增报错
  • 回归测试:登录、文件上传下载、Excel 导出、异常触发后的前端提示正常
  • 复扫:使用相同检测模板重新扫描,目标中危缺陷数量下降

Example

场景:扫描报告提示 ExcelUtils.setResponseHeader 存在 HTTP 响应截断。

// 修复前
fileName = new String(fileName.getBytes("utf-8"), "ISO-8859-1");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

// 修复后
fileName = fileName.replaceAll("[\\r\\n]", "");
fileName = new String(fileName.getBytes("utf-8"), "ISO-8859-1");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

Notes

  • 密码管理/加密算法类缺陷(DES 转 AES、MD5 升级等)涉及存量数据兼容性,需单独评估迁移方案(双算法支持 + 登录时自动迁移)。
  • 数据库访问控制类缺陷数量通常最多(900+),若系统已在 Controller/Service 层通过登录会话做了统一鉴权,多数为误报,优先修复暴露在外网或无 Token 的接口。
  • 扫描报告中的行号可能与当前代码分支不完全一致,需结合跟踪路径(调用链)定位实际爆发行。

References