sonarqube默认不报statement.execute()拼接sql,因其java安全规则(如jdbc/hql/mybatis注入)被默认关闭,需显式配置sonar.java.rule.jdbc=security等参数并确保字节码路径、源码上下文和规则启用三者齐备,否则动态sql拼接将静默通过。

默认启用的静态扫描工具几乎从不报SQL注入——不是它们没能力,而是安全规则被默认关掉了。必须手动激活对应语言层的语义规则,并确保编译产物、源码路径、上下文识别三者全部到位,否则String sql = "SELECT * FROM user WHERE id = " + id;这种代码会安静地通过所有检查。
为什么SonarQube默认不报Statement.execute()拼接SQL
SonarQube把质量规则和安全规则分开了。Java项目里@Query硬拼、JdbcTemplate.execute()动态构造、MyBatis的${}占位符,全属于security规则集,默认关闭。不显式启用,就等于没装检测模块。
-
sonar.java.rule.jdbc=security:必须开启,否则Statement.executeUpdate("UPDATE t SET v = " + input)完全不触发告警 -
sonar.java.rule.hql=security:不加这行,@Query("SELECT * FROM u WHERE name = '" + name + "'")不会被标记 -
sonar.mybatis.mapper.location=src/main/resources/mapper:不指定路径,XML里的<select>SELECT * FROM ${table}</select>直接被跳过 - 这些配置只在
sonar-scanner5.0+生效;老版本要用sonar.rules.category=Security,但漏报率明显更高
GitLab CI / Jenkins中常见的sonar-scanner配置失效点
规则配了,却没生效?大概率是参数传错了地方。命令行-D方式对sonar.java.rule.*类参数完全无效,这是SonarQube的硬限制。
- GitLab CI必须用
sonar-project.properties文件或环境变量SONAR_SCANNER_OPTS传递规则,写成sonar-scanner -Dsonar.java.rule.hql=security等于白配 - Jenkins Pipeline中,
withSonarQubeEnv块内漏掉sonar.java.binaries=target/classes——没有字节码路径,AST分析无法进行,所有Java安全规则静默失效 - Maven多模块项目只在父
pom.xml里配sonar-maven-plugin,子模块不显式声明sonar.language=java,可能 fallback 到通用解析器,跳过Hibernate/JPA语义识别
VSCode本地预检:保存即跑codeql查sql-injection.ql
别等CI才发现问题。用CodeQL在编辑器里实时拦截,比流水线早至少一个提交周期。
- 安装VSCode扩展:
CodeQL(官方)、ESLint + @typescript-eslint(配合自定义规则拦截"SELECT * FROM " + table类拼接) -
.vscode/tasks.json里定义任务,保存.ts或.js时自动执行:codeql database create db --language=javascript --source-root . && codeql database analyze db codeql-suites/javascript-code-scanning.qls --format=sarif-latest --output=report.sarif - 结果直出SARIF格式,VSCode问题面板原生解析,高亮到具体行,且可配置为“保存失败”阻断动作
真正难的不是加工具,而是让规则理解业务上下文:MyBatis里${table}可能是合法的动态表名,也可能是注入入口;Druid报sql injection violation未必是漏洞,也可能是字段名撞了order这种关键字。所以配置之后,一定要拿真实SQL日志反向验证规则是否真在起作用,而不是只看扫描报告有没有红标。











