result-with-file

star 72

将安全分析/测试结果持久化为按入口点/主题组织的分级 Markdown 报告,内嵌 POC

Q16G By Q16G schedule Updated 6/7/2026

name: result-with-file description: 将安全分析/测试结果持久化为按入口点/主题组织的分级 Markdown 报告,内嵌 POC version: "2.0" agent: all when-to-use: 所有分析完成后,需要将结果持久化输出时 context: inline

核心原则:无损超集

最终报告是所有子报告的超集,不是摘要。子报告(各步骤的 result_file)中可机械列举的内容,必须原样进入最终报告对应的详细章节,禁止概括、折叠或抽样。具体包括但不限于:

  • 端点 / 接口清单:逐条保留 method + URL + 参数名 + 记录数等
  • 测试场景矩阵:每个场景独立成行,保留请求与关键响应字段,禁止合并为单行结论
  • 算法 / 关键逻辑源码片段:原样代码块
  • 配置项与响应头:逐条保留(如 CORS 各响应头、缺失安全头清单、OPTIONS 预检响应)
  • 环境 / WAF / 前置条件等限制说明:逐条并入"评估局限性"

顶层综合层(执行摘要、严重度统计、攻击链串联、统一修复建议)是在明细之上额外添加的,不能取代明细,也不得以"已在汇总表概括"为由删减明细。各子报告文件保留为可追溯的原始证据,最终报告须引用并链接它们。

反折叠机制:机械派生 + 计数闸门(最重要)

历史上"折叠"反复发生的根因不是上游丢数据,而是 findings-index.md(反折叠的"基准")由 LLM 边读 prose 报告边手写概括出来,于是被写成区间行(如 AUTH-001~021DEEP-001~550(19处)),随后的逐行对账拿"折叠的索引"核对"折叠的报告"——两边一致、永远通过,对账空转。

修复原则:基准和闸门必须脱离 LLM 自由发挥。 本 skill 用以下确定性流程取代手写:

  1. 每条发现先抽成规范化 jsonl(一发现一行、字段见所选模板的 schema、绝不写区间),落 shared/coverage-ledger/findings/<src>.jsonl
  2. findings-index.md 与 id 清单 index-ids.txt / exclude-ids.txt模板提供的 jq 派生命令从 jsonl 机械派生(区间行从构造上不可能出现),作为闸门基准。
  3. 报告正文里每条进入正文的发现行末附隐藏锚点 <!-- fid:<对应 jsonl 的 id> -->;写入前用 grep 抽取报告全部 fid,与 index-ids.txt集合比对comm),缺一条或多一条即判失败、回去对齐。fid 锚点让漏条精确到具体 id,而非只比对总数。

发现记录契约(jsonl,每行一条)

本 skill 只规定抽象契约;具体字段名、status 取值、去重键、jq 派生命令全部由所选模板的"发现记录与派生"节定义(见 step 2),4 个模板各自可不同。

  • 发现记录 = jsonl,一发现一行,绝不写区间(禁止 001~021(19处)等7处)。
  • 每行必含:全局唯一 id带源前缀,如 src1-001,避免多份报告各自从 001 起 append 撞车)、titlesource_report、一个 status、以及供去重的键字段
  • status取值集合、status→{进正文 / 进排除项 / 仅作覆盖证明 / 忽略}桶映射去重键字段由模板定义。其中"进正文"桶再分两档:已确认(确凿)与待复核(需人工确认,归入"待人工复核项汇总"章节);两档对应的具体 status 名同样由模板给出。PoC 是否强制不按这两档简单二分,而按"是否做过验证动作"裁决——以下方"完整性要求"为准。
  • 两个 id 清单是模板 derive 与本 skill 闸门之间的通用接口(由模板的 jq 派生命令产出):
    • shared/coverage-ledger/index-ids.txt —— 应纳入报告正文的发现 id 全集("进正文"桶)。
    • shared/coverage-ledger/exclude-ids.txt —— 应纳入"误报 / 排除项"章节的发现 id 全集("进排除项"桶)。
  • 若上游各 skill 已在发现当下落行(见各 skill 的"发现即落行"约定,其字段即对应模板的 schema),本 step 直接复用,无需重新抽取。

执行步骤

  1. 收集已完成步骤的分析结果(并集收集,禁止只读摘要)

    • 先取前序步骤 step outcome 中登记的 result_file / summary_file 路径。

    • 再递归列出共享工作区下的报告文件(用你当前可用的任意手段枚举,不限定具体工具),避免遗漏未登记为 reference 的报告:workspace 根目录下的 shared/ 目录树,以及所有 sub_agents/**/shared/ 目录树(含其下任意层级子目录,如 shared/recon-3/analysis-summary.md),匹配全部分析报告 md(如 *-report.md*analysis*.md*-overview.mdfallback_*.mdcomprehensive-*.md 等)。planner_skills_index.mdfindings-index.md 等纯流程/索引/中间产物文件不算分析报告,跳过。还须跳过本 skill 自己上一轮的输出——即 shared/ 根下的最终聚合报告,用双判据识别:(1) 文件名为 {project}-security-report.md(step 7 产物,与子报告 *-api-security-report.md 等不同名,不误伤);(2) 文件内含 ## 源报告覆盖表 这一聚合报告专属章节(子报告不会有,名字漂移时的兜底)。否则重跑时上一轮最终报告会被当源报告读入,发现翻倍、统计虚高。

    • 开始登记前先准备目录与清空旧产物mkdir -p shared/coverage-ledger/findings;删除本轮要重建的 shared/findings-index.md(覆盖写,不在旧内容上追加),避免上一轮残留行污染本轮对账。shared/coverage-ledger/findings/ 下已存在上游 skill 发现当下落盘的 jsonl,直接复用,跳过本份的重新抽取。

    • 将两类来源取并集逐份完整读取详细报告文件本身(分页读取到 EOF:单页上限约 200 行/20KB,文件更大时必须用 offset 继续翻页直到读完,禁止只读首页就开始整合):每读完一份,把其每条发现抽成规范化 jsonl 行(一发现一行,字段见 step 2 所选模板的 schema,绝不写区间行如 001~021(19处)等7处),用追加写入该源对应的 shared/coverage-ledger/findings/<src>.jsonl<src> 取源报告文件名去扩展名),再读下一份。不要求一次性把全部源报告 load 进上下文——增量抽取并落盘即可,规避上下文过载。

      • 结构化交付物(端点授权矩阵的每一行、技术栈表等)同样逐行落成 jsonl 记录,不得概括为一条。
      • 模板若有自身的覆盖面对账需求(如 code-audit 的入口点清单),按该模板 reference 文件的约定另行落盘其专属台账,本通用步骤不规定其格式。
    • 机械派生(运行所选模板的派生命令):所有源报告抽完后,执行 step 2 所选模板"发现记录与派生"节给出的 jq 派生命令,产出三件机器产物——

      • shared/findings-index.md:索引视图(列由模板定义);
      • shared/coverage-ledger/index-ids.txt:应纳入报告正文的发现 id 全集("进正文"桶,去重、排序);
      • shared/coverage-ledger/exclude-ids.txt:应纳入"误报 / 排除项"章节的发现 id 全集("进排除项"桶,去重、排序)。

      命令体(含该模板的 status 取值、去重键、索引列、去重键非空校验)在模板里,本步只负责执行它并确认三件产物生成。三者都是机器产物、不可手工编辑

    • 严禁用子 agent 的 final_answer / 摘要替代详细报告:子 agent 的详细报告(写在各自 sub_agents/<id>/shared/ 下)通常比冒泡上来的摘要包含更多发现、端点矩阵、攻击链等表格,必须读详细文件,否则最终报告会丢失这些内容。

    • 区分发现型与侦察型报告:含漏洞/发现/矩阵的报告(如 *-api-security-report.mdcomprehensive-*.mdfallback_*.mdsecret-detection-report.md)其发现必须逐条带入;纯侦察/架构报告(如 *-overview.md*-technology-stack-report.md)用于补全"配置/架构类发现"与覆盖声明的上下文,正文可不照搬,但其结构化交付物(端点授权矩阵、技术栈表等)仍须逐行抽成 jsonl 落 shared/coverage-ledger/findings/<src>.jsonl,以便 step 6 对账,避免端点矩阵这类交付物被漏。

    • 去重但不折叠:多份源报告报同一漏洞时,仅当模板定义的去重键完全相同才合并为一条;去重键任一字段不同即各自独立成条,禁止跨键折叠。

  2. 选择报告模板:根据当前 agent 类型,从 ${SKILL_DIR}/reference/ 读取对应模板文件:

    Agent 类型匹配 模板文件
    code-audit ${SKILL_DIR}/reference/code-audit-template.md
    pentest-* ${SKILL_DIR}/reference/pentest-template.md
    host-defense-* ${SKILL_DIR}/reference/host-security-template.md
    其他 / 不确定 ${SKILL_DIR}/reference/general-template.md

    使用 read_file 加载模板文件,按模板结构组织报告内容。

  3. 组织全部发现:以 step 1 落盘的 jsonl 为数据源shared/coverage-ledger/findings/*.jsonl 去重后的每一条 + 已逐份读入的详细报告内容;findings-index.md 是其 jq 派生视图),严禁回头从冒泡上来的步骤结果/摘要重新抽取——正文、index 与 jsonl 三者必须同源。把每个漏洞实例独立成节,禁止合并或折叠。每条进正文的发现(已确认 / 待复核两档)的详细发现节必须携带其在子报告中的完整证据链——全部测试场景行、全部受影响端点、全部源码片段——而非一句话加两行表;大块明细(端点/接口清单、路由树、算法源码、完整测试矩阵)正文引用、附录展开,逐条原样保留,禁止抽样。

    • 组织结构按所选模板:详细发现卡片的标题约定、章节顺序、是否按入口点/按严重度组织、§8 配置类发现如何承载,全部由 step 2 选定的 reference 模板规定,本通用步骤不再重述。
    • 每条进入正文的发现都打 fid 锚点:无论它以详细卡片、配置/架构类发现表行、还是系统性发现的形式出现,其所在行(卡片标题行或表格行)的行末都追加 <!-- fid:<该发现在 coverage-ledger/findings 里的 id> -->。fid 是 step 6 闸门唯一的核对依据——漏打一个 fid 等同漏一条发现。排除项发现(status 属模板定义的"排除"桶)写入"误报与排除项"章节时同样打 fid(核到 exclude-ids.txt)。
  4. 为进正文的发现编写 POC:按下方"POC 规则"选择格式、构造内容、执行自检。PoC 强制与否取决于"是否实际做过验证动作",而非最终落哪个档位:凡做过验证尝试的发现(已确认档,以及"待复核"中已构造并发送请求 / 已做可达性分析等做过验证动作的)都必附 PoC——哪怕没复现成功,也要留下当时构造/尝试的请求/payload/分析作为过程证据;只有压根没法验、没动手的发现才可不附(详见下方"完整性要求")。

  5. 填充评估完整性章节:同样以 step 1 落盘的 jsonl(shared/coverage-ledger/findings/*.jsonl)+ 详细报告为准,提取"待复核"桶条目(附无法确认的原因和排查建议)、"排除"桶条目(附排除依据)、已检测但未发现漏洞的维度、因前置条件不足或环境限制未能覆盖的维度,分别填入模板对应章节。最后编写结论章节,综合所有发现给出整体风险评级和后续建议。

  6. 确定性 fid 闸门(写入前必须执行,不通过禁止写入):用 grep + comm 机械比对"报告里打了 fid 的发现集合"与 step 1 派生的两个 id 清单。闸门只消费 id 文件、与 status 取值无关(status 语义已在模板 derive 里处理)。REPORT 为待写入的最终报告文件路径。

    REPORT=shared/<project>-security-report.md   # 替换为实际路径
    
    sort -u shared/coverage-ledger/index-ids.txt   > /tmp/ids_reg    # 应进正文的发现 id 全集
    touch shared/coverage-ledger/exclude-ids.txt
    sort -u shared/coverage-ledger/exclude-ids.txt > /tmp/ids_exc    # 应进"误报/排除项"章节的 id 全集
    sort -u /tmp/ids_reg /tmp/ids_exc              > /tmp/ids_allowed # 报告里允许出现的全部 fid
    # 报告侧:正文里实际打出的 fid
    grep -oE 'fid:[A-Za-z0-9_-]+' "$REPORT" | sed 's/^fid://' | sort -u > /tmp/ids_rep
    
    miss=$(comm -23 /tmp/ids_reg /tmp/ids_rep)       # 应进正文却无 fid → 折叠 / 漏条
    exc_miss=$(comm -23 /tmp/ids_exc /tmp/ids_rep)   # 排除项未在"误报/排除项"章节打 fid
    extra=$(comm -13 /tmp/ids_allowed /tmp/ids_rep)  # 报告有、基准(含排除项)均无 → 凭空多出 / fid 写错
    [ -z "$miss$exc_miss$extra" ] || echo "FAIL: 缺失[$miss] 排除缺[$exc_miss] 多余[$extra] —— 必须逐条对齐 fid 后重写,禁止直接写入"
    
    • 核对项(全部须对得上,对不上回去补全再写):
      • miss 必须为空:index-ids.txt 里每个 id 都要在报告正文出现对应 <!-- fid:id -->;缺失即折叠或漏条。
      • exc_miss 必须为空:exclude-ids.txt 里每个 id 都在"误报与排除项"章节打了 fid。
      • extra 必须为空:报告里的 fid 都必须能在基准(index-ids ∪ exclude-ids)里找到;多出即 fid 写错或凭空发现。
      • severity_counts / 风险统计表的每个数字 == 正文实际列出的对应严重度条目数。
    • 折叠话术扫描:对全文检索禁用措辞(还有相同其余+同理以此类推不再赘述同上代表性典型几例~+区间)。任一命中且未展开为逐条实体的,必须先展开/修正再写入(规则见"通用规范 → 禁止折叠话术")。
    • 覆盖声明里标 done 的维度,其对应交付物(尤其结构化矩阵/表格)必须实际存在于报告正文,禁止"声明 done 但正文缺表"。
    • 模板若有自身的覆盖面对账(如 code-audit 的入口点节数对账),按该模板 reference 文件的约定追加执行,本通用闸门只负责 fid 集合一致性。
    • 最终报告末尾必须附源报告覆盖表(code-audit 模板见对应章节;其他模板在末尾追加同等表格):每份源报告 → 贡献的发现编号 → 是否全部纳入(是 / 部分+原因)。
  7. 写入文件:将完整 Markdown 报告写入共享工作区目录(workspace 根目录下的 shared/ 子目录,使用绝对路径)。文件名格式:{project}-security-report.md必须是单一报告文件:顶层综合、全部详细发现、全部附录枚举都写入这一个文件,禁止把附录或任何章节拆分到其他文件。

  8. 报告文件路径:写入完成后,在调用 update_current_step 时将文件的绝对路径填入 references 字段,禁止使用相对路径。

通用规范(所有模板共享)

禁止折叠话术(硬约束)

折叠 = 用计数、抽样、省略号、"等"字或引用,替代逐实例枚举的任何手法。 折叠会导致漏条、统计虚高、覆盖面对账失真,一律禁止。以下五类话术明令禁用:

手法 禁用话术(示例,凡同义变体一并禁止)
A 计数替代枚举 "还有相同 18 个接口存在同样问题"、"其余 N 处同理"、"同类漏洞共 N 个,不再赘述"、"批量存在于 N 个端点"
B 省略号 / "等"字收尾 "…"、"等"、"等等"、"诸如…等"、"以此类推"、"限于篇幅省略其余"
C 抽样 / 代表性 "选取典型/代表性几例"、"仅列高危若干"、"举例说明"
D 引用替代卡片 "同 EP-01 不再重复"、"详见前述/参见上文"(用来省掉发现卡片本身)
E 表格行折叠 端点授权矩阵/配置发现表写"其余端点同上/略";统计表只给总数、正文无对应实体

正向规则(必须满足):

  • 数字必须逐条可数:报告中出现的任何数字(风险统计表的 N、覆盖声明端点数、"共发现 N 处")都必须在正文找到 N 个独立实体(EP 小节 / F 卡片 / 矩阵行)一一对应,数字 = 正文实体数。
  • 相似不是折叠理由:同一漏洞影响 N 个入口点,就写 N 个 EP 小节(或 N 个 F 卡片);即使内容高度相似也要逐个落地,禁止"1 条 + 还有 N-1 个同理"。
  • 跨节引用边界:复合 ID(攻击链 step 引用某条发现、源报告覆盖表对账互指)是允许的合法引用;仅当引用被用来替代发现卡片正文本身时,才算 D 类折叠。

完整性约束

  • 所有有危害的发现(CRITICAL 到 LOW)必须逐条出现并各自打 fid,禁止折叠或省略(见上方"禁止折叠话术");归属到所选模板规定的组织单元(入口点节 / 严重度分组 / 系统性发现节),不得因组织方式丢条
  • 同一漏洞点被多个组织单元到达时,每个单元下独立成节
  • 同一根因导致多个独立攻击面时,每个攻击面独立成节
  • 结构化交付物章节(如端点授权矩阵、攻击链、技术栈表):源报告中已产出的整表必须完整填入对应章节,禁止压扁成单条发现或省略整表;具体章节编号由所选模板规定
  • 有明确数据流或可构造 POC 的系统性漏洞(硬编码密钥、弱加密、可利用依赖漏洞等)逐条写发现卡片;仅配置/基线/架构缺陷(RBAC 缺失、安全头缺失等)用"配置/架构类发现"表格汇总,不需逐条 POC——此处"汇总"指每项独立成行并各自打 fid(如每个缺失安全头一行、每条 RBAC 缺失一行),仅免去 POC,不得把多项合并为一行或概括为一句话
  • 风险统计表数字必须与实际 finding 数量一致
  • 所有"待复核"档发现必须出现在"待人工复核项汇总"章节,逐条附注无法确认的具体原因和排查建议
  • 初步检测后排除的误报项必须在"误报与排除项"章节列出,说明排除依据
  • 已检测但未发现漏洞的维度必须在"已验证安全的维度"章节声明
  • 因前置条件不足(如无测试账号、无源码权限、WAF 拦截等)导致无法覆盖的维度必须在"评估局限性"章节说明
  • "结论"章节必须包含整体风险评级和后续建议

无损整合自检(写入报告前必须执行)

整合完成后,逐项对照以下检查表。任一项不通过则补全后再写入。

# 检查项 通过标准
1 子报告全部读完 每份 result_file 已分页读到 EOF,未只读首页
2 端点/接口枚举保留 子报告中的端点清单逐条出现在最终报告正文或附录
3 测试矩阵保留 每个测试场景独立成行,未折叠为单行结论
4 算法/源码片段保留 子报告中的代码块原样出现
5 配置/响应头逐条保留 CORS 响应头、缺失安全头、OPTIONS 预检等逐条出现
6 限制/WAF/环境说明保留 子报告中的环境与前置条件说明已并入"评估局限性"
7 finding 数量对账 最终报告 finding 总数 ≥ 各子报告 finding 之并集,且统计表数字一致
8 来源映射完整 每份源报告在"源报告覆盖表"(章节编号见所选模板)中均有记录,标注贡献的发现编号及是否全部纳入

POC 规则

格式选择

场景 格式 原因
单一请求即可触发 http 可直接复制到 Burp/curl
需多步骤、条件判断或自动化 python 单请求无法表达完整攻击链
默认凭证 / 配置类 http 一次请求验证即可

同一报告内尽量统一格式;对于单请求可触发的漏洞,优先选 http

构造规则(代码审计)

代码审计的 POC 从源码推导,未经运行时验证。这条静态 POC / 静态 confirmed 路径仅适用于 pure code-audit 报告(无可运行目标,或动态验证明确不可行动)。若同一任务存在可行动的运行目标并在产出 graybox / pentest 报告,总结论里的 confirmed 仍必须按运行时效果判定,静态 POC 只作白盒佐证。 必须遵循:

  1. URL 必须从代码注解推导:@RequestMapping / @GetMapping / web.xml 映射 → 完整 URL path
  2. HTTP 方法必须从代码注解推导:@GetMapping → GET, @PostMapping → POST
  3. 参数名必须从 source 表达式提取:request.getParameter("questionData") → 参数名 questionData
  4. payload 必须匹配漏洞类型(见下方适配表)
  5. 前置条件显式标注:如需特定配置、认证、角色等,在 POC 上方注明
  6. POC 末尾加注释行:# 基于代码分析构造,未经运行时验证

构造规则(渗透测试)

渗透测试的 POC 是实际发送并得到响应的请求。必须遵循:

  1. 请求必须是实际发送过的(从 HAR/流量捕获中提取)
  2. 响应要点附在 POC 后:关键响应字段/状态码
  3. 不编造未测试的请求

漏洞类型 payload 适配

CWE 漏洞类型 payload 要求
CWE-78 命令注入 payload 包含命令分隔符 + 可观测命令,如 ; id 或 `
CWE-89 SQL 注入 payload 包含 SQL 语法,如 ' OR 1=1--1 UNION SELECT ...
CWE-79 XSS payload 包含脚本标签,如 <script>alert(1)</script>
CWE-611 XXE payload 包含外部实体声明
CWE-918 SSRF payload 包含内网地址,如 http://127.0.0.1:port
CWE-798 硬编码凭证 payload 直接使用发现的凭证
CWE-352 CSRF 提供完整 HTML PoC 表单
CWE-22 路径穿越 payload 包含 ../ 序列

完整性要求

PoC 是否强制,按"是否实际做过验证动作"裁决,不按最终档位。其中 pure code-audit 可用静态 POC 支撑静态 confirmed;但 graybox / pentest / 有可运行目标的报告里,confirmed 仍要求运行时效果证据:

  • 已确认档(confirmed:必附 POC。落入此档就强制,不因确认来自静态分析而非运行时、或证据带"未经运行时验证"标注而豁免——按对应场景的构造规则(见上方各"构造规则"小节)构造即可。但带"未经运行时验证"尾注的静态 POC,只能用于 pure code-audit 报告;graybox / pentest / 有可运行目标的报告要进 confirmed,仍需运行时效果证据。
  • 待复核档(needs_review)中做过验证尝试但未闭环的必附 PoC。把当时构造/尝试的请求、payload 或可达性/数据流分析片段如实贴出,并注明"为何未复现、缺哪一环"。此处 PoC 是"试过什么"的过程证据,不要求它证明危害。
  • 待复核档中确无验证路径、未做任何尝试的:PoC 不适用,可不附。(注:若验证路径其实可用却没走,该发现应判为未闭环 / uncovered 推回去验证,而不是停在这里——见 common/closure-verification.md。)
  • 证据链本身已是实际发出并捕获的请求/响应时,可直接充当 POC。
  • 配置/架构类发现(安全头缺失、RBAC 缺失等)用表格汇总,不需 POC。
  • 一句话:做过验证动作的发现都要留下 PoC(哪怕没复现成功);只有压根没法验、没动手的才免

POC 最终自检(写入报告前必须执行)

所有 POC 写完后,逐条对照以下检查表。任一项不通过则修正后再写入报告。

# 检查项 通过标准
1 URL 路径与源码一致 代码审计:URL 能在 @RequestMapping / web.xml / 路由配置中找到对应;渗透测试:URL 来自实际发送的请求
2 HTTP 方法正确 GET/POST/PUT/DELETE 与代码注解或实际请求一致
3 参数名正确 参数名可在 source 表达式(request.getParameter / @RequestParam / body 解析)中找到
4 payload 匹配漏洞类型 对照"漏洞类型 payload 适配"表,payload 中包含该 CWE 对应的特征语法
5 前置条件已标注 若漏洞触发需要特定配置/认证/角色/数据状态,POC 上方已注明;无前置条件则标注"无"
6 格式一致性 同一报告内同类单请求漏洞使用相同格式(http 或 python),不混用
7 代码审计标注 代码审计场景的 POC 末尾包含"基于代码分析构造,未经运行时验证"注释

文件格式

  • 格式为 .md,不使用 JSON
  • 文件名包含项目标识:{project}-security-report.md
Install via CLI
npx skills add https://github.com/Q16G/aster --skill result-with-file
Repository Details
star Stars 72
call_split Forks 6
navigation Branch main
article Path SKILL.md
More from Creator