Semgrep:从 0 到能跑代码扫描,5 分钟写好第一条检测规则
【免费下载链接】semgrepLightweight static analysis for many languages. Find bug variants with patterns that look like source code.项目地址: https://gitcode.com/GitHub_Trending/se/semgrep
你刚接手一个三年没动过的老仓库,团队想在下午会议前跑一轮安全扫描。旧规则风格混杂没人读得懂,你现在需要的是一台能立刻出结果的代码扫描器,而且规则要像自己写的代码一样能读。
Semgrep 就是干这件事的轻量级开源静态分析工具:用类源代码风格的 pattern 在代码里找漏洞与编码规范违规,支持 30 多种语言。
可以把它理解成"AST 版 grep"。同样输入一段代码片段,但关键区别在于:grep 对文本逐字符匹配,Semgrep 先把目标代码和你的 pattern 都解析成抽象语法树,再在树上做结构比对。所以print(...)会命中任意参数的 print 调用,变量改名、缩进变化都不影响结果。
三步跑通第一次扫描
安装
python3 -m pip install semgrep写一条规则
存成print-rule.yaml,6 行够用:
rules: - id: print-statement pattern: print(...) message: "调试打印,请改用 logger" languages: [python] severity: WARNING逐字段看为什么这么写:
id:规则唯一标识,出现在所有输出和报告里,后面写--include、聚合结果都要靠它pattern:规则本体,就是一段"源代码"。...是通配符,匹配任意参数,所以能覆盖print()到print(a, b, flush=True)的所有变体message:附在结果上的可读描述,写清楚"该怎么办"比只说"有问题"更有用languages:限定生效的语言,同一份文件改这里就能复用到别的语言severity:严重级别,INFO/WARNING/ERROR,决定 CI 里是否阻断
执行
semgrep scan --config print-rule.yaml .终端里会得到每条命中的文件、行号、代码原文和你写的 message。
看到结果之后,再回头看原理就不抽象了。
匹配过程分四步
1. 解析目标代码。languages/ 下每种语言都有专门的前端,有的走 Tree-sitter,有的用专门解析器,产出该语言的语法树。
2. 归一化为通用 AST。各语言树再转成同一套通用 AST,匹配逻辑因此被所有语言复用——这是"30 多语言共享一个引擎"成立的原因。
3. 结构化匹配。核心实现在 src/matching/:pattern 也被解析成树,与目标树逐结构比对。$X元变量绑定任意表达式,...匹配任意中间节点,规则因此写得可以很"松"而不会误伤。
4. 组合逻辑公式。一条规则不必只有一个 pattern:用patterns加and/or/where组合多个条件,还能用metavariable-pattern对已匹配出的元变量做二次过滤,比如"函数名匹配$F且$F以fetch开头"。求值逻辑在 src/engine/。
输出支持 JSON、SARIF 等机器可消费格式,挂到 pre-commit 或 CI 里基本是加一行配置的事。
能做什么,哪里会打折扣
- 强项:单文件、单函数范围内的结构匹配,速度快、误报低,默认全部本地执行,代码不出机器
- 弱项:社区版的分析边界止步于单函数/单文件,没有跨文件数据流分析。官方文档明确说,当用途是严肃的 SAST 时,开源版会漏掉不少真阳性,Pro 引擎才补上可达性分析
- 效果打折的场景:代码大量使用间接调用、动态分发时,pattern 难写且容易漏;仓库里解析报错文件多时,只能拿到部分 AST,依赖完整结构的 pattern 会失手
- 别高估:它是模式引擎,不是漏洞预言机。结果质量取决于规则写法,调误报这件事没有免费午餐
工具本身很快,真正的功夫在下笔时让规则既不太窄(漏报)也不太宽(全是噪音)。
【免费下载链接】semgrepLightweight static analysis for many languages. Find bug variants with patterns that look like source code.项目地址: https://gitcode.com/GitHub_Trending/se/semgrep
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考