sonarqube默认不报sql注入是因为java安全规则(如sonar.java.rule.jdbc=security)被关闭,必须显式启用,并确保字节码路径、源码上下文和规则激活三者齐备,否则statement.executeupdate("update t set v = " + input)等代码将静默通过。

为什么SonarQube默认不报Statement.executeUpdate("UPDATE t SET v = " + input)?
不是规则没能力,是Java安全规则集默认关闭。SonarQube把quality和security规则完全隔离,所有JDBC拼接风险(如executeUpdate、@Query(""+name)、${table})全在sonar.java.rule.jdbc=security这类独立开关下。没显式启用,等于没装模块。
常见静默失效组合:
-
sonar.java.rule.jdbc=security没配 →executeUpdate("UPDATE t SET v = " + input)直接通过 -
sonar.java.binaries=target/classes路径错或缺失 → AST分析跑不起来,所有Java安全规则失效 -
sonar.sources=src/main/java指向不准 →@Query("SELECT * FROM u WHERE name = '" + name + "'")因上下文丢失而漏检
GitLab CI / Jenkins中sonar-scanner必须配对的三个硬性参数
SonarScanner 5.0+对sonar.java.rule.*类配置有硬限制:不支持命令行-D方式传参。错放位置=白配。
正确做法分场景:
-
GitLab CI:用
sonar-project.properties文件,或通过环境变量SONAR_SCANNER_OPTS="-Dsonar.java.rule.jdbc=security -Dsonar.java.rule.hql=security" -
Jenkins Pipeline:
withSonarQubeEnv块内必须显式声明sonar.java.binaries=target/classes,否则无字节码,AST分析中断 -
Maven多模块:父POM配了
sonar-maven-plugin,但子模块未声明sonar.language=java,会fallback到通用解析器,跳过Hibernate/JPA语义识别
如何让PR/MR评审时真正“卡住”不安全代码?
只标红问题不够,必须绑定质量门禁(Quality Gate)强制拦截。SonarQube不会自动拒绝合并,得靠规则+门禁双触发。
关键操作:
- 进后台创建/编辑Quality Gate,加条件:
Blocker issues > 0或New Blocker issues on new code > 0 - CI流水线执行
mvn sonar:sonar后,必须调用waitQualityGate()等待分析完成 - PR/MR页面会自动显示门禁状态;未通过则Merge按钮禁用,日志明确提示
Inheritance depth exceeds threshold或SQL injection detected
注意:sonar.java.rule.jdbc=security启用后,连final String sql = "SELECT * FROM " + table;这种看似受控的拼接也会告警——SonarQube不追踪变量来源,它只认字符串拼接行为本身。这是设计使然,不是误报。
要不要加semgrep做前置拦截?
要,而且建议放在pre-commit或MR pipeline最前端。SonarQube依赖编译和字节码,适合合入前最后一道防线;semgrep纯AST匹配,不依赖构建,能更早卡住cursor.execute("SELECT * FROM " + table)这类模式。
GitLab CI中必须带的关键参数:
-
--error:匹配即返回非0码,CI自动标红失败 -
--exclude=tests/ --exclude=migrations/:否则测试SQL和建表语句大量误报 -
--config=p/python.lang.security.insecure-sql-string-concatenation:必须写全规则ID,不能只写p/python
真正容易被忽略的是:SonarQube的jdbc和hql规则必须同时启用,且binaries与sources路径必须严格对应Maven实际输出结构——差一个target/或少个main/,整套安全扫描就形同虚设。











