用 5 行规则扫出整个代码库的漏洞:Semgrep 静态分析上手指南
【免费下载链接】semgrepLightweight static analysis for many languages. Find bug variants with patterns that look like source code.项目地址: https://gitcode.com/GitHub_Trending/se/semgrep
一个 PR 里混进一行硬编码密钥、一行遗留的print,靠人眼 review 还能稳定接住吗?Semgrep是一个开源、轻量的静态分析工具:你用类源码风格的 pattern 写规则,它对 30 多种语言做代码漏洞检测与 bug 变体扫描,可以跑在本地终端、pre-commit 或 CI/CD 流水线里。
从一次真实扫描说起:字符串 grep 差在哪
先看效果:在终端执行semgrep scan --config auto,它会列出每条发现的规则 ID、说明文字,并高亮命中的那一行源码。
这和grep的差距不在速度,而在"看到什么"。对字符串做grep "foo("只能精确命中foo(这个写法,参数换个变量名、中间加一行空行,就可能漏掉;而 Semgrep 是先理解代码结构再去比对,所以能抓到同一个问题的不同"变体"写法——README 里有个直观例子:搜语义上的2,它甚至能命中x = 1; y = x + 1,因为比较的是含义而非字符。
从源码到命中:AST 分析的三步流水线
"理解"是怎么做到的?拆解成三步:
- 前端解析:每种语言有自己的解析器,把源码变成该语言的语法树,各语言解析器集中在 languages/ 目录,部分前端基于 Tree-sitter 构建。
- 归一化:各语言语法树统一转成一棵"通用抽象语法树"(generic AST),核心逻辑在 src/parsing/。打个比方:各国选手用各自方言交卷,判分程序先把所有答卷翻译成标准记号,再统一判分。
- 模式匹配:你的规则同样被解析成树,然后和目标代码的树做逐节点的结构比对,匹配引擎在 src/matching/ 目录。
正是第 2 步,让核心匹配逻辑只写一份,就能覆盖几十种语言。
写第一条规则:YAML 里直接嵌源码
规则就是一个 YAML 文件,pattern 部分用目标语言原样书写:
rules: - id: hardcoded-credential languages: [python] severity: ERROR message: 密钥不应硬编码在仓库里 pattern: $VAR = "password"需要新学的只有两个符号:
...省略号:通配占位符,匹配任意数量的参数或表达式。print(...)表示"任何参数的 print 调用"。$X元变量:有名字的占位符,记住命中的内容供后续复用,$X == $X就能抓到任何"变量和自己比较"的无效代码。
进阶规则语法:排除误报与二次过滤
写规则到一定阶段,最常用的是下面几种组合:
| 语法 | 作用 | 典型场景 |
|---|---|---|
pattern-not | 从命中里减去子集 | 检测$DB.execute("..." + $INPUT)拼接 SQL,再排除参数化写法 |
metavariable-pattern | 对已命中的元变量做二次过滤 | 只对$F的路径含/etc/的open($F)报警 |
patterns/pattern-either | 多模式 AND / OR | 同一函数里既出现反序列化又出现用户输入 |
涉及"用户输入流入危险函数"这类跨语句问题时,引擎会切换到污点分析路径,相关实现在 src/tainting/ 目录——这就是"SQL 注入防护"这类规则背后的原理。
AST-based Autofix:不只报问题,还能直接改
发现漏洞之后,能不能顺手改掉?可以。加上--autofix,Semgrep 会把命中代码按修复模板替换,且替换发生在 AST 层面,改完的代码结构依然合法,不是粗暴的字符串拼接。
仓库 tests/autofix/ 里就有真实用例(Python 目录下):规则命中foo(3),修复模板为bar($X * 2):
# 修复前(被规则命中) foo(3) # 修复后($X 原样带出 3) bar(3 * 2)修复模板还能用正则捕获组、...通配,实现逻辑集中在 src/fixing/。
接下来跑在哪:从本地 CLI 到 CI 流水线
- 本地:
pip install semgrep装好后,一条semgrep scan就能扫完整个仓库;不装环境也可以直接在 Semgrep Playground 网页上写规则试跑。 - 流水线:接入 GitHub Actions、GitLab CI、Jenkins 等,让每个 PR 合并前自动过一遍规则。
想抄作业的话,tests/rules/ 目录下的官方规则与测试用例值得逐条读,规则写法基本都覆盖到了。下一步建议:翻一遍 README.md 的 Quick Start,再到 Playground 里给自己项目写第一条规则。技术细节以仓库最新版本为准。
【免费下载链接】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),仅供参考