如何用源码写规则做静态分析: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 是一个开源静态分析工具,核心卖点是"用长得像源码的模式去匹配代码":你写print(...),它就能在所有 Python 文件里找到各种变体的print调用,而不只是字符串相同的行。它面向需要做安全扫描、代码规范检查、API 迁移审计的工程师,本地即可运行,代码默认不上传。
当"找到所有用法"靠 grep 已经不够时
grep 只能匹配字面量,而代码审查和安全审计要的是语义匹配:同一个函数换了参数、拆成多行、包了一层,grep 就漏了。Semgrep 的规则就是为这个场景设计的——模式写法就是你平时写的代码,变量用$X这样的元变量代替。
不安装任何规则文件,直接用-e跑一条内联模式是最快的验证方式:
# 找出所有"左右两边是同一个表达式"的相等比较,常见笔误 semgrep -e '$X == $X' --lang=py path/to/src这条模式会命中if x == x:这类逻辑上必然恒真的比较,$X可以是任意表达式。确认输出里列出的文件行号确实是误用之后,你就理解了 Semgrep 与 grep 的本质区别:它解析代码结构后再做匹配,参数数量、表达式嵌套都不影响命中。
本地跑一次完整扫描:安装与自动配置
社区版默认在本地完成分析,不需要联网即可扫描;只有拉取远程规则库或登录账号时才需要网络。
# macOS brew install semgrep # Linux / macOS / WSL python3 -m pip install semgrep # 不安装,直接容器里跑 docker run -it -v "${PWD}:/src" semgrep/semgrep semgrep scan --config auto安装完成后在项目根目录执行semgrep scan --config auto。auto配置会自动检测项目语言,并从 Semgrep 规则库拉取对应的高置信度社区规则,省去了手动挑选规则的步骤。
从输出可以读到三类信息:扫描矩阵(每种语言匹配了多少规则、多少文件)、进度条、以及按文件聚合的 Findings。每条 finding 给出规则 id、人类可读的问题描述和命中的具体代码行——后续做误报豁免时,规则 id 就是引用依据。
登录账号是可选步骤,但登录后才能使用 Pro 规则、Pro 引擎和依赖供应链扫描:
semgrep login写自己的规则:一条模式到一份规则文件
内置规则覆盖通用安全模式,但"本项目禁止直接print、必须走 logging"这类团队规范只能自己写。规则就是一个 YAML 文件,最小可用结构如下:
rules: - id: python-no-prints-in-prod languages: [python] pattern: print(...) message: Use logging.debug() instead of print() severity: WARNING...是省略符,匹配任意数量的参数;$X匹配任意表达式。保存为rules/no-print.yml后执行:
semgrep scan --config rules/no-print.yml .进阶能力包括用patterns(多条模式取交集)、pattern-not(排除)、metavariable-regex(对元变量内容再做正则约束)来收窄命中范围。想验证规则写得对不对,仓库里自带了大规模测试样例,tests/patterns/ 目录下有上千个按语言组织的模式测试用例,tests/rules/ 则是完整的规则行为测试,可以作为编写和调试规则的参照。
接入 CI 流水线:只报这次提交引入的问题
在 CI 里全量跑扫描,第一反应通常是"存量问题几百条,流水线直接红了"。Semgrep 的 CI 模式针对这个痛点做了处理:接入 CI 后配置为扫描 Pull Request 时,只报告该 PR 新引入的问题,存量问题不会阻塞合并——这是它能低成本落地的关键原因。
支持 GitHub Actions、GitLab CI/CD、Jenkins、CircleCI、Azure Pipelines 等主流平台,仓库的 README 里附带了各平台的接入指引:
最简接入方式是让 Semgrep 在 CI 里调用semgrep ci命令,它会读取账号下的策略配置并回写 PR 评论。本地开发时的门禁可以复用同一条规则文件,保持本地与 CI 结果一致:
semgrep scan --config rules/no-print.yml --error--error让扫描在发现命中时以非零码退出,这样 git pre-commit 钩子就能直接拦截提交。
边界与代价:社区版不适合什么场景
社区版(CE)的能力边界是官方明确声明的:分析被限制在单个函数或单个文件的边界内,无法做跨文件、跨函数的数据流追踪。
- 复杂漏洞检测会漏报。像"用户输入从 HTTP 端点流经三个文件最终进入 SQL 拼接"这类污点分析场景,CE 引擎看不到完整链路,安全团队对此的定位是"适合对误报容忍度较高的临时审计"。
- 误报率高于商用平台。官方 README 声称其商业平台的数据流能力可减少约 25% 误报并提升约 250% 的真阳性检出,这个数字反过来也说明纯模式匹配在深层数据流场景下的精度上限。
- 与替代方案的取舍。如果需求是"快速把团队编码规范钉住、审计危险 API、做 API 迁移",模式匹配足够且扫描速度快;如果需求是生产环境的 SAST 合规,应评估商用平台而不是硬用 CE。
- 指标上报。使用规则库远程配置(如
--config auto)时会向 semgrep.dev 上报匿名规则指标,介意可用--metrics=off关闭;本地 YAML 文件在登录状态下也会上报指标。
另外,仓库中 cli/src/semgrep/mcp/ 提供了一个 MCP Server(semgrep mcp启动),让 AI 编码助手能在本地直接触发扫描,适合把扫描嵌入 IDE 工作流;而 languages/ 目录可以查当前引擎对每种语言的解析器实现情况,判断某门小众语言的支持深度。
最小可执行清单
pip install semgrep,在项目根目录跑semgrep scan --config auto,看输出结构,确认能读到规则 id 与命中行号。- 用
semgrep -e '$X == $X' --lang=py .验证语义匹配,体会元变量写法。 - 写一份 5 行的团队规范规则(
id/pattern/message/severity),用--config指向本地文件验证命中。 - 给规则加
--error挂进 pre-commit,本地提交时先拦截。 - 在 CI 中接入
semgrep ci,确认它只报 PR 新引入的问题,存量代码不阻塞合并。
【免费下载链接】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),仅供参考