☰
deepsec 批处理提示词组装解析:INFO.md 与 promptAppend 的注入位置及防重复机制
2026/9/27 21:22:22 网站建设 项目流程
  • 应用安全
  • 漏洞扫描
  • 人工智能
  • AI Agent

【免费下载链接】deepsec

Deepsec is a security harness for finding vulnerabilities in your codebase powered by coding agents

项目地址:https://gitcode.com/gh_mirrors/deeps/deepsec
点击查看免费下载

Deepsec 在将扫描候选文件交给编码 Agent 做安全研判前,会先把"系统提示词半区"组装成一份完整、可复现、可快照的 prompt。本文以仓库中prompt-samples/08-with-info-and-append.md这一份真实样例为解剖对象,讲解项目级 INFO.md 与config.json:promptAppend两块用户自定义上下文在组装 prompt 中的确切位置、它们如何与核心提示词、技术栈威胁要点、漏洞 Slug 笔记协同工作,以及为什么 Agent 层不会把它们重复发射——读完你既能看懂任意一份 prompt 样本的来龙去脉,也能在自己的项目里正确配置这两类上下文。

这份样例在验证什么

先看样例文件头部注释给出的"场景元数据"(prompt-samples/08-with-info-and-append.md第 1-10 行):

  • 场景名:08-with-info-and-append
  • 场景描述:Next.js 批处理 + 项目 INFO.md +config.json:promptAppend附加说明——展示它们在组装后 prompt 中的位置,并确认不会由 Agent 层二次发射
  • 检测到的技术标签:["nextjs","react"]
  • 批处理文件:["app/secrets.tsx"]
  • 批处理语言:["typescript"]
  • 批处理 Slug:["xss","secret-in-fallback"]
  • 生成者:packages/processor/src/__tests__/prompt-samples.test.ts
  • 重新生成命令:UPDATE_PROMPT_SAMPLES=1 pnpm test:unit

这些元数据不是手写的,而是测试代码根据场景定义动态推导出来的:批处理语言由文件扩展名推导,批处理 Slug 由候选匹配的vulnSlug去重得到(见 场景定义 中的scenarioBatch()与languagesForBatch())。也就是说,这份 .md 文件不是"示例文案",而是当前代码实际会生成的确切 prompt 的确定性快照,由测试逐字节比对校验。

组装后的完整结构:一份 prompt 的两个半区

prompt-samples/08-with-info-and-append.md从第 12 行起就是模型最终收到的完整 prompt。它由两个半区拼接而成,对应生产链路中的两个函数:

  1. 组装半区(system prompt 部分):由assemblePrompt()生成,见 assemble.ts;
  2. Agent 层包装(任务部分):由buildInvestigatePrompt()追加目标文件列表、调查步骤与 JSON 输出规范,见 shared.ts。

测试中fullPromptFor()正是按生产路径的顺序把两步串起来:detectTech()得出标签 →assemblePrompt()组装系统提示词半区 →buildInvestigatePrompt()包上文件列表(见 prompt-samples.test.ts)。下面按实际出现顺序逐段拆解。

1. 核心提示词:与具体项目无关的通用底盘

样例开头的"世界级安全研究员"角色设定、严重级别分类(CRITICAL/HIGH/MEDIUM + HIGH_BUG/BUG)、已知漏洞类别总表、误报规避指南、认证绕过模式清单、作用域外文件说明,全部来自CORE_PROMPT常量,定义在 core.ts。这份内容刻意保持精简:"任何只属于某一个框架的内容都必须放进 highlights,而不是这里"(core.ts 第 7-8 行的注释)。

值得注意的细节:核心提示词里的"Known Vulnerability Categories"表格列了 30 多个 slug(auth-bypass、xss、sql-injection、ssrf、secret-in-fallback……)以及other-*通配后缀,告诉模型"扫描器只看这些模式,但你要全看"。这份样例中批处理的xss与secret-in-fallback两个 slug 都出现在表内,属于该批次的"已知类别"。

2. 技术栈威胁要点:只注入检测到的技术

样例的## Threat highlights for this repo's tech stack一节只包含Next.js与React两个小节,没有 Django、Laravel 等内容——因为场景的detectedTags就是["nextjs","react"]。这正是assemblePrompt的按需注入逻辑:renderFrameworkSection()只渲染detectedTags中能查到的 highlight(assemble.ts 第 83-89 行)。

更细一层的控制是batchLanguages语言过滤:highlightForTag()返回的每个TechHighlight都声明了适用的语言集合,只有当批处理文件的语言与该集合有交集时,该技术的 highlight 才会进入 prompt。所以在一个 Next.js + Django 的 polyglot 仓库里,纯 Python 批处理只会带 Django 的要点,不会带 Next.js 的。本场景是["nextjs","react"]标签 +typescript批处理语言,两者吻合,两个 highlight 都正常注入。

这一节还受 6000 字符的预算上限约束:FRAMEWORK_SECTION_CHAR_BUDGET(assemble.ts 第 14 行),超过后整节退化为一行"这个仓库使用了 N 个已知框架……"的摘要,避免撑爆模型上下文(对应场景07-overflow-fallback.md)。

3. Slug 专项评审笔记:只出现本批次命中的 slug

## Slug-specific reviewer notes一节只有两行:

  • xss:检查每一步的转义状态;裸拼接进 HTML、script 中未转义</的 JSON、ref.innerHTML是常见 sink;
  • secret-in-fallback:process.env.X || "hardcoded"才是 bug——只有当 fallback 看起来像真实凭据时才标记,"localhost"不算。

这两条来自 slug-notes.ts 的SLUG_NOTES表,且只有出现在当前批次的 slug 才会被拉进来(renderSlugSection(),assemble.ts 第 122-133 行)。SLUG_NOTES表内有 150+ 条笔记,但每次只渲染命中项,prompt 长度随扫描器实际看到的内容伸缩,而不是按整个注册表膨胀。

用户自定义上下文的注入:INFO.md 与 promptAppend

这是 08 号场景区别于其他样例的关键:它是唯一同时携带projectInfo(INFO.md)与promptAppend两个字段的场景(见 场景定义)。

注入位置:在框架要点与 Slug 笔记之后

在assemblePrompt中,两个用户自定义块被追加在所有框架生成内容之后:

// INFO.md 和 promptAppend 是用户撰写的,常自带 H1/H2, // 因此用水平分隔线(---)分隔,而不是再包一层我们自己的标题, // 避免出现两个相邻的 H2 之间什么都没有。 if (projectInfo && projectInfo.trim().length > 0) { sections.push(`---\n\n${projectInfo.trim()}`); } if (promptAppend && promptAppend.trim().length > 0) { sections.push(`---\n\n${promptAppend.trim()}`); }

见 assemble.ts。整个组装顺序由注释明确给出:

[generic core] ## Threat highlights for this repo's tech stack ## Slug-specific reviewer notes [project INFO.md, verbatim] [config.json:promptAppend, verbatim]

样例中两者的真实内容

  • INFO.md(## Project notes):指出认证辅助函数是lib/auth.ts里的requireUser(),内部路由集中在app/(internal)/**之下。这是给 Agent 的项目级背景知识——告诉它"认证长什么样、哪些目录是内部面",让它在研判时能区分真缺失与假缺失。
  • promptAppend(Custom: ...):追加"额外标记任何静默吞掉错误的 logger——这是本仓库已知的坑"。这是把仓库特有的历史教训沉淀成提示词的方式。

两者都以"原样追加(verbatim)"的方式进入 prompt,中间用---分隔。选择水平分隔线而非包装标题,是避免用户写的##标题与系统生成的##标题"双 H2 撞车"(assemble.ts 第 179-182 行注释,且测试明确断言最终 prompt 不含## Project context包装标题,见 prompt-assemble.test.ts)。

防重复发射:Agent 层只拿到空 projectInfo

生产链路中process()调用buildInvestigatePrompt时把projectInfo传成"",因为 INFO.md 已经躺在组装好的promptTemplate里了(shared.ts 第 394-398 行注释)。buildInvestigatePrompt只在调用方显式传入时才生成## Project Context块;模块化路径传空串,于是 INFO.md 在最终 prompt 中只出现一次。

测试用直接可验证的方式锁死了这一点:

it("INFO.md appears exactly once in the final prompt", () => { const sample = fullPromptFor(PROMPT_SAMPLE_SCENARIOS[7]); // 08-with-info-and-append const occurrences = sample.split("Auth helper is `requireUser()`").length - 1; expect(occurrences, "expected INFO.md content exactly once").toBe(1); });

见 prompt-samples.test.ts。这条测试连同"样例必须与组装器+Agent 层输出逐字节一致"的断言(同文件第 66-91 行),共同保证了仓库里的样例文件永远不会与代码漂移——任何有意改变 prompt 形状的改动都要先跑UPDATE_PROMPT_SAMPLES=1 pnpm test:unit重写样本并人工 review diff。

Target Files:扫描候选如何落到 prompt 里

样例的## Target Files一节把批处理文件app/secrets.tsx连同扫描器的两条候选命中一起列出:

  • [xss] L22: dangerouslySetInnerHTML
  • [secret-in-fallback] L4: process.env.X || "..."

这是buildInvestigatePrompt渲染的:对每个FileRecord,把候选匹配的 slug、行号、匹配模式拼成列表(shared.ts 第 368-385 行)。如果某文件没有任何扫描器命中,则会渲染成(no scanner hits — full holistic review),要求 Agent 对整文件做全面评审而非只盯候选行——保证process --diff之类场景下无命中的文件也不会被忽略。

输出规范:JSON findings 的契约

## Output Format一节(样例第 145-173 行)定义了模型必须返回的 JSON 结构:每个文件一个条目,findings数组中每条包含severity(CRITICAL/HIGH/MEDIUM/HIGH_BUG/BUG)、vulnSlug(可用已知类别,新颖问题用other-前缀)、title、description、lineNumbers、recommendation、confidence(high/medium/low)。无真实漏洞的文件也必须出现,带空findings数组。

这是整个管线的解析契约:模型输出先经 JSON 解析(严格解析失败会走jsonrepair容错),再逐条用findingSchema做字段级校验,校验失败的不落盘而是发起同会话的字段修复轮次(shared.ts 第 800-849 行parseInvestigateResults与第 857-895 行修复 prompt)。

如何在自己的项目里配置这两块上下文

方式一:deepsec.config.ts的项目声明字段

在项目声明的ProjectDeclaration上直接声明(见 configuration.md):

import { defineConfig } from "deepsec/config"; export default defineConfig({ projects: [ { id: "my-app", root: "../my-app", infoMarkdown: "## 仓库背景\n\n认证用 requireUser(),内部路由在 app/(internal)/**。", promptAppend: "额外标记任何静默吞掉错误的 logger——本仓库已知的坑。", }, ], });

对应字段(packages/core/src/config.ts):

字段类型必填作用
infoMarkdownstring否注入到 AI 提示词中的仓库背景;与data/<id>/INFO.md同时存在时优先
promptAppendstring否追加到该系统提示词末尾的自由文本

方式二:data/<id>/INFO.md与data/<id>/config.json

如果infoMarkdown未设置,deepsec 会读取data/<id>/INFO.md并注入其内容(适用于process、triage、revalidate)。docs/configuration.md对篇幅的建议是"几百词的仓库背景——代码库是干什么的、认证长什么样、威胁模型、已知误报来源",并说明 one-shot setup 会自动写入并校验该文件。

promptAppend等字段仍支持在data/<id>/config.json中声明(见 configuration.md):

{ "priorityPaths": ["app/api/", "lib/"], "promptAppend": "Pay extra attention to the booking flow.", "ignorePaths": ["**/legacy/**"] }

如果配置文件与项目声明的同名字段同时存在,配置文件优先。一个真实可参考的样例在 samples/webapp/config.json,其中的promptAppend明确写了"跨租户访问(缺少 companyId 作用域)是本代码库影响最大的 bug 形态,检查数据库查询是否按req.session.user.companyId过滤"——这正是 08 号样例所展示的用法:把只有项目维护者知道的领域知识沉淀进提示词,引导 Agent 关注高价值 bug 形状。

处理器侧的数据流

从处理器入口看,projectConfig.promptAppend在初始化时被读入并透传(见 index.ts),最终经assemblePrompt({ projectInfo, promptAppend })进入组装器;组装器对两者一视同仁:非空白就追加,且都用---分隔保持与系统生成段落的分界。INFO.md 与 promptAppend 的"原样注入、只出现一次、位置固定"由此贯穿配置层 → 处理器 → 组装器 → Agent 层整条链路。

样例的生成与回归机制

prompt-samples/目录下的 11 份样例全部由 prompt-samples.test.ts 生成并持续校验:

  • 常态运行:每个场景的fullPromptFor()与磁盘上的.md文件逐字节比对,不一致即测试失败;
  • 有意变更时:UPDATE_PROMPT_SAMPLES=1 pnpm test:unit会重写全部样例文件,然后通过 PR diff 审查变更内容。

这意味着08-with-info-and-append.md不只是文档,更是一份可回归的契约:任何对核心提示词、highlights、slug 笔记、INFO.md/promptAppend 注入位置或 Agent 层包装的改动,都会先在这里留下痕迹。测试还额外断言了两点:样例必须同时包含组装半区与 Agent 层文件列表两个部分(同文件第 93-100 行),以及 INFO.md 在最终 prompt 中恰好出现一次(第 102-106 行)——与样例头部注释声称的"确认它们不会被 Agent 层重复发射"完全对应。

小结

08-with-info-and-append是理解 deepsec 提示词工程的最小完备案例:一条组装器代码路径(assemblePrompt)加上一条 Agent 层包装路径(buildInvestigatePrompt),把通用核心、按需技术要点、按需 slug 笔记、用户自定义的 INFO.md 与 promptAppend、具体的候选文件列表与输出契约,拼成一份既不过度膨胀、又承载了项目特有知识的最终提示词。而样例文件本身被测试以字节级精度钉在仓库里,让 prompt 的每一次演化都变得可审查、可回放、可回归。若要进一步研究,可以从 assemble.ts、core.ts、slug-notes.ts 三个源文件入手,再对照 configuration.md 与 samples/webapp/config.json 把配置侧的字段接上。

  • 应用安全
  • 漏洞扫描
  • 人工智能
  • AI Agent

【免费下载链接】deepsec

Deepsec is a security harness for finding vulnerabilities in your codebase powered by coding agents

项目地址:https://gitcode.com/gh_mirrors/deeps/deepsec
点击查看免费下载

相关推荐

上一篇:DevDocs MCP服务器配置:如何让Claude智能查询你的文档数据
下一篇:DeepSeek Harness 统一 JSON 值 Schema DSL:从工具参数到结构化输出的单一强制词汇

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询