ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Deepsec Matcher 编写实战:从 setup 自动生成的声明式 Matcher 到手写 MatcherPlugin

Deepsec Matcher 编写实战:从 setup 自动生成的声明式 Matcher 到手写 MatcherPlugin 应用安全漏洞扫描人工智能AI Agent【免费下载链接】deepsecDeepsec is a security harness for finding vulnerabilities in your codebase powered by coding agents项目地址https://gitcode.com/gh_mirrors/deeps/deepsec点击查看免费下载Deepsec 的扫描覆盖能力由「matcher匹配器」驱动初始化阶段由 setup agent 自动生成严格受限的声明式 matcher 来填补扫描盲区而当规则需要负向条件、跨搜索或组织特定语义时则需要手写 TypeScriptMatcherPlugin。本文以 docs/writing-matchers.md 为骨架结合仓库源码packages/scanner/src/declarative-matcher.ts、packages/core/src/plugin.ts、packages/deepsec/src/setup/coverage.ts等深入讲解这两条路径从「保留还是编辑生成的 matcher」的取舍到「手写 matcher 的字段、噪音分级与注册方式」的完整实操读完你可以在自己的.deepsec/工作区里安全地新增、调优并贡献 matcher。从 setup coverage 开始初始化阶段如何决定是否需要自定义 matcher正常初始化流程已经内置了「是否需要自定义 matcher」的决策npx deepsec initsetup agent 会完成三件事盘点仓库的入口面ingress surfaces对仓库做只读分析产出结构化的 surface inventory。从packages/deepsec/src/setup/coverage.ts可以看到surface 被划分为http、rpc、queue、cron、cli、webhook、agent-tool、other等 kind并标记public/authenticated/internal/mixed/unknown暴露级别——这正是「哪些入口值得安全审查」的机器可读抽象。运行内置 matcher加载默认注册表createDefaultRegistry见 packages/scanner/src/matchers/index.ts对仓库做一次免费的全量扫描。应用确定性的覆盖策略对每个 surface 检查文件级与代表文件级覆盖率。只有存在具体缺口时例如某个未被覆盖的内部 RPC 注册表、队列消费者家族、或框架路由原语才生成 matcher 提案。被接受的提案会写入.deepsec/generated-matchers.ts作为严格的数据strict data存在并通过generatedMatchersPlugin加载。这一点在源码中有直接对应writeGeneratedMatcherspackages/deepsec/src/setup/generated-matchers.ts把 JSON 规格序列化进一个.ts文件文件内容只是compileDeclarativeMatchers(specs)的调用没有任何模型手写的执行代码。务必 review 并提交generated-matchers.ts。不要复制生成的 setup inventory 或 setup-state 文件——它们是可再生产物已被 gitignore。初始化阶段的整体位置可以对照 docs/architecture.md 的流水线图scaffold → install → link/model/Sandbox → INFO inventory → baseline scan → coverage policy → declarative matcher generation → final scan → processmatcher 生成是覆盖策略与付费 AI 处理之间的必经关卡。声明式 matcher 的安全契约模型只写数据不写代码生成的规格由compileDeclarativeMatchers编译模型写出的 TypeScript 永远不会被执行。编译入口在 packages/scanner/src/declarative-matcher.ts先用 Zod 严格解析.strict()拒绝未知字段再按规格构造正则与排除 glob最后返回一个普通MatcherPlugin。测试 packages/scanner/src/tests/declarative-matcher.test.ts 明确验证了「带match可执行字段的输入会被拒绝」以及「输入数据会被structuredClone脱离调用方后续修改不污染编译结果」。每个 spec 必须声明唯一的kebab-case slug、描述和噪音分级noise tier受限的相对文件 glob约束目录、文件名或扩展名可选的技术栈 / 哨兵文件门tech / sentinel-file gates有界正则且只允许i、m或im三种 flagallowedFlagsSchema z.enum([i, m, im])examples——每个被提案的 matcher 必须真实命中的示例该 matcher 声称要关闭的surface ID 列表closesSurfaceIds。校验拒绝清单源码级验证会拒绝以下全部情况具体规则都能在declarative-matcher.ts中找到实现类别被拒绝的内容源码依据未知字段schema 之外的任何可执行字段Zod.strict()遍历/兜底 glob../src/**、绝对路径、盘符路径、!/#前缀、**、**/*等无约束 globglobSafetyError重复 slug组内重复、与既有内置/插件 slug 冲突declarativeMatcherSpecsSchemaexistingSlugs检查空正则空字符串 sourceregexPatternSchema的z.string().min(1)反向引用 / 后顾\1、\kname、(?、(?!regexSafetyError指数回溯形状嵌套量词(a)、量化的多选(a\|aa)、多个通配重复.*...*regexSafetyError超大重复重复次数上限超过 1000regexSafetyError不触发的示例examples 必须被至少一个声明 pattern 命中superRefine对每个 example 逐一测试越界限制正则 500 字符、glob 240 字符、example 10000 字符、patterns 1–32 个、filePatterns 1–32 个、closesSurfaceIds 1–64 个、整套 specs ≤64 个各 schema 常量glob 的约束细节值得一提必须用正斜杠、必须相对仓库根、不允许../.遍历段、花括号组 ≤3、逗号备选 ≤16、星号 ≤12并且会跑一组广度探针README.md、src/index.ts、.env、deep/a/config.yaml——如果这些互不相关的文件全部命中说明 glob 太宽直接拒绝。这套规则的意图是setup agent 只写覆盖性 matcher不需要任何依赖引擎微妙回溯行为的正则特性。编译后的爆炸策略与可恢复的停止编译之后setup 会重新扫描并应用爆炸策略explosion policy。在evaluateCoverage中每个新 matcher 的命中文件数会被统计命中文件数 matcherMaximumFiles默认500——直接判为爆炸或命中文件数占非忽略源文件比例 matcherMaximumSourceRatio默认20%且仓库 ≥5 个文件时才启用比例门——同样判为爆炸。爆炸的 matcher 会从插件中移除其已持久化的候选candidates在再次尝试前被删除。每次调用 setup最多做两次生成/重扫尝试如果覆盖仍然失败则在任何付费 AI 处理开始前停止。这个停止是可恢复的停止时打印的 actions 指向已保存的提案与覆盖证据重新运行 setup 会再做两次全新的修复尝试。何时保留或编辑一个生成的 matcher保留它的条件其文件范围和正则描述的是一个稳定存在的仓库原语stable repository primitive且候选数量接近对应的入口点数量说明它命中了你真正想审查的入口而不是泛泛的噪音。编辑或删除它当出现以下任一情况glob 跟随的是生成代码generated code而非真实的入口家族正则命中的是某个偶然的标识符incidental identifier而不是框架形态本身examples 不能代表仓库的真实语法它声称关闭某个 surface实际却无法触及该 surface一个手写 matcher 能以更精确的方式表达同一条件。编辑完数据后运行两条命令做验证pnpm deepsec scan --matchers slug pnpm deepsec setup第一条是聚焦的定点检查spot-check第二条用完整的覆盖评估来对账。--matchers过滤在 packages/deepsec/src/commands/scan.ts 中解析逗号分隔、按 slug 过滤扫描结束后还会输出Matchers that fired命中表、Top files by candidate count和低覆盖警告——低覆盖警告甚至会直接提示你去看 docs/writing-matchers.md 编写自定义 matcher。何时该手写 MatcherPlugin声明式 matcher 被刻意限制为安全的正则扫描。当规则需要以下能力时就应该写 TypeScriptMatcherPlugin负向条件例如「没有任何 auth helper 的路由声明」——纯正则只能表达「命中了什么」无法表达「缺少什么」对同一文件的多次相关搜索需要把多个模式的命中结果组合判断语法感知的预处理或上下文窗口需要读取文件内容做结构化分析如排除 test 文件、跳过_internal/目录组织特定的语义这些规则应当以代码形式被 review而不是藏在数据里值得向上游贡献的可复用公共框架 / CWE 规则。另外当一次 revalidate重新验证确认的 true positive 暴露出一个稳定的兄弟模式sibling pattern而 setup 的入口点覆盖并没有建模它时也值得考虑手写 matcher。一个现实中的负向条件范例是 samples/webapp/matchers/webapp-route-no-rate-limit.ts它先排除测试文件、_internal/与 webhook 路径再检查文件中是否出现withRateLimit(、rateLimiter.check(、ratelimit.limit(等保护性调用若全无且存在export ... GET/POST/...导出才产出候选——这是纯声明式 spec 无法表达的「缺失检测」。手写 matcher 的工作区布局把更丰富的 matcher 放在生成的插件旁边.deepsec/ ├── deepsec.config.ts ├── generated-matchers.ts └── matchers/ ├── my-route-no-auth.ts └── my-internal-rpc.ts通过一个叠加式additive内联插件注册它们import { defineConfig, type DeepsecPlugin } from deepsec/config; import { generatedMatchersPlugin } from ./generated-matchers.js; import { myRouteNoAuth } from ./matchers/my-route-no-auth.js; import { myInternalRpc } from ./matchers/my-internal-rpc.js; const projectMatchers: DeepsecPlugin { name: my-app-matchers, matchers: [myRouteNoAuth, myInternalRpc], }; export default defineConfig({ ai: { mode: gateway, provider: vercel }, projects: [{ id: my-app, root: .. }], plugins: [generatedMatchersPlugin, projectMatchers], });要点slug 必须全局唯一。一次性生成器one-shot generator会拒绝与内置 matcher、插件 matcher 以及同批响应内部的 slug 冲突见compileDeclarativeMatchers的existingSlugs去重逻辑与 packages/scanner/src/tests/declarative-matcher.test.ts 的冲突测试。手写的变体请使用独立的 slug而不是依赖注册顺序去覆盖内置规则。插件系统是叠加的matchers、notifiers、agents都是 additive多个插件的贡献会全部注册ownership、people、executor才是后写覆盖。插件接口定义见 packages/core/src/plugin.ts。想直观地看到一个「被长期维护过的扫描工作区」长什么样可阅读 samples/webapp/README.md 与它的 deepsec.config.ts——它在配置里内联读取INFO.md、注册了两个自定义 matcher 并通过priorityPaths声明了重点审查目录。Matcher 形态详解MatcherPlugin 与 regexMatcher一个完整的手写 matcherimport { regexMatcher, type MatcherPlugin } from deepsec/config; export const myInternalRpc: MatcherPlugin { slug: my-internal-rpc, description: Internal RPC entry points, noiseTier: normal, filePatterns: [src/rpc/**/*.ts], examples: [registerRpc(users.get, handler)], match(content) { return regexMatcher( my-internal-rpc, [{ regex: /registerRpc\s*\(/g, label: RPC registration }], content, ); }, };MatcherPlugin的完整字段见 packages/core/src/plugin.ts字段类型说明slugstring全局唯一的 kebab-case 标识会写入候选的vulnSlugdescriptionstring人类可读的描述noiseTierprecise \| normal \| noisy噪音分级用于排序处理优先级filePatternsstring[]该 matcher 作用的文件 globrequires?MatcherGate可选门控tech技术栈 tag、sentinelFiles哨兵文件 glob、sentinelContains对命中文件内容做更深检查examples?string[]内联测试用例每个字符串必须产生 ≥1 个候选match(content, filePath) CandidateMatch[]核心匹配逻辑门控MatcherGate让 matcher 只在合适的仓库里激活requires门在每次扫描开始时对项目根解析一次不是每个文件一次提供两层控制tech匹配detectTech()归一化后的技术栈 tag如laravel、nextjs、django、rails任意命中即激活。这是首选快捷方式。sentinelFiles 可选sentinelContains当detectTech还不认识你的技术栈、或需要比一个 tag 更精细的判断时使用例如「只有装了 Livewire 的 Laravel 项目」。glob 在每次扫描时对项目根求值一次sentinelContains接收命中的相对路径与文件内容做谓词判断。内置 matcher 大量使用这一机制。例如 js-express-route.ts 声明requires: { tech: [express] }并在文件级排除 test/spec 与node_modules避免在恰好出现app.get(...)的随机 Node 脚本上误触发。扫描输出里的dormantmatcher 就是这些被门控按下的内置规则。regexMatcher逐行扫描、带回溯上下文regexMatcher是官方辅助函数对每个 pattern 逐行测试命中时记录1-based 行号并截取命中行前 2 行、后 3 行作为snippet上下文同一文件同一 pattern 只产出一个CandidateMatchvulnSluglineNumberssnippetmatchedPattern。多 pattern 时每个 pattern 独立产出候选这正是声明式 matcher 编译后的运行时行为。内联 examples 是可执行文档examples不是运行时逻辑而是开发期契约packages/scanner/src/tests/matcher-examples.test.ts 会自动遍历注册表中所有带 examples 的 matcher为每个示例生成一个测试用例断言该 matcher 至少产出 1 个候选。因此为 matcher 加一个 example 只需要在examples数组里加一行无需任何测试接线好的实践是覆盖每一个子 pattern 的典型语法变体不同动词、大小写、标识符、空白任何子 pattern 的笔误都会让 CI 失败示例字符串同时充当该 matcher 想要捕获什么的可读文档。噪音分级Tier适用场景precise匹配到的语法本身就是一个强漏洞信号例如原始 SQL 拼接、硬编码密钥normal模式选出值得审查的候选由 AI 进一步消歧noisy一个严格有界的入口点家族里的每个文件都值得审查例如 Express 的每个路由注册filePatterns要尽量收窄。避免仓库级的大噪音 glob——内置的 Express matcher 已经用noisy表示「每个路由都值得看一眼」如果你的自定义规则也是这种语义请确保 glob 严格限定在入口家族目录内。用 coding agent 辅助手写 matcher 的工作流让一个编码 agent 完成一次 matcher 编写时给它以下阅读清单.deepsec/data/id/setup/surface-inventory.json—— 目标 surface 的结构化清单.deepsec/generated-matchers.ts—— 已覆盖的缺口避免重复.deepsec/data/id/files/—— 候选数量与已 revalidate 的 findings判断真实命中率.deepsec/node_modules/deepsec/dist/config.d.ts——MatcherPlugin类型定义安装后工作区内的类型声明仓库源码对应 packages/core/src/plugin.ts.deepsec/node_modules/deepsec/dist/samples/webapp/—— 更丰富的参考示例仓库中的对应源码在 samples/webapp/。要求 agent解释它发现的未被覆盖的 surface提出一个有界的 matcher补上 examples在不移除generatedMatchersPlugin的前提下注册新插件跑一次聚焦扫描pnpm deepsec scan --matchers new-slug打开几个候选文件核对命中质量微调 matcher 后跑全量扫描与 setup 对账。需要提交的是deepsec.config.ts、generated-matchers.ts和matchers/不要提交生成的data/id/setup/证据gitignored、可再生。把可复用的 matcher 贡献进内置注册表如果这个形态属于某个公共框架或广泛适用的弱点类别应该把它加进 deepsec 的内置 matcher 注册表而不是保留一份组织专属副本。内置注册表由 packages/scanner/src/matchers/index.ts 的createDefaultRegistry()组装按生态分组注册了覆盖 Express、Fastify、NestJS、Django、Flask、Rails、Gin、Spring、.NET、Terraform、Next.js 等框架的路由/控制器/handler matcher以及跨生态的原始 SQL 逃生舱 matcherjsSqlRawMatcher、pySqlRawMatcher、jvmSqlRawMatcher等。贡献时遵循仓库根目录的 CONTRIBUTING.md注意附带具有代表性的 examples新 matcher 会自动进入matcher-examples.test.ts的测试矩阵technology / sentinel 门控尽量收窄让 matcher 在无关仓库上保持 dormant保持 kebab-case slug 全局唯一。内置 matcher 的写法是很好的学习范本阅读 packages/scanner/src/matchers/js-express-route.ts 的「wide-net tech 门控」风格以及 samples/webapp/matchers/webapp-route-no-rate-limit.ts 的「负向 排除路径」风格几乎涵盖了手写 matcher 的两大类典型模式。结语与延伸阅读matcher 体系是 Deepsec 在「免费的正则扫描」与「付费的 AI 分析」之间的桥梁声明式 matcher 以数据形式安全地承载 setup 自动发现的覆盖缺口手写MatcherPlugin则以代码形式表达更精细的负向与组织特定规则。判断何时使用哪种形态核心准则是——能否用一条受约束的正则安全表达能就用生成的声明式 spec不能就手写插件并配好 examples。与本文配套的仓库文档docs/architecture.md —— setup、scan、process、revalidate 流水线与插件架构全貌docs/configuration.md ——deepsec.config.ts字段、matcher 过滤matchers: { only, exclude }与插件顺序语义docs/getting-started.md —— 从npx deepsec init开始的一次性初始化与断点恢复。赞分享应用安全漏洞扫描人工智能AI Agent【免费下载链接】deepsecDeepsec is a security harness for finding vulnerabilities in your codebase powered by coding agents项目地址https://gitcode.com/gh_mirrors/deeps/deepsec点击查看免费下载相关推荐从零编写自己的安全规则Deepsec 自定义 Matcher 插件开发实战从零编写自己的安全规则Deepsec 自定义 Matcher 插件开发实战 Deepsec 是一款由 AI 编码智能体驱动的安全漏洞扫描工具能在你的代码库中应用安全漏洞扫描人工智能AI AgentAI 自动补全扫描盲区Deepsec 声明式 Matcher 生成与安全校验机制深度解析AI 自动补全扫描盲区Deepsec 声明式 Matcher 生成与安全校验机制深度解析 Deepsec 是一款由编码智能体驱动的漏洞扫描器security应用安全漏洞扫描人工智能AI AgentOpenCreator视频翻译配音一键出片的本地开源AI工作台OpenCreator视频翻译配音一键出片的本地开源AI工作台 OpenCreator原名 KrillinAI是一个面向创作者的开源 AI 工作台以 C人工智能AI 应用AI AgentAI 技能媒体生成音视频桌面应用上一篇3个简单步骤让Mac与Android设备秒传文件NearDrop完全攻略下一篇Cataclysm-DDA Flatpak 构建指南从清单解析、自定义构建到本地安装分发创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表