说起自定义规则这回事,我可太有发言权了。刚开始用Semgrep那会儿,我跟很多人一样,觉得跑跑内置规则就万事大吉了。结果呢?被误报和漏报折腾得够呛。后来我才明白,真正让Semgrep发挥价值的,恰恰是那几条自己亲手写的规则,它们就像给代码安全装上了“定制瞄准镜”,指哪打哪。
写规则前,先搞懂三个小套路
很多朋友一上来就照着文档抄YAML模板,结果写出来的规则要么匹配不上,要么把正常代码也标红了。我踩过的坑告诉我,写规则前得先想清楚三个问题:我们要抓什么模式?这个模式有没有反例?这个文件该不该扫?
举个例子,我们团队有个规范:所有密码做散列时必须用bcrypt,禁止用MD5。如果你直接写一条规则匹配“MD5”关键词,那百分之百会炸——测试代码里的注释、文档里的示例全给你报一遍。正确做法是:先用pattern匹配hashlib.md5或MessageDigest.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做精细化匹配:别只盯着固定字符串,结合正则可以抓取各种变体,比如判断变量名是否包含password、secret等敏感字眼。 - 善用
pattern-either处理多写法:比如加密函数在不同语言里写法不同,用pattern-either一次性覆盖全拼、缩写、别名,避免重复定义多条规则。 - 配合CI环境动态调整超时:大项目建议把
--timeout设成30秒,同时用--jobs 4开多线程,别让安全扫描变成流水线瓶颈。
说实话,写自定义规则最爽的不是拦截漏洞,而是看着规则库一点点积累,团队的安全水平肉眼可见地提升。从最开始我一人写,到现在开发自己提规则需求,整个氛围都变了。记住一句话:规则不在多,够准就行。下次你们项目再出新规,不妨自己动手试试,保准成就感爆棚。

MD5那段太真实,注释也报真的烦
mapper里写${}这个坑见过,查起来后背发凉
这个metavariable-regex能匹配多层调用吗?