Semgrep自定义规则编写实战技巧

话题来源: DevSecOps自动化:用Semgrep在CI/CD中构建代码安全护栏

说起自定义规则这回事,我可太有发言权了。刚开始用Semgrep那会儿,我跟很多人一样,觉得跑跑内置规则就万事大吉了。结果呢?被误报和漏报折腾得够呛。后来我才明白,真正让Semgrep发挥价值的,恰恰是那几条自己亲手写的规则,它们就像给代码安全装上了“定制瞄准镜”,指哪打哪。

写规则前,先搞懂三个小套路

很多朋友一上来就照着文档抄YAML模板,结果写出来的规则要么匹配不上,要么把正常代码也标红了。我踩过的坑告诉我,写规则前得先想清楚三个问题:我们要抓什么模式?这个模式有没有反例?这个文件该不该扫?

举个例子,我们团队有个规范:所有密码做散列时必须用bcrypt,禁止用MD5。如果你直接写一条规则匹配“MD5”关键词,那百分之百会炸——测试代码里的注释、文档里的示例全给你报一遍。正确做法是:先用pattern匹配hashlib.md5MessageDigest.getInstance("MD5"),再用pattern-not排除掉if DEBUG:这样的测试分支,最后用path-include只扫src目录。这样下来,误报率直接降到接近零。

实战:一条规则让SQL注入无处遁形

我再给你分享一条我们团队用得最狠的规则。以前我们用的是Java的MyBatis框架,总有开发在mapper.xml里写${xxx}(即直接拼接字符串),而不是用#{xxx}(参数化占位符)。那条规则长这样:

rules:
- id: mybatis-sql-injection
  patterns:
    - pattern: |
        $xxx
      - metavariable-regex:
          metavariable: $xxx
          regex: '${[^}]+}'
  paths:
    include:
      - "**/mapper/**/*.xml"
  message: "检测到MyBatis中使用了${}拼接,请改用#{}参数化查询"
  languages: [xml]
  severity: ERROR

写完直接放到项目里测,第一次就跑出了23个高危问题,其中好几个是核心交易接口的查询语句。开发者看完MR里的评论,当场就改过来了。这种即时反馈,比任何安全培训都管用。

几个容易忽略的小技巧

  • metavariable-regex做精细化匹配:别只盯着固定字符串,结合正则可以抓取各种变体,比如判断变量名是否包含passwordsecret等敏感字眼。
  • 善用pattern-either处理多写法:比如加密函数在不同语言里写法不同,用pattern-either一次性覆盖全拼、缩写、别名,避免重复定义多条规则。
  • 配合CI环境动态调整超时:大项目建议把--timeout设成30秒,同时用--jobs 4开多线程,别让安全扫描变成流水线瓶颈。

说实话,写自定义规则最爽的不是拦截漏洞,而是看着规则库一点点积累,团队的安全水平肉眼可见地提升。从最开始我一人写,到现在开发自己提规则需求,整个氛围都变了。记住一句话:规则不在多,够准就行。下次你们项目再出新规,不妨自己动手试试,保准成就感爆棚。

评论