必须显式启用sonar.java.rule.jdbc=security等安全规则,并配置字节码路径与源码上下文,否则sql拼接代码将静默通过;命令行-d方式传参无效,需用sonar-project.properties或环境变量传递。

CI/CD 里加 SQL 注入扫描,不是“装个工具就完事”,而是必须让规则激活、上下文识别、退出机制三者同时生效,缺一不可。否则 String sql = "SELECT * FROM user WHERE id = " + id 这类代码会安静通过所有检查。
为什么 SonarQube 默认不报 SQL 拼接
SonarQube 把质量规则和安全规则物理隔离,默认只开 quality 规则集,sonar.java.rule.jdbc=security 这类安全规则全被关着。Java 项目里 @Query("SELECT * FROM u WHERE name = '" + name + "'")、JdbcTemplate.execute("UPDATE t SET v = " + input)、MyBatis XML 中的 ${table},全属于 security 规则范畴,不显式启用等于没装检测模块。
-
sonar.java.rule.jdbc=security:必须配,否则 JDBC 层字符串拼接完全不触发告警 -
sonar.java.rule.hql=security:不加这行,JPA/HQL 拼接不会被标记 -
sonar.mybatis.mapper.location=src/main/resources/mapper:不指定路径,XML 里的<select>SELECT * FROM ${param}</select>直接被跳过 - 这些参数仅在
sonar-scanner 5.0+生效;老版本用sonar.rules.category=Security,但漏报率明显更高
GitLab CI / Jenkins 中配置失效的三个硬坑
规则写了,却没生效?大概率是传参方式错了——sonar.java.rule.* 类参数不支持命令行 -D 方式传递,这是 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 语义识别
用 semgrep 替代 sqlmap 做 CI 内嵌扫描
sqlmap 是渗透工具,不适合 CI:它发真实请求、可能写脏数据、触发风控、不满足“无副作用”原则。真正适合流水线的是静态分析工具组合,其中 semgrep 是主力。
- 用
semgrep --config p/python.lang.security.insecure-sql-string-concatenation --error --exclude=tests/ --exclude=migrations/:加--error让匹配即失败,CI 自动标红 - 能精准捕获
cursor.execute(query + user_input)、f"SELECT * FROM {table_name}"(表名无法参数化,必须白名单校验)、filter(**{dynamic_key: value})(字段名未校验)等 ORM “伪安全”模式 - 别信“用了 PreparedStatement 就万事大吉”:工具链能识别
Statement和PreparedStatement混用、或预编译后仍用+拼字符串 - 配合
gitleaks防凭证泄露,间接降低注入风险;Python 项目可加bandit补充语言特异性规则
本地 VSCode 预检比 CI 更早拦截问题
别等流水线失败才发现问题。VSCode 里保存即跑 codeql query run sql-injection.ql,比 CI 早至少一个提交周期。
- 安装 VSCode 扩展:
CodeQL(官方)、ESLint + @typescript-eslint(配合自定义规则拦截"SELECT * FROM " + table类拼接) - 配置
.vscode/settings.json启用保存时自动扫描,把高危模式卡在键盘敲下回车前 - CI 是最后一道防线,编辑器才是第一道——很多
${}、format()、f-string拼接,根本不该进 Git
最常被忽略的点:所有扫描都依赖上下文识别。没有字节码路径、没有源码映射、没有规则激活,再好的工具也当摆设。尤其在多模块、混合框架(Spring Boot + MyBatis + JPA)项目里,漏掉任意一个路径或参数,SQL 注入就从检测列表里彻底消失。











