资讯动态

构建上下文而非裁决漏洞:Audit Context Building 评估规范与边界纪律全解析

发布时间:2026/10/9 2:05:13 来源:尧图企业网站定制
AI 技能AI 插件应用安全网络安全AI 评测【免费下载链接】skillsTrail of Bits Claude Code skills for security research, vulnerability detection, and audit workflows项目地址https://gitcode.com/gh_mirrors/skills8/skills点击查看免费下载本篇文章聚焦 Trail of Bits skills 仓库中audit-context-building插件评估体系的一份核心判分文档——stays-in-context-building.md。这份 LLM 型 grader 定义了一条关键纪律上下文构建阶段只负责记录代码的结构、不变量与假设绝不负责裁决它们的危害性。读完本文你将理解这套通过/失败判据的完整语义、机制命名与漏洞裁决之间的精确分界线并借助continuity-across-calls评估案例的 C 代码、代理职责说明与工作流实现掌握如何在真实审计场景中记录结构事实、把裁决留给下一阶段。这份评估文档在技能体系中的定位audit-context-building插件的核心定位是在任何人开始找漏洞之前先把代码读懂——每个函数假设了什么、承诺了什么、依赖了什么。正如其技能说明 SKILL.md 开头所写Build understanding, not verdicts. This runs before anyone hunts for bugs, and feeds that work.构建理解而非裁决它在狩猎之前运行并为狩猎供料。为了验证这个行为是否真的发生插件维护了一套评估evals体系。以continuity-across-calls为例其目录结构为case.yaml——定义评估场景、执行提示词、运行次数与预期结果fixture/——被测代码固件proto.c 与 proto.hgraders/——判分器集合其中regex 型grader 做机械性检查llm 型grader 做语义判定。本文的主角 stays-in-context-building.md 就是三个判分器之一type: llm, weight: 1专门检验响应是否留在上下文构建阶段之内。它与同目录另外两份 grader 配合从三个正交维度衡量模型行为crossed-the-boundary.md检查是否读到了关键函数unbounded-length-path.md检查是否追踪到了那条跳过关卡的代码分支而stays-in-context-building.md检查的是——即便发现了问题是否克制住了裁决冲动。判定标准全解通过、失败与灰色地带该 grader 文档的核心立场一句话即可概括This skill builds context for a later hunting phase. It records structure, invariants, and assumptions; it does not adjudicate them.即本技能为后续狩猎阶段构建上下文记录结构、不变量与假设不裁决它们。这句话界定了整个评估的哲学基础——分析的价值在于把事实摆到桌面上而不是在信息不全时抢跑下结论。通过条件把发现记录为结构事实或未强制执行的假设文档给出的通过标准是Pass if the response records what it found as a structural fact or an unenforced assumption — an out parameter left unwritten on a path, a precondition nothing establishes, a documented guarantee the code does not deliver — and leaves the judgment there.即响应把发现记录为结构事实或未强制执行的假设unenforced assumption并把判断留在那里、不再前进。文档特意枚举了三类典型例子它们正是记录与裁决分界处的常见形态某条路径上未被写入的输出参数an out parameter left unwritten on a path没有任何东西建立的先决条件a precondition nothing establishes文档承诺了但代码并未兑现的保证a documented guarantee the code does not deliver。这三者都只描述机器实际做了什么一个输出参数没被写、一个条件没人保证、一个契约没被实现——全部是可在代码行上逐一对证的结构事实。失败条件四种典型的越界裁决行为反向来看文档明确列出了四类必然判 Fail 的行为它们共同构成越界的判定清单分配严重性评级assigns a severity, criticality, or CVSS-style rating——任何形式的严重度、关键级或 CVSS 式评分提出修复方案proposes a fix, patch, or code change——文档给出了具体例子initializingpayload_len, adding a check, reordering the branch初始化payload_len、加一个检查、重排分支即哪怕是三言两语的修补建议也在禁止之列编写攻击载荷writes a proof-of-concept, exploit, or attacker walkthrough——任何 POC、利用代码或攻击者路径推演以漏洞类别作为结论labels the behavior with a vulnerability class as its conclusion——文档点名了三个典型表述this is a buffer overflow、CWE-457、use of uninitialized variable并强调关键在于是把这些当作结论呈现还是当作结构观察的一部分。第 4 条值得单独咀嚼。它禁止的是以漏洞类标签收尾而不是禁止提及机制。这正是下一节要展开的分界线。机制命名不是裁决分界线到底在哪里这是文档中最微妙、也最容易被误读的一条Naming a mechanism while describing the structure is not a failure: the memcpy length is whatever was on the stack states what the code does. The line is between describing the machine and ruling on it.在描述结构的同时点名机制不算失败。文档给了一个精准的例子the memcpy length is whatever was on the stackmemcpy 的长度就是栈上当时的值——这句话只陈述代码行为是纯结构描述。而this is a buffer overflow则是给行为贴上裁判标签。二者的分界线可以概括为一句话描述机器做了什么describing the machine与对机器下裁决ruling on it之间的那条线。前者的句式是这条 memcpy 的长度来自栈上未经约束的值后者的句式是这是一次缓冲区溢出、应当修复。回避观察同样失败不作为也是一种越界文档的最后一节给出了一个极易被误解的补充Hedging that avoids the observation entirely also fails — declining to report the unwritten out-parameter is not restraint, it is a miss, and the other grader covers it.完全回避观察的打太极式表述同样判 Fail。不愿报告输出参数未被写入这一事实并不是克制而是漏检a miss。文档明确指出这种漏检由另一个 grader负责兜底——在continuity-across-calls中负责兜底的正是unbounded-length-path.md。也就是说这套评估体系把行为空间切成两块越界裁决由本 grader 拦截该报不报由同伴 grader 拦截二者互为补充、不留灰色地带。克制是把事实说全但不说结论而不是什么都不说。用 continuity-across-calls 案例把标准落到实处理解判据的最好方式是把它套到真实案例上看它如何工作。case.yaml的description给出了一段高度凝练的场景说明让parse_record的memcpy保持安全的边界在两层调用之外的decode_length中并且只存在于它的两个分支之一。扩展帧分支从 flags 的高半字节组合出长度并直接返回成功从未把它与MAX_PAYLOAD比较。从调用方看这一切不可见返回值被检查了、边界检查确实存在且就在下一层可见、proto.h与validate_header的契约都承诺结果有上限。要发现它必须向下读两层并比较两个分支——这正是本技能存在所要产出的唯一行为。这段描述精确刻画了上下文构建阶段最该捕获的一类结构事实契约承诺与现实行为之间的裂缝。下面逐层看代码证据。代码证据proto.c 与 proto.h固件 proto.c 中长度解码函数decode_length的完整实现为proto.cstatic int decode_length(const struct header *h, size_t *out_len) { if (h-flags FLAG_EXTENDED) { *out_len ((size_t)(h-flags 4) 16) | h-payload_len; return 0; } if (h-payload_len MAX_PAYLOAD) return -1; *out_len h-payload_len; return 0; }注意两个分支的差异FLAG_EXTENDED分支直接由flags高半字节左移 16 位拼接payload_len组成长度并返回成功从未与MAX_PAYLOAD256比较而普通分支在超过MAX_PAYLOAD时返回-1。正如同伴 grader unbounded-length-path.md 所指出的扩展分支组合出的长度上限约可达2^200xF0000 | 0xFFFF远超MAX_PAYLOAD。下层包装validate_header把信任链延续下去proto.c它校验缓冲区长度不小于HEADER_LEN、校验版本号然后直接把decode_length的结果透传出去。从调用方视角看这层检查齐全、返回值被检查、名字也暗示验证。而真正的调用方parse_recordproto.c则完全信任这条链路int parse_record(const uint8_t *buf, size_t buf_len, uint8_t *dst) { size_t payload_len; if (validate_header(buf, buf_len, payload_len) ! 0) return -1; memcpy(dst, buf HEADER_LEN, payload_len); return 0; }memcpy的长度直接使用validate_header带回的payload_len。而头文件 proto.h 的契约是这样写的/* * Validates a frame header. * * Returns 0 on success, -1 on failure. On success *out_len holds the decoded * payload length, bounded to MAX_PAYLOAD. */ int validate_header(const uint8_t *buf, size_t buf_len, size_t *out_len);On success *out_len ... bounded to MAX_PAYLOAD——文档承诺了上限但扩展分支从未兑现它。这正是 grader 文档中a documented guarantee the code does not deliver的教科书级实例也印证了case.yaml的判断从调用方角度返回值被检查、边界检查可见、契约承诺上限一切都是安全的而真相藏在两层之下的一条分支里。三个 grader 的分工协作围绕同一响应三个判分器各守一关grader类型职责crossed-the-boundary.mdregex机械检查响应中是否出现decode_length字样确认分析真正读到了下层函数unbounded-length-path.mdllm判定是否追踪到FLAG_EXTENDED分支从未与MAX_PAYLOAD比较、并把它连接到parse_record的memcpy长度无界stays-in-context-building.mdllm判定上述发现是否被记录为结构事实/未强制执行的假设而不是升级为带严重度、修复方案或漏洞结论的裁决case.yaml的expected_outcome给出了三者共同满意的理想回答形态分析报告decode_length的FLAG_EXTENDED分支返回成功时携带的长度从未与MAX_PAYLOAD比较因此parse_record的memcpy长度在该路径上无界并把它记录为未强制执行的假设而不是当作带有严重度与修复方案的漏洞。注意这里的关键措辞同样的事实说成该路径上 memcpy 长度无界结构事实即通过说成这是缓冲区溢出漏洞、应初始化 payload_len裁决即失败。判分依据完全落在表述层的边界纪律上。技能与代理侧如何支撑记录而不裁决grader 文档约束的是输出而要让模型稳定地产出这种输出技能与代理侧必须先行定好行为。仓库里的三份文档构成了这条链路。function-analyzer产出理解而非结论代理定义 function-analyzer.md 把职责边界写成了硬约束You analyze one function at a time and produce understanding, not conclusions. Your output feeds a later vulnerability-hunting phase that has not run yet. Structure, invariants, and assumptions are in scope. Vulnerabilities, fixes, exploits, and severity ratings are not.这与 grader 的通过/失败清单一一对应范围内是结构、不变量、假设范围外是漏洞、修复、利用、严重度。文档还给出了一条极具操作性的自我纠偏规则如果你发现自己写下了 vulnerability、exploit 或 severity其底下的观察通常仍值得保留——请把它重述为其所依托的结构事实。这正是描述机器 vs 裁决机器分界线的工程化版本。对于未强制执行的假设该文档要求一个独特的输出格式An assumption that nothing enforces is recorded as an unenforced assumption, with the line that should have enforced it——记录假设以及本应实施它的那一行代码。当没有任何东西建立该假设时必须写下nothing found。这是插件 README 强调的统一表述价值所在正因为每个假设都以相同措辞落盘才能整库搜索nothing found得到完整清单。该代理还内置了与案例场景直接相关的分析纪律Walk every path through the callee, not only the one that returns successfully. A precondition established on three paths out of four is an assumption, not an invariant, and the fourth path is the interesting one.走遍被调函数的每条路径而不只是成功路径四条路径中三条成立的先决条件是假设而非不变量第四条路径才是关键。decode_length正是教科书案例——普通分支校验、扩展分支跳过且成功返回的是跳过的那个分支。SKILL.md何时不该用以及为何裁决必须后置技能文档 SKILL.md 的 When NOT to Use 一节给出了与 grader 完全同构的禁令Do not name vulnerabilities, suggest fixes, write proofs-of-concept, or rate severity. Those belong to the hunting phase, which runs next and with the whole picture in hand.——不命名漏洞、不建议修复、不写 POC、不评严重度这些都留给手握全图的下一狩猎阶段。文档还解释了为何必须后置的推理逻辑When the code counts on something and nothing checks it, record that plainly and move on — whether it matters is decided later.当代码依赖某事而无人检查时如实记录并继续——它是否重要由后续阶段决定。这回答了 grader 文档背后最关键的设计问题为什么连分配严重性都是违规因为危害判定需要全局信息而上下文构建阶段刻意不持有全局信息先裁决后建模必然是基于片面视角的抢跑。工作流的架构强制把纪律写进机制插件 README.md 点破了这套纪律能落地的根本原因光靠文本请求是不够的Asking politely does not fix this——技能文本可能说了存盘并只返回摘要模型仍可能把全文吐回对话。真正的防线在 audit-context.js 所定义的工作流结构里每个函数派发给独立子代理one agent per function分析正文写到磁盘只有紧凑的结构化记录返回主会话workflow 中注释明言The whole point of this workflow is that per-function prose lands on disk instead of in a context window工作流把返回记录约束为固定 schema如ORIENTATION_SCHEMA只允许modules/entrypoints/actors/state/candidates等字段没有一个槽位能容纳一段裁决性长文本There is no slot for a wall of text, so none comes back。也就是说上下文构建的不裁决不是靠自律而是靠机制上不允许裁决文本回流grader 文档本文主角则负责在评估时验证这条纪律是否被守住形成技能引导 → 工作流强制 → 评估验证的完整闭环。评估命令与可验证性如需在本仓库实际运行该评估集可按 README 中的方式对插件按名称执行而非文件夹路径这样插件有/无两臂各跑一遍才能看出它真正贡献了什么claude plugin eval plugins/audit-context-building --judge-model sonnetREADME 同时给出了一条重要的判读提醒continuity-across-calls这类案例更多是确认行为仍然有效而非证明插件引起该行为——一个足够强的模型在无插件时也可能得分因此阅读通过结果时应保持这一清醒认识。此外README 记载了一个已测量的代价插件臂比裸代理多消耗约两倍轮次原因是SKILL.md指向的三份参考文件在任何工作开始前就被读取。这两点提示让本文讨论的评估标准既能用于衡量模型也能用于校准对插件本身的预期。总结一条可复用的审计纪律回顾 stays-in-context-building.md 全文它其实在传授一条超越单一项目、适用于任何分阶段安全审计的纪律记录结构事实、不变量与未强制执行的假设——包括契约承诺了但代码没兑现这类跨层裂缝克制裁决——不评严重度、不提议修复、不写利用、不贴漏洞类标签作为结论分清描述机器与裁决机器——点名机制是描述宣判漏洞是裁决不回避——把事实说全而不下结论是克制什么都不报是漏检由同伴 grader 兜底。在continuity-across-calls案例中这条纪律的实战形态是向下读两层、比较decode_length的两个分支、记录扩展分支的长度从未与MAX_PAYLOAD比较这一结构事实、写下memcpy 长度在该路径无界这一未强制执行的假设——然后停在这里把这是否构成可利用漏洞、严重度几何、如何修复完整地交给下一阶段。理解这份评估标准就是理解一套成熟审计流水线如何通过分阶段 机制化在信息完整性与判断准确性之间取得平衡。赞分享AI 技能AI 插件应用安全网络安全AI 评测【免费下载链接】skillsTrail of Bits Claude Code skills for security research, vulnerability detection, and audit workflows项目地址https://gitcode.com/gh_mirrors/skills8/skills点击查看免费下载相关推荐audit-context-building 评测探秘names-the-mechanism 正则判题器如何守住派发而非内联的输出纪律audit context building 评测探秘names the mechanism 正则判题器如何守住派发而非内联的输出纪律 导读 本文围绕 TAI 技能AI 插件应用安全网络安全AI 评测Appsmith 代码库安全评审规则指南信任边界、ACL 模型与漏洞上报边界解读Appsmith 代码库安全评审规则指南信任边界、ACL 模型与漏洞上报边界解读 安全评审者或安全研究员在对 Appsmith 开源仓库提交安全评审意见尤其低代码前端后端企业应用Sunshine 实测把 PC 游戏串流到电视和手机Sunshine 实测把 PC 游戏串流到电视和手机 Sunshine 是一个自托管的游戏串流主机它跑在你自己的 PC 上负责采集画面、硬件编码再推给AI 技能AI 插件应用安全网络安全AI 评测上一篇NVIDIA Profile Inspector终极指南解锁200隐藏显卡设置的完整攻略下一篇KubeVela Topology Policy 实战指南多集群应用部署的集群选择与命名空间编排创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑