6.1 semgrep:规则即代码


6.1 semgrep:规则即代码

本节摘要:semgrep 是轻量多语言静态分析工具,口号是「模式即代码」——规则本体就是 YAML 里的一段代码模式。本节从安装和第一场自动扫描开始;然后用官方宣传的「三行规则起步」写出第一条自定义规则;接着过一遍规则语法要点:组合匹配、元变量捕获、污点模式三件套;再拿一个自建的小型 Flask 项目跑官方规则集,学会读结果而不是只数告警数;最后澄清 semgrep 的 AI 能力官方口径——误报分诊宣称降低约八成人工工作量、AI 修复建议与 MCP 支持,并强调「口径以官方文档为准」。研究对象全部使用自建项目与开源代码。

学习目标

  • 安装 semgrep 并用自动规则完成第一场扫描。
  • 从三行核心规则写出第一条自定义匹配并跑出报告。
  • 掌握 patterns 组合、元变量、pattern-not 排除与污点模式。
  • 用官方规则集扫描自建项目,按「定位、证据、置信」三步读结果。
  • 准确转述 semgrep AI 能力的官方口径,不夸大不脑补。

一、安装与第一场扫描

semgrep 社区热度约 17.1k stars(2026-10 社区口径),社区版免费,安装一条命令:

# install_semgrep.sh —— semgrep 安装与版本确认 pip install semgrep semgrep --version ​

第一场扫描不需要写任何规则,auto 模式会按项目语言自动挑选官方规则:

# first_scan.sh —— 自动规则首扫:进入项目根目录执行 cd myflask semgrep scan --config auto --metrics=off . ​

--metrics=off 关闭匿名使用上报,在敏感研究环境里建议常带。扫描输出按文件分组列出规则编号、严重级别、命中的代码行。此时你大概率会看到几条低置信的 NOTE——先别急着重写代码,6.1 节末尾的分诊方法与第 11 章的证据链会告诉你怎么处理它们。

提示:官方文档与规则注册表(registry)是唯一的权威口径来源,本节所有命令参数以 semgrep 官方文档为准。

二、从三行规则起步

官方宣传「规则可以从三行写起」。最精简的规则核心确实只有三件事:匹配什么(pattern)、说什么(message)、适用什么语言(languages),再加上 id 与 severity 两个登记项。先造一个测试对象——自己写的表达式小工具:

# calc.py —— 自建测试对象:表达式计算小工具(仅用于测试规则) def run(expr): return eval(expr) def safe_run(expr): return eval(compile(expr, "<input>", "eval")) ​

三行起步的规则:

# no_eval.yml —— semgrep 最小规则:报告 eval 调用 rules: - id: python-eval-used pattern: eval(...) message: 检测到 eval 调用,确认参数来源是否可控 languages: [python] severity: WARNING ​

运行与读结果:

# run_rule.sh —— 用自定义规则扫描测试文件 semgrep scan --config no_eval.yml --metrics=off calc.py ​

输出会把 run 与 safe_run 里的两处 eval 都标出来。这条规则已经具备生产能力的三要素:可版本管理(规则是文件)、可解释(message 就是文档)、可复用(换一个仓库照样跑)。所谓「模式即代码」,是说模式直接用目标语言写,不用学新的匹配 DSL。

三、规则语法要点:从匹配到污点

规则语法常用件可以归成一张表:

语法件 作用 一句话例子
pattern 单一模式 eval(...)
patterns 与组合 同时满足多个条件
pattern-either 或组合 多个危险写法一网打尽
pattern-not 排除 排除已知安全的等价写法
metavariable 捕获与复用 把 $X 抓出来参与后续判断
pattern-inside 上下文限定 只看函数体内、只看循环内
mode: taint 污点模式 从 source 到 sink 的数据流

元变量示例——把「谁赋值给谁」抓出来:

# self_assign.yml —— 元变量捕获:报告变量自赋值 rules: - id: self-assignment patterns: - pattern: "$X = $X" message: 变量 $X 被赋值给自身,疑似笔误 languages: [python] severity: ERROR ​

污点模式是规则语法的进阶形态。它不再问「这一行长什么样」,而是问「脏数据能不能流到这里」。三件套如下:

# open_taint.yml —— semgrep 污点模式:request 参数流向 open rules: - id: flask-open-taint mode: taint languages: [python] severity: ERROR message: 用户可控参数未净化即进入 open,可能路径穿越 pattern-sources: - pattern: request.args.get(...) pattern-sinks: - pattern: open(...) pattern-sanitizers: - pattern: secure_filename(...) ​

在自建 Flask 项目上试跑:只要 request.args.get 的返回值经过任何赋值、拼接、传参到达 open,且中途没过 secure_filename,就会报 ERROR。把净化调用补上,告警消失——这条「补净化消警」的正反馈,正是污点模式教学价值所在。

四、拿开源项目跑官方规则集

官方规则注册表用 p/ 前缀引用,常用包:

# registry_scan.sh —— 对自建项目与开源副本跑官方规则集 semgrep scan --config p/owasp-top-ten --metrics=off ./myflask semgrep scan --config p/secrets --metrics=off ./myflask semgrep scan --config p/default --json --out=semgrep.json --metrics=off ./myflask ​

对开源项目(选一个许可证允许的仓库副本)或自己写的练手项目,按三步读结果:

  • 定位:规则 id 指向的文件与行号,先看代码再看 message。
  • 证据:命中的代码片段是否真是外部输入可控,向上追参数来源。
  • 置信:OWASP 类规则误报不低,一条告警只是「值得看」,不是「有漏洞」。

若在 CI 中使用,可以加 --error 让命中高级别规则时以非零码退出,形成门禁;研究场景则建议 --json 落盘,交给后续的分诊与证据链流程(第 11 章)。

五、AI 能力的官方口径

semgrep 平台侧的 AI 能力有三块,引用时务必区分「官方宣称」与「独立验证」:

  • AI 误报分诊:官方宣称可减少约八成的误报人工分诊工作量——这是官方口径,实际收益随语言与规则集差异很大,以官方文档与自己项目的抽样复核为准。
  • AI 修复建议:对确认的发现生成修复片段,采纳前必须走人工评审。
  • MCP 支持:semgrep 提供 MCP 接入能力,可以把扫描与分诊变成模型可调用的工具,与第 03 章《GhidraMCP实战》、第 05 章《REA聚合层》的工具编排思路同构。

分诊的定位要摆正:AI 能把「明显误报」压下去,让人的注意力集中在高价值告警上;但它不产出最终结论。结论永远来自证据链——第 11.1 节的四列模板会接住这里输出的每一条高置信告警。

注意:本节扫描对象限于自建项目与许可证允许的开源代码;对他人的闭源或在线系统进行未授权扫描不在本书范围内。

本节要点回顾

  • semgrep 规则三行起步:pattern、message、languages,加 id 与 severity 登记项。
  • 污点模式三件套 source、sink、sanitizer,把「长得像」升级为「流得到」。
  • 官方规则集用 p/ 前缀引用;读结果按定位、证据、置信三步走。
  • AI 分诊约八成的降幅是官方口径;分诊减负,不替你下结论。

模式匹配跑得快,但它看不见「数据跨过三个函数之后去了哪里」,也很难回答「同一类缺陷在仓库里还有多少变体」。这两个问题正是下一节 CodeQL 的主场——先把代码变成数据库,再用一条查询把整条污点路径捞出来。


作者与出处
原作者: 灏天文库
整理: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U