10分钟上手Semgrep:从安装到跑通第一次静态分析扫描
【免费下载链接】semgrepLightweight static analysis for many languages. Find bug variants with patterns that look like source code.项目地址: https://gitcode.com/GitHub_Trending/se/semgrep
Semgrep 是一款能"读懂代码"的轻量级静态分析工具:你用写源码的方式写规则,它在 30 多种语言里找出同一类 bug 的所有变体。这篇指南不假设任何前置知识,目标是 10 分钟内让你装好它、看到第一条扫描结果,并写下第一条自己的规则。
为什么你需要一个会读代码的扫描器
假设你的代码库有 200 个 Python 文件,你想揪出所有没加 SSL 校验的requests.get调用。用 grep 搜字符串 "requests.get",你能找到 37 处,然后一个个点开看;而requests.get(url)和requests.get(url + suffix)写法不同、语义相同,正则更难伺候。缺的是一个理解代码结构、而不是字符匹配的工具。
Semgrep 静态分析就是干这个的:规则长得和你写的代码一模一样,它负责找出这种"代码形状"的所有变体——变量名不同、参数个数不同、换行不同都躲不掉。最受益的三类人:想统一团队编码规范的开发者、排查危险 API 调用的安全同学、以及被正则表达式折磨怕了的任何人。
30秒先跑通:一条命令装好 Semgrep 🚀
先装。Linux、macOS、WSL 都是一行(Windows 原生环境建议看下一节对比表里的 Docker 方案):
python3 -m pip install semgrep装完立刻验证安装是否成功,能打印出版本号就说明可用:
semgrep --version现在不用写任何配置就能扫第一次。这条命令在当前目录里查找"变量和自己比较"($X == $X,几乎必然是笔误):
semgrep --lang python -e '$X == $X' .终端列出文件:行号就算跑通了;显示 0 条也是正常结果,只说明代码里没这种笔误。
它凭什么不一样:读懂代码,而不是搜文字
用一个具体对比。找代码里的数字 2:
grep "2"相当于在 Word 里按 Ctrl+F:只匹配字面上出现 "2" 的位置,x = 1 + 1不会命中,注释里的# 共 2 种情况反而误报。- Semgrep 搜 2 更像请了个读过代码的同事来翻:它知道
1 + 1求值就是 2,所以x = 1; y = x + 1里的y = x + 1也能命中(这是 README.md 里的官方例子)。
底层靠的是两个记号。省略号...表示"任意参数或任意代码",print(...)能匹配print(x)也能匹配print(a, b, sep="-");$开头的元变量是通配符,$X == $X意思是"同一个东西跟自己比"。会用函数签名写代码,就会写规则。下图里上下两块都是正常源码:上面是规则,下面是测试代码,高亮那行就是命中处:
安装方式怎么选:一张表看明白
| 方式 | 命令 | 适合谁 | 一句话优缺点 |
|---|---|---|---|
| pip | python3 -m pip install semgrep | 跨平台、最常见 | 官方主路径、升级方便;要求 Python ≥3.10,建议在虚拟环境里装 |
| Homebrew | brew install semgrep | macOS 用户 | 一条命令、随 brew 升级省心;仅 macOS 可用 |
| Docker | docker run --rm -v "${PWD}:/src" semgrep/semgrep semgrep scan | 不想动本机环境、CI 里用 | 零依赖、环境一致;首次拉镜像慢,需挂载项目目录 |
| 源码构建 | 见下方流程 | 想参与贡献、改核心引擎 | 能跑最新代码和完整测试;需 OCaml 工具链(opam、gcc、dune),构建最慢 |
选法:只是扫代码 → pip;Mac 上 → brew;容器或 CI → Docker;要改源码 → 源码构建。源码构建先克隆仓库:
git clone https://gitcode.com/GitHub_Trending/se/semgrep然后在仓库目录依次执行make setup(装 OCaml 依赖)、make all(编译)、make install(装到 PATH)。这三个目标的用途在根目录 Makefile 的注释里写得很清楚。
配置你的第一次扫描:写一条最小规则
装好后你想把规则沉淀下来。在项目根目录建一个my-rules.yml(名字随意),内容就一条规则:
rules: - id: no-print-in-prod pattern: print(...) message: 生产代码请用 logging,禁止 print severity: WARNING languages: [python]逐字段说明:id是规则名,结果里会打印它,也用来去重;pattern是匹配目标,写成源码,...代表任意参数,所以print(x)和print(a, b)都能命中;message是命中时展示的文字;severity是严重级别,常用 INFO / WARNING / ERROR;languages限定规则作用的语言,这里只扫 Python,不碰其他文件。
然后运行:
semgrep --config my-rules.yml .跑完终端会按"文件 → 规则 id → message → 命中代码行"列出结果,大致长这样:
再补两个马上用得到的行为:Semgrep 会读取项目根目录的.semgrepignore,把dist/、*.min.js之类写进去即可跳过;规则里加fix:字段就能自动改写,本仓库 semgrep.yml 里就有现成例子(如fix: List_.map2),配合--fix参数直接替换代码。
踩坑与排查 ⚠️
- 现象:
semgrep: command not found。原因:pip 装进了未激活的虚拟环境,或 user 目录的 bin 不在 PATH。一句话解决:先用python3 -m semgrep --version绕过 PATH,确认可用后再激活环境或补 PATH。 - 现象:
pip install semgrep报Requires-Python >=3.10。原因:当前版本要求 Python 3.10+(见 cli/pyproject.toml 的requires-python)。一句话解决:升级 Python,或为你的 Python 版本固定安装一个旧的 semgrep。 - 现象:规则明明能命中,结果却是 0 条。原因:最常见是
languages与实际文件类型不符,或路径被.semgrepignore排除了。一句话解决:把具体文件路径直接传参semgrep --config my-rules.yml 那个文件.py,排除忽略规则干扰。 - 现象:pattern 看着对却报错或不命中。原因:按正则的习惯写了(比如
print\()。一句话解决:pattern 是代码不是正则,去掉转义,通配用...和$X。 - 现象:
--config auto或semgrep ci提示要登录。原因:这两个模式从在线规则仓库拉配置,需要账号。一句话解决:纯本地使用不需要登录,写本地规则文件加--config即可。
接下来做什么
- 学真实写法:tests/patterns/ 里 3000 多个规则测试用例覆盖 30 多种语言,随便打开一个看元变量和
patterns怎么组合。 - 抄生产级规则集:perf/r2c-rules/ 是官方 CI 自用的规则(django、flask、java、javascript 等),按需摘用。
- 看项目自己怎么查自己:根目录 semgrep.yml 是这套仓库的自检规则,含 OCaml/Python 专项规则和
fix自动修复字段,是"规则 + 自动修"最好的范本。
【免费下载链接】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),仅供参考