Shannon 工作区机制详解:扫描状态持久化、目录布局与可恢复扫描
发布时间:2026/9/6 15:51:45 锦皓数字建站

Shannon 工作区机制详解扫描状态持久化、目录布局与可恢复扫描【免费下载链接】shannonShannon is an AI pentester for web applications and APIs. It analyzes your source code, identifies attack vectors, and executes real exploits to prove vulnerabilities before they reach production.项目地址: https://gitcode.com/GitHub_Trending/shan/shannonShannon 的 workspace工作区是每次渗透测试运行的持久化单元负责保存扫描状态、日志、提示词和交付物并支撑中断或失败后断点续扫这一核心能力。本文以 Shannon 官方文档 Workspaces and Resuming 为主线结合 CLI 启动命令、工作区路径解析、检查点接口 与 恢复状态加载逻辑 等源码实现完整讲解工作区的命名规则、存储位置、目录结构、恢复resume机制与 URL 一致性校验原理并给出可直接复制的 npx 与源码构建两种模式的实操命令。1. 为什么 Shannon 需要工作区一次完整的 Shannon 扫描包含预侦察、侦察、五个并行漏洞分析 Agent、五个并行利用 Agent 和报告生成等多个阶段完整的多 Agent 流水线定义见 session-manager.ts单次运行耗时可达 11.5 小时且涉及 LLM API 开销。如果中途因网络抖动、LLM 服务故障或人为中断而失败从头重跑既浪费成本又浪费时间。为此 Shannon 的设计目标是每次运行都创建一个工作区用于存放扫描状态、日志、提示词和交付物每个 Agent 的进度都被检查点checkpoint记录恢复运行时可以跳过已完成的 Agent只重跑未完成的部分最终报告以Security-Assessment-Report.md的形式呈现于工作区根目录而交付物、日志、提示词与会话状态等运行内部文件则收敛在隐藏的.shannon/目录中保持工作区顶层整洁。注意工作区只是本地状态存储Shannon 的实际执行发生在一次性的 Docker worker 容器中工作区目录以卷挂载方式被容器读写。2. 工作区的命名规则与存储位置2.1 自动命名主机名 会话时间戳不指定-w参数时Shannon 会基于目标 URL 的主机名加当前时间戳自动生成工作区名例如example-com_shannon-1771007534808。从源码看这个命名规则实现于 start.ts 第 84-86 行const workspace args.workspace ?? ${new URL(args.url).hostname.replace(/[^a-zA-Z0-9-]/g, -)}_shannon-${Date.now()};即取 URL 的 hostname将字母、数字、连字符以外的字符全部替换为-所以example.com变成example-com再拼接_shannon-前缀和毫秒级时间戳。时间戳保证了同一目标多次扫描不会互相覆盖。2.2 两种运行模式对应不同的存储位置运行模式工作区存储位置npx模式推荐~/.shannon/workspaces/源码构建模式local./workspaces/仓库根目录下这一差异的判定逻辑见 home.ts 第 19-21 行export function getWorkspacesDir(): string { return getMode() local ? path.resolve(workspaces) : path.join(SHANNON_HOME, workspaces); }其中SHANNON_HOME固定为~/.shannonconfig.toml凭据文件也位于该目录下。在 start 命令 执行时工作区目录会被递归创建并chmod 0o777同时预建.shannon/deliverables、.shannon/scratchpad、.shannon/.playwright-cli、.shannon/.playwright四个子目录——因为容器内 worker 以 UID 1001 的非特权用户运行目录必须可写而目标仓库本身是只读挂载进容器的可写的交付物通过 overlay 目录落盘到工作区。2.3 使用-w指定自定义名称-w name为运行指定自定义工作区名这是后续断点续扫的关键句柄npx keygraph/shannon start -u https://example.com -r /path/to/repo -w my-audit恢复一次扫描时必须传入与首次运行完全相同的工作区名并且 URL 必须一致见第 5 节。3. 工作区的目录结构一次运行结束后工作区目录的布局是顶层一个报告 隐藏目录装一切内部状态workspaces-dir/workspace-name/ ├── Security-Assessment-Report.md # 最终人类可读报告工作区根目录 └── .shannon/ # 运行内部文件隐藏目录 ├── session.json # 会话状态状态、Agent 进度、工作流 ID ├── deliverables/ # 各 Agent 的交付物含独立 git 检查点库 ├── scratchpad/ # Agent 工作草稿 ├── .playwright-cli/ .playwright/ # 浏览器自动化产物 └── ... # 日志、提示词等运行内部文件关键路径常量集中定义在 worker 的 paths.tsINTERNAL_DIR .shannon内部文件隐藏目录注释明确说明其目的是让运行目录顶层只暴露最终报告FINAL_REPORT_FILENAME Security-Assessment-Report.md呈现给用户的最终报告文件名ASSEMBLED_REPORT_FILENAME comprehensive_security_assessment_report.md内部组装版报告位于 deliverables 内report.json/report.sarif报告 Agent 产出的结构化发现与可选 SARIF 2.1.0 日志。另外resolveSessionJsonPath 会优先读取.shannon/session.json并回退到旧版布局的根目录session.json保证重构前的旧工作区依然可列出、可恢复。CLI 端还有配套的迁移函数 migrateLegacyWorkspaceLayout挂载前检测到旧版扁平布局存在根级session.json且无.shannon/时会把所有顶层文件在同一文件系统内 rename 进.shannon/——注释特别指出这个同盘重命名会让交付物目录自带的.git检查点库一并迁移从而让恢复时能继续识别旧的交付物和它们的 git 检查点而不是重跑所有 Agent。4. 断点续扫Resume机制全解4.1 基本操作以命名工作区启动并恢复文档给出的标准示例如下npx 模式# 首次启动一个名为 my-audit 的工作区 npx keygraph/shannon start -u https://example.com -r /path/to/repo -w my-audit # 用同样的工作区名恢复该次扫描 npx keygraph/shannon start -u https://example.com -r /path/to/repo -w my-audit # 恢复一个自动命名的工作区 npx keygraph/shannon start -u https://example.com -r /path/to/repo -w example-com_shannon-1771007534808源码构建模式下把npx keygraph/shannon换成./shannon即可参数完全一致./shannon start -u https://example.com -r /path/to/repo -w my-audit ./shannon start -u https://example.com -r /path/to/repo -w example-com_shannon-1771007534808 ./shannon workspaces4.2 恢复时底层发生了什么第一步判定新运行还是恢复。CLI 在拉起 worker 容器后通过轮询session.json区分两种情况start.ts 第 153-194 行文件存在即判定为 resume新运行的就绪标志是session.json中出现了originalWorkflowId恢复运行的就绪标志是session.session.resumeAttempts数组新增了记录每条含一个workflowId。这也意味着session.json是工作区的状态中枢记录会话状态in-progress/completed/failed、创建/完成时间、每次恢复尝试的 Temporal 工作流 ID以及每个 Agent 的状态与检查点哈希结构见 activities.ts 的 SessionJson 接口扫描以后台容器方式运行CLI 打印提示后终端可以关闭可用shannon logs workspace跟踪日志、shannon status查看状态。第二步加载并校验恢复状态。worker 侧的 loadResumeState 按顺序执行四道校验工作区存在性session.json不存在则抛出不可重试的WorkspaceNotFoundErrorJSON 完整性解析失败抛出CorruptedSessionErrorURL 一致性session.session.webUrl与本次传入的 URL 不一致则抛出URLMismatchError见第 5 节Agent 状态与磁盘交付物交叉核对对每个在session.json中状态为success的 Agent检查其交付物文件文件名映射见 session-manager.ts 的 AGENTS 注册表是否真实存在于磁盘若标记成功但交付物缺失则记录警告并重新运行该 Agent防止状态文件与磁盘不一致导致的假跳过。第三步逐 Agent 的检查点跳过。流水线在每个 Agent 活动执行前后都会回调 CheckpointProvider 接口export interface CheckpointProvider { /** Agent 执行前调用。返回 { skip: true, metrics } 表示跳过该 Agent。 */ shouldSkipAgent(agentName: string, repoPath: string, deliverablesSubdir: string): PromiseSkipDecision; /** Agent 成功后调用用于工件持久化。 */ onAgentComplete(agentName: string, phase: string, state: PipelineState, context?: CheckpointContext): Promisevoid; }shouldSkipAgent在并发漏洞利用阶段按 Agent 粒度触发5 条流水线并行已完成的 Agent 直接跳过并沿用其历史指标onAgentComplete在 Agent 成功后持久化工件。从源码结构看交付物目录带有独立的 git 仓库git-manager.ts 负责 commit 与取 hashworkflows.ts 中多处if (input.checkpointsEnabled)分支会将resumeState.checkpointHash传给各 Agent 活动——每个 Agent 的检查点就是一个 commit 哈希恢复时比对哈希即可判定该 Agent 的产出是否已存在。综合来看每个 Agent 的进度都被检查点记录这一文档描述在实现上 session.json 中的 Agent 状态表 交付物磁盘交叉校验 deliverables 目录 git 检查点哈希三层保险任何一层发现不一致都会触发对应 Agent 的安全重跑。5. URL 一致性约束防止跨目标污染文档中有一条重要注意事项恢复扫描时 URL 必须与原工作区的 URL 一致否则 Shannon 会拒绝执行。这一约束的源码实现非常直接activities.ts 第 911-916 行if (session.session.webUrl ! expectedUrl) { throw ApplicationFailure.nonRetryable( URL mismatch with workspace\n Workspace URL: ${session.session.webUrl}\n Provided URL: ${expectedUrl}, URLMismatchError, ); }该错误被标记为不可重试的URLMismatchError并打印工作区记录的 URL 与本次传入的 URL 便于比对。其安全含义是工作区中保存了针对特定目标的侦察结果、漏洞假设与利用证据如果允许复用旧工作区、换新目标上一目标的上下文就会污染新目标的结论例如把旧目标的端点误当作新目标的存在证据。强制 URL 一致从机制上杜绝了这种跨目标串档。6. 列出所有工作区shannon workspacesnpx keygraph/shannon workspaces # npx 模式 ./shannon workspaces # 源码构建模式该命令的实现分两层。CLI 侧 workspaces.ts 本身不解析任何文件而是启动一个一次性 Docker 容器docker run --rm把工作区目录挂载到容器内的/app/workspaces并执行镜像中的node apps/worker/dist/temporal/workspaces.js——这样列出逻辑始终与 worker 镜像保持同一版本若镜像不可用会提示先docker pull。容器内的 工作区列表脚本 遍历工作区目录读取每个工作区的session.json按创建时间倒序输出表格包含五列信息列来源字段WORKSPACE目录名URLsession.session.webUrlSTATUSsession.session.statusin-progress/completed/failedDURATIONcompletedAt - createdAt未完成则算到当前时刻COSTmetrics.total_cost_usd该次运行累计 LLM 成本美元状态非completed的工作区会在行尾标注(resumable)末尾汇总N workspaces found (M resumable)并提示恢复命令./shannon start -u url -r repo -w name。无法解析session.json的目录会被静默跳过因此手工创建的空目录不会干扰列表。7. 实操建议与常见排查长期审计项目建议始终显式-w自动名虽然含时间戳保证唯一但主机名时间戳不利于人工辨认自定义名让logs、status、workspaces等后续命令都能用同一个稳定句柄。恢复前确认三要素工作区名-w、目标 URL-u、仓库路径-r三者都要与首次运行保持一致URL 不一致会直接得到URLMismatchError。旧版本工作区仍可恢复.shannon/布局之前的扁平结构会在挂载前自动迁移migrateLegacyWorkspaceLayout且resolveSessionJsonPath对旧位置有回退读取。状态异常时看session.json它是工作区内一切状态查询的第一现场Agent 级状态、检查点哈希、恢复尝试历史都在其中交付物缺失但状态标成功时恢复运行会自动重跑对应 Agent 而不是静默跳过。工作区目录权限CLI 会把工作区目录及其内部子目录设为0o777以便容器内 worker 用户写入这是为容器化挂载设计的不需要也不建议在容器外修改这些权限。8. 小结Shannon 的工作区机制把一次耗时且昂贵的多 Agent 渗透测试变成可中断、可恢复的有状态过程~/.shannon/workspaces/npx或./workspaces/源码构建下的每个目录对应一次运行顶层只暴露Security-Assessment-Report.md.shannon/隐藏目录承载session.json、交付物、日志与浏览器产物恢复扫描时loadResumeState依次完成存在性、完整性、URL 一致性校验与交付物磁盘核对再由CheckpointProvider按 Agent 粒度跳过已完成的工作。掌握-w命名、URL 一致性约束和shannon workspaces列表命令就足以对中断的扫描做可靠的断点续跑。【免费下载链接】shannonShannon is an AI pentester for web applications and APIs. It analyzes your source code, identifies attack vectors, and executes real exploits to prove vulnerabilities before they reach production.项目地址: https://gitcode.com/GitHub_Trending/shan/shannon创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。