拓冰建站拓冰建站
首页 / 资讯中心 / 正文

使用 Fabric 的 write_semgrep_rule 模式编写精准通用的 Semgrep 静态分析规则

使用 Fabric 的 write_semgrep_rule 模式编写精准通用的 Semgrep 静态分析规则【免费下载链接】FabricFabric is an open-source framework for augmenting humans using AI. It provides a modular system for solving specific problems using a crowdsourced set of AI prompts that can be used anywhere.项目地址: https://gitcode.com/GitHub_Trending/fa/Fabric本指南以 Fabric 仓库中的write_semgrep_rule模式system.md为核心系统讲解如何让 AI 以安全专家身份根据一条安全公告或一段存在问题的代码输入自动产出一条可运行、可泛化、不过拟合的 Semgrep YAML 规则。你将掌握 Semgrep 规则的完整 YAML 语法必需字段、可选字段、全部操作符、元变量机制看懂真实漏洞如 langchain 任意代码执行如何被翻译成检测规则并了解该模式在 Fabric 中的加载与调用方式。模式定位从漏洞情报到可执行规则的自动化write_semgrep_rule是 Fabric 模式库中面向安全工程场景的模式之一它与同目录下的create_sigma_rulesSIEM 检测规则、write_nuclei_template_ruleNuclei 模板等模式共同构成从安全公告/漏洞描述到可落地检测的 AI 辅助工作流。该模式的 system.md 开篇即定义了其身份与目标身份IDENTITY你是一名精通编写 Semgrep 规则的专家输出要求OUTPUT SECTIONS为提供的输入编写一条能够匹配该输入的 Semgrep 规则上下文CONTEXT FOR CONSIDERATIONsystem.md 内嵌了完整的 Semgrep 规则编写语法速查手册YAML Schema、语言支持表、操作符说明、元变量匹配规则、真实漏洞规则示例用于在推理时教会模型如何写出高质量规则输入INPUT用户提供具体的漏洞描述或代码片段。模式的使用方式与 Fabric 其他模式一致把待分析的漏洞信息通过管道喂给 Fabric并指定该模式名。模式文件位于 data/patterns/write_semgrep_rule/其中user.md预留为输入模板system.md提供专家系统提示词。从源码看Fabric 的模式加载机制位于 internal/tools/patterns_loader.go默认从data/patterns目录读取模式模式的读取与打印由 internal/plugins/db/fsdb/patterns.go 中的PatternsEntity实现如PrintPattern、GetNames运行fabric --list patterns可查看当前已加载的全部模式清单。Semgrep 规则的基本骨架顶层必需字段任何一条 Semgrep 规则都是 YAML 文件中的rules:列表元素。以下四个字段必须出现在规则顶层字段类型说明idstring唯一、有描述性的标识符例如no-unused-variablemessagestring说明 Semgrep 为什么匹配该模式以及如何修复的消息文本severitystring取值为INFO低危、WARNING中危或ERROR高危指明规则潜在问题的严重程度Semgrep Supply Chain 规则除外其严重性由 CVE 决定languagesarray规则作用的目标语言取值见下方语言支持表在匹配表达式字段中五选一必填pattern、patterns、pattern-either、pattern-regex四者之一其中pattern直接写表达式即可加上pattern-regex也只需其中一个即可满足规则完整性要求。语言扩展名与 languages 键值对照表语言扩展名languages键值Apex仅 Semgrep Pro Engine.clsapexBash.bash、.shbash、shC.ccCairo.cairocairoClojure.clj、.cljs、.cljc、.ednclojureC.cc、.cppcpp、cC#.cscsharp、c#Dart.dartdartDockerfile.dockerfile、.Dockerfiledockerfile、dockerElixir.ex、.exsex、elixirGeneric通用模式—genericGo.gogo、golangHTML.htm、.htmlhtmlJava.javajavaJavaScript.js、.jsxjs、javascriptJSON.json、.ipynbjsonJsonnet.jsonnet、.libsonnetjsonnetJSX.js、.jsxjs、javascriptJulia.jljuliaKotlin.kt、.kts、.ktmkt、kotlinLisp.lisp、.cl、.ellispLua.lualuaOCaml.ml、.mliocamlPHP.php、.tplphpPython.py、.pyipython、python2、python3、pyR.r、.RrRuby.rbrubyRust.rsrustScala.scalascalaScheme.scm、.ssschemeSolidity.solsolidity、solSwift.swiftswiftTerraform.tf、.hcltf、hcl、terraformTypeScript.ts、.tsxts、typescriptYAML.yml、.yamlyamlXML.xmlxml不同语言在 Semgrep OSS Engine 与 Semgrep Pro Engine 下的成熟度maturity level不同编写规则前可查阅官方支持语言文档确认目标语言的匹配能力。顶层可选字段让规则更完整、更可控除必需字段外system.md 还列举了以下顶层可选字段字段类型说明optionsobject启用/禁用某些匹配特性的选项对象详见后文 options 表fixobject简单的搜索-替换自动修复功能metadataobject任意用户数据可附加到规则而不影响匹配行为min-versionstring与规则兼容的最低 Semgrep 版本max-versionstring与规则兼容的最高 Semgrep 版本pathsobject运行规则时要包含或排除的路径以下嵌套字段必须位于patterns或pattern-either之下字段类型说明pattern-insidestring仅保留位于该模式内部的匹配结果metavariable-regexmap用 Python re 兼容正则搜索元变量正则匹配为非锚定metavariable-patternmap用模式公式匹配元变量metavariable-comparisonmap将元变量与基本 Python 表达式比较pattern-notstring逻辑非——移除匹配该表达式的发现pattern-not-insidestring保留不位于该模式内部的发现pattern-not-regexstring用 PCRE 兼容模式过滤结果多行模式操作符详解Semgrep 规则的核心语法Semgrep 的匹配能力由一组操作符operators组合而成system.md 对每个操作符都给出了明确的语义说明。pattern最基础的代码匹配pattern操作符查找匹配其表达式的代码既可以是$X $X这类基础表达式也可以是hashlib.md5(...)这类不受欢迎的函数调用。...省略号用于匹配任意参数或任意中间语句。patterns逻辑 AND 组合patterns操作符对多个子模式执行逻辑与AND适合把多个必须同时成立的条件串联起来。patterns 的求值策略重要子模式的声明顺序不影响最终结果patterns总是按固定顺序求值先求所有正向模式包括pattern-inside、pattern、pattern-regex、pattern-either把每个模式的匹配区间互相求交集得到一组携带元变量绑定的正向区间再求所有负向模式pattern-not-inside、pattern-not、pattern-not-regex产生负向区间用于过滤正向区间得到严格子集再求所有条件操作符metavariable-regex、metavariable-pattern、metavariable-comparison只能检查步骤 1 中绑定、且通过了步骤 2 过滤的元变量负向模式绑定的元变量在此不可用最后应用focus-metavariable把每个正向区间与目标元变量的区间求交集且只能聚焦于正向模式绑定的元变量。pattern-either逻辑 OR 组合pattern-either对多个子模式执行逻辑或OR任一成立即匹配。典型场景是同一类不安全函数的不同变体。例如同时检测hashlib.md5与hashlib.sha1两个不安全的哈希函数调用。pattern-regexPCRE 正则匹配pattern-regex在文件中搜索匹配给定 PCRE 模式的子串适合把已有的正则代码搜索迁移到 Semgrep。PCRE 是功能完整的正则库与 Perl 及 Python、JavaScript、Go、Ruby、Java 的正则库广泛兼容。模式以多行模式编译即^和$除匹配输入首尾外还会匹配每行的行首行尾。注意事项PCRE 对 Unicode 字符属性支持有限例如\p{Egyptian_Hieroglyphs}可用但\p{Bidi_Control}不可用YAML 中单引号与双引号行为不同使用pattern-regex时若涉及反斜杠\建议优先用单引号可以通过命名捕获组把正则的某段绑定到元变量捕获组名必须是合法的元变量名。pattern-not-regex正则排除pattern-not-regex用 PCRE 正则多行模式过滤结果语法与pattern-regex相同。它最适合与纯正则规则组合免去编写负向先行断言negative lookahead的麻烦也可以与普通 pattern 子句搭配使用。该操作符会过滤掉与给定正则有任意重叠的发现——例如用pattern-regex检测到Foo1.1.1、Foo-Bar3.0.8、Bar-Foo3.0.8时可用pattern-not-regex剔除不需要的结果。focus-metavariable聚焦元变量匹配区域focus-metavariable把匹配缩放到单个或一组元变量匹配的代码区域。考虑以下场景pattern: | def $FUNC(..., $ARG : bad, ...): ...它能匹配到函数定义但如果函数体有上百行整个定义都会被匹配且在使用 Semgrep Cloud Platform 时只要函数定义有任何改动已被 triage 的发现又会以新发现重新出现。此时用focus-metavariable: $ARG只聚焦参数声明区域即可。需要特别区分focus-metavariable: $ARG不等于pattern: $ARG。pattern: $ARG会匹配参数x的所有使用位置因为在该上下文中$ARG只匹配表达式甚至不会匹配形参声明而focus-metavariable: $X本身不做任何匹配只是把匹配聚焦到其他模式已经绑定给$X的代码上。多焦点交集语义在一个patterns块中列出多个focus-metavariable键时只匹配所有焦点代码的重叠区域patterns: - pattern: foo($X, ..., $Y) - focus-metavariable: - $X - $Y若需要并集语义无论元变量在代码中的位置如何都匹配则应使用多个focus-metavariable键的并集文档所述写法。metavariable-regex按值过滤元变量metavariable-regex用 PCRE 正则匹配元变量的取值需要metavariable和regex两个键可与其他操作符组合。正则匹配是非锚定的需要锚定时用\A字符串开头与\Z字符串结尾。例如判断元变量是否为std::前缀的命名空间名时用regex: ^std::是非锚定的而\Astd::\Z是锚定的两者结果可能完全不同。用metavariable-regex搜索字符串字面量时正则中要包含引号本身。字符串匹配功能也可用于搜索字符串字面量。metavariable-pattern用模式公式匹配元变量metavariable-pattern用模式公式匹配元变量适合基于元变量取值做更细粒度的过滤。它需要metavariable键且pattern、patterns、pattern-either、pattern-regex四者恰好取其一支持嵌套与组合甚至可以嵌套在另一个metavariable-pattern内部。两个典型用法在patterns的 AND 组合中以pattern-not开头过滤不满足条件的匹配此时存在一个隐式的pattern: ...匹配元变量的内容与pattern-either组合对同一元变量按不同标准分别判定。当元变量绑定到字符串时还可以通过language键指定目标语言把该字符串当作代码来匹配——例如在 HTML 中匹配内嵌的 JavaScript 代码。注意metavariable-pattern的判定要求元变量绑定到表达式、语句或语句列表。若元变量绑定的是函数实参列表、类型或模式判定恒为 false。metavariable-comparison数值比较metavariable-comparison把元变量与基本 Python 比较表达式做比较适合基于数值过滤结果。它需要metavariable和comparison两个键。例如patterns: - pattern: set_port($ARG) - metavariable-comparison: metavariable: $ARG comparison: $ARG 1024 and $ARG 65535上述规则能匹配set_port(8080)而不会匹配set_port(80)或set_port(443)。比较表达式支持布尔、字符串、整数、浮点字面量布尔操作符not、or、and算术操作符、-、*、/、%比较操作符、!、、、、函数int()字符串转整数、str()数字转字符串、today()当前日期返回 epoch 秒的浮点数、strptime()把yyyy-mm-dd格式字符串转 epoch 秒浮点数列表配合in/not in中缀操作符字符串配合in/not in做子串包含判断函数re.match()不含可选 flags 参数。元变量$MVAR在比较表达式中的求值规则若$MVAR绑定到字面量则该字面量即为$MVAR的值若$MVAR绑定到代码中的常量变量且常量传播默认开启可用则该常量即为$MVAR的值否则代码原样保留未求值状态可用str($MVAR)得到其字符串表示——例如$MVAR绑定到代码变量x时str($MVAR)求值为字符串字面量x。遗留键说明旧版base: int与strip: bool键分别用于指定元变量值的整数进制、以及去除元变量值两端的引号、、。现在可以用int()函数替代如int($ARG) 0o600八进制权限判断或int($ARG) 2147483647用strip的场景对应2147483648这类带引号字符串的数值比较strip: true后可检测2147483648而不检测2147483646。pattern-not 与 pattern-inside / pattern-not-inside排除与上下文约束pattern-not是pattern的反操作找出不匹配其表达式的代码常用于消除常见误报pattern-inside只保留位于其表达式内部的发现适合限定在函数内 / 在 if 块内等上下文pattern-not-inside只保留不在其表达式内部的发现是pattern-inside的反操作特别适合查找缺少对应清理动作的代码如disconnect、close、shutdown或排查没有缓解措施包围的问题代码。例如文件被打开但从未关闭可能导致资源耗尽的规则查找open(...)模式且其后没有close()调用。$F元变量保证open与close使用同一变量名省略号...允许open带任意参数、中间有任意语句序列。规则不关心open如何被调用、close之前发生了什么——只需确保close被调用。元变量Metavariable匹配机制元变量在不同父操作符下的匹配行为不同行为在所有子操作符pattern、pattern-not、pattern-regex、pattern-inside、pattern-not-inside间保持一致逻辑 ANDpatterns中元变量的值必须跨子模式完全相同。例如下面的规则中$X在pattern-inside与pattern中必须一致rules: - id: function-args-to-open patterns: - pattern-inside: | def $F($X): ... - pattern: open($X) message: Function argument passed to open() builtin languages: [python] severity: ERROR它匹配def foo(path): open(path)但不匹配def foo(path): open(something_else)。逻辑 ORpattern-either中元变量匹配不参与OR 判定。例如rules: - id: insecure-function-call pattern-either: - pattern: insecure_func1($X) - pattern: insecure_func2($X) message: Insecure function use languages: [python] severity: ERROR上面的规则对insecure_func1(something)、insecure_func2(something)、insecure_func1(something); insecure_func2(something_else)均匹配。复杂逻辑中当父节点是逻辑 AND 时元变量一致性仍会约束后续的 OR 分支。例如patterns: - pattern-inside: | def $F($X): ... - pattern-either: - pattern: bar($X) - pattern: baz($X)它匹配def foo(something): bar(something)与def foo(something): baz(something)但不匹配def foo(something): bar(something_else)。options微调匹配引擎行为options对象可启用、禁用或修改以下匹配特性system.md 列出了默认值选项默认值说明ac_matchingtrue模结合性与交换性匹配把布尔 AND/OR 视为可结合把位运算 AND/OR/XOR 视为既可结合又可交换attr_exprtrue表达式模式如f($X)也匹配属性如f(a)commutative_boolopfalse即使语义上不准确也把布尔 AND/OR 视为可交换constant_propagationtrue常量传播含过程内流敏感的常量传播generic_comment_stylenone通用模式下的注释语法可选c传统 C 风格/* ... */、cpp// ...或/* ... */、shell# ...。默认通用模式不识别任何注释Semgrep 0.96 起支持generic_ellipsis_max_span10通用模式下省略号...最多跨越的换行数即匹配覆盖的最大行数减一。默认 10出于性能考虑可谨慎调大写... ...等效于 20 而不改设置设为 0 适用于行导向语言如 INI 或键值对强制匹配不延伸到下一行Semgrep 0.96 起支持taint_assume_safe_functionsfalse污点分析实验选项假定函数调用不会把污点从实参传播到输出否则 Semgrep 默认假定函数可能传播污点taint_assume_safe_indexesfalse污点分析选项假定数组访问即使索引被污染也是安全的。推荐高信号high-signal规则开启、审计规则关闭vardef_assigntrue赋值模式如$X $E匹配变量声明如var x 1;xml_attrs_implicit_ellipsistrueXML/JSX/HTML 元素模式对属性隐式使用省略号如div /匹配div foo1完整选项列表可查阅 Semgrep 匹配引擎配置模块上表未列出的选项均视为实验性可能随时变更或移除。fix、metadata、版本约束与 categoryfix自动修复顶层fix键可为每个匹配建议一个简单的自动修复。配合semgrep --autofix运行时会把修改应用到文件rules: - id: use-dict-get patterns: - pattern: $DICT[$KEY] fix: $DICT.get($KEY) message: Use .get() method to avoid a KeyNotFound error languages: [python] severity: ERRORmetadata附加元数据metadata键提供规则的补充信息如相关 CWE、可能性、OWASP 分类等rules: - id: eqeq-is-bad patterns: - [...] message: useless comparison operation $X $X or $X ! $X metadata: cve: CVE-2077-1234 discovered-by: Ikwa Lequale使用semgrep --json运行时metadata 也会出现在输出中。category: security的规则有额外的元数据要求。min-version 与 max-version版本兼容约束每条规则可指定min-version和max-version限制其适用的 Semgrep 版本范围。版本不满足约束时规则会被跳过不会导致致命错误。典型用途rules: - id: bad-goflags # earlier semgrep versions cant parse the pattern min-version: 1.31.0 pattern: | ENV ... GOFLAGS-tagsdynamic -buildvcsfalse ... languages: [dockerfile] message: We should not use these flags severity: WARNING另一个常见场景是新旧双版本规则发布新规则依赖新特性、性能更好如注释10x faster than v1!旧规则用max-version: 1.72.999限定、新规则用min-version: 1.73.0限定确保同一环境只加载其中一条。该特性自 Semgrep 1.38.0 起可用主要面向发布依赖新特性的规则而不在老版本 Semgrep 中报错。category规则分类category为规则使用者提供分类信息如best-practice、correctness、maintainability。paths路径包含与排除排除规则用paths.exclude忽略特定文件上的规则路径相对于被扫描项目的根目录rules: - id: eqeq-is-bad pattern: $X $X paths: exclude: - *.jinja2 - *_test.go - project/tests - project/static/*.js当以semgrep -f rule.yaml project/运行时以下文件不会返回结果任何.jinja2扩展名的文件名称以_test.go结尾的文件如project/backend/server_test.goproject/tests及其子目录内的任何文件匹配project/static/*.jsglob 的文件。glob 语法来自 Python 的 wcmatch用于匹配给定文件及其所有父目录。包含规则反之用paths.include只对特定文件运行规则rules: - id: eqeq-is-bad pattern: $X $X paths: include: - *_test.go - project/server - project/schemata - project/static/*.js - tests/**/*.js此时只对*_test.go结尾的文件、project/server与project/schemata及其子目录、匹配project/static/*.js的文件、tests目录下任意深度的.js文件返回结果。如果正在为规则编写测试务必把测试文件或目录也加入 include 路径。混合规则同时使用 include 与 exclude 时exclude 优先。例如 includeproject/schemata且 exclude*_internal.py时project/schemata/scan.py返回结果而project/schemata/scan_internal.py不返回。综合实战一条完整的高级规则system.md 的其他示例部分给出了一条综合运用多种操作符的规则——检测无用的比较操作rules: - id: eqeq-is-bad patterns: - pattern-not-inside: | def __eq__(...): ... - pattern-not-inside: assert(...) - pattern-not-inside: assertTrue(...) - pattern-not-inside: assertFalse(...) - pattern-either: - pattern: $X $X - pattern: $X ! $X - patterns: - pattern-inside: | def __init__(...): ... - pattern: self.$X self.$X - pattern-not: 1 1 message: useless comparison operation $X $X or $X ! $X该规则同时运用了pattern-either、patterns、pattern、pattern-inside来细致地区分不同场景并用pattern-not-inside与pattern-not对被豁免的无用比较如__eq__重载内部、断言内部、1 1做白名单排除。它是学习操作符组合的最佳范本。从真实漏洞到 Semgrep 规则langchain 案例剖析system.md 内置了两个真实漏洞的规则示例展示了从 GitHub Advisory 漏洞描述到检测规则的完整翻译过程也演示了模式要求的输出可泛化规则的粒度。案例一PALChain 任意代码执行CVE-2023-36258漏洞背景langchainpip 包受影响版本 0.0.247修复版本0.0.247的 PALChain 在 python exec 方法中存在任意代码执行问题CVSS 3.1 评分 9.8CriticalAV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H。对应规则r2c-internal-project-depends-on: depends-on-either: - namespace: pypi package: langchain version: 0.0.236 languages: - python severity: ERROR patterns: - pattern-either: - patterns: - pattern-either: - pattern-inside: | $PAL langchain.chains.PALChain.from_math_prompt(...) ... - pattern-inside: | $PAL langchain.chains.PALChain.from_colored_object_prompt(...) ... - pattern: $PAL.run(...) - patterns: - pattern-either: - pattern: langchain.chains.PALChain.from_colored_object_prompt(...).run(...) - pattern: langchain.chains.PALChain.from_math_prompt(...).run(...)该规则先用depends-on-either约束依赖版本再用pattern-either覆盖先构造 PALChain 对象再调用.run()与链式直接.run()两类调用形态且用$PAL元变量保证构造与执行是同一个对象。案例二load_prompt 任意代码执行CVE-2023-36281漏洞背景langchain v.0.0.171 起攻击者可通过向load_prompt参数传入恶意 JSON 文件实现远程任意代码执行受影响版本 0.0.312CWE-94代码注入。对应规则r2c-internal-project-depends-on: depends-on-either: - namespace: pypi package: langchain version: 0.0.312 languages: - python severity: ERROR patterns: - metavariable-regex: metavariable: $PACKAGE regex: (langchain) - pattern-inside: | import $PACKAGE ... - pattern: langchain.prompts.load_prompt(...)这里展示了metavariable-regex与pattern-inside的组合先确认导入了 langchain 包再检测危险调用点langchain.prompts.load_prompt(...)。输出要求写通用规则不做过拟合system.md 的最后一部分OUTPUT INSTRUCTIONS对模型输出做了三条硬性约束这也是使用该模式时对结果的验收标准输出一条正确的 Semgrep 规则像示例那样能捕获问题的任何通用实例而不仅是输入中的特定实例不要过拟合输入中的具体示例规则要覆盖一般情况只输出规则本体YAML 代码块不附带警告或说明文字。以案例二为例如果输入只给了langchain.prompts.load_prompt(p)这一处调用合格的输出仍应通过元变量、pattern-inside等机制覆盖任意导入方式 任意调用参数的一般形态而不是把具体变量名硬编码进规则。在 Fabric 中使用该模式的工作流结合 internal/tools/patterns_loader.go 与 internal/plugins/db/fsdb/patterns.go 的实现可以梳理出该模式在 Fabric 中的完整生命周期加载PatternsLoader默认从data/patterns目录读取模式DefaultPatternsGitRepoFolder通过PopulateDB从远程仓库拉取并落盘createUniquePatternsFile会生成unique_patterns.txt供--list patterns使用调用运行时把漏洞描述/公告文本通过管道传给fabric并指定--pattern write_semgrep_rule模式目录下的system.md会被PatternsEntity读取并注入到提示词上下文产出AI 依据 system.md 内嵌的语法速查与示例输出一条可直接保存为.yaml的通用 Semgrep 规则验证将产出规则与本仓库其他安全检测模式如 create_sigma_rules 的 SIEM 检测规则类比可知安全检测规则类模式强调可落地、可运行、结构规范Semgrep 规则产出后建议在 Semgrep Playground 或本地semgrep --config rule.yaml验证后再合入规则库。小结write_semgrep_rule模式把Semgrep 规则专家的系统提示词、完整的 YAML 语法速查、语言支持表、操作符语义、元变量匹配机制和两个真实漏洞规则范本固化在 system.md 中。掌握本文梳理的字段体系与操作符组合方式patterns的固定四步求值顺序、pattern-either的 OR 语义、focus-metavariable与pattern: $X的本质区别、metavariable-comparison的求值规则等你就能把任意一条漏洞情报快速转化为可扫描、可修复、可版本化管理的通用 Semgrep 检测规则让 AI 辅助的安全规则生产流程真正落地。【免费下载链接】FabricFabric is an open-source framework for augmenting humans using AI. It provides a modular system for solving specific problems using a crowdsourced set of AI prompts that can be used anywhere.项目地址: https://gitcode.com/GitHub_Trending/fa/Fabric创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门