Repository navigation
Releases
v2.0.3 — 参数引号加固 + submit_flag 命令注入修复
两处修复:工具参数引号加固(治上次那轮失败)+ pentest_submit_flag 命令注入。
1. 模型在参数里写裸双引号 → 整轮 MALFORMED_RESPONSE
宿主在流结束时直接 JSON.parse 每个 tool-call 的 arguments,一个块坏了整步报错,参数根本到不了插件层——所以只能在提示词侧降低概率、缩小影响面:
- persona(
agent.cordis.yml/agent.cordis.next.yml两代变体)新增参数编码纪律:字符串参数里不写裸 ASCII 双引号,中文引用用「」,命令/PoC 用单引号; pentest-report/pentest-exploit技能同步这条硬性要求,并限定一步只记一条 finding——同一步的多个 tool-call 是「一坏全废」,拆开可限制损失。
2. pentest_submit_flag 命令注入
原先 "http://" + server + "/api/submit" 裸插值:模型(或被测目标上的提示注入)给出带引号 / $(...) 的字符串就能在宿主执行任意命令。改为白名单校验(host[:port] / token 字符集)+ q() 转义;未传参时仍走 $TSEC_* 环境变量回退(该路径由 shell 展开,不经拼接)。
验证
node --check lib/pentest-tools.js- js-yaml 校验 3 份 yml
npm test:13 通过,1 跳过- 注入用例(token 带
"; touch /tmp/pwned; echo "、server 带$(id))均被拒,正常调用与环境变量回退不受影响 node scripts/release-check.mjs:31/31
升级
gh release download v2.0.3 --repo hack-umbrella/pipadeep -p '*.tgz' -D ~/.dsh/pkgs
dsh plugin --profile web add file:~/.dsh/pkgs/pipadeep-dsh-pentest-2.0.3.tgzv2.0.2 — 修 persona 模板 {{cwd}}(dsh 0.2.1 整轮失败)
修 dsh 0.2.1 上「渗透模式 Pro」预设整轮失败(unknown prompt variable "{{cwd}}")。
dsh 0.2.1-rc.3 的 dsh-persona 注册 deployment:persona-prefix 时只传 text,不声明变量白名单,
渲染器默认变量集是 provider / model。预设 persona 里的 {{cwd}} 于是每轮渲染系统提示都抛:
unknown prompt variable "{{cwd}}" in section "deployment:persona-prefix"; registered variables: provider, model
表现为「本轮运行失败」,用户侧看起来像预设凭空消失。
工作目录本来就由 runtime context 逐轮注入,persona 里再写一遍是冗余的 —— 改为文字说明,不用变量。
改动
preset/pentest/agent.cordis.yml(0.1.x / worker-thread 变体)preset/pentest/agent.cordis.next.yml(0.2.x / ptc 变体)- 同步修正注释,避免后续误以为
{{cwd}}仍可用
验证
- js-yaml 校验 5 份 yml 全部通过
node scripts/release-check.mjs:31/31- 真实 profile 上会话可正常开轮(人格段只剩
{{model}})
升级
gh release download v2.0.2 --repo hack-umbrella/pipadeep -p '*.tgz' -D ~/.dsh/pkgs
dsh plugin --profile web add file:~/.dsh/pkgs/pipadeep-dsh-pentest-2.0.2.tgzv2.0.1 — 适配 dsh 0.2.1(子 agent 改独立预设)
适配 dsh 0.2.1-rc.2(破坏性变更)。
症状
在 dsh 0.2.1 上,渗透预设整份建不了会话:
tool-subagent (@deepseek-ai/dsh-tool-subagent):
tool-subagent: persona is no longer supported;
configure persona and tool plugins in an Agent Preset and select it with agentPreset (spawn only)
根因
dsh 0.2.1 把 tool-subagent 的 Config 白名单收窄为
provider / toolName / modelSelectionSettings / agentOptions / agentPreset / allowedAgentPresets / maxDepth,
移除了 persona / toolFilter / n —— 只要配置里出现就抛错(不是"忽略")。
渗透预设的执行子 agent 正是用 persona + toolFilter.deny 定义的。
修复:执行子 agent 抽成独立 Agent Preset
- 新增
pentest-executor预设(preset/pentest/executor.cordis*.yml):- 人设(原 persona 文本)→
dsh-agent-instructions - 工具面 =
bash/fs/fs-search+ 本包pentest-tools(31 个执行工具)+ 上下文压缩 - 不含记录层
pentest(goal/intent/fact/finding/asset 的写入口)与subagent—— 结果只能经父会话的pentest_submit写回,防越权写库与递归委派
- 人设(原 persona 文本)→
- 父预设的
tool-subagent改为agentPreset: pentest-executor
两条变体分工(关键)
| 变体 | workflow provider | 子 agent 配置 |
|---|---|---|
agent.cordis.yml |
worker-thread(≤0.1.5) |
保留 persona/toolFilter 供 0.1.x |
agent.cordis.next.yml |
ptc(≥0.1.6 / 0.2.x) |
只用 agentPreset,不含 persona/toolFilter |
因为 dsh 0.2.1 见到 persona 就拒绝整份预设,两代无法共用同一份配置 —— 这正是变体机制存在的意义。
验证
- dsh 0.2.1-rc.2 沙箱:
pentest/pentest-executor/code-audit三个预设均可建会话 ✓ - dsh 0.2.1-rc.2 生产机:启动零失败、
pentest+code-audit均可建会话 ✓ test/preset-variants.test.mjs重写为内容级断言(旧变体有 persona/worker-thread、新变体有 agentPreset/ptc 且无 persona)release-check第 5 项同步升级 → 31/31 通过
附:0.2.1 升级踩到的其它坑(供参考)
~/.dsh下 0.1.x 残留目录(code-audit/.agent-presets/skills)会阻止启动,需移走dsh-vision-router在 0.2.1 上加载失败并劫持connection的依赖,报错却指向webRuntime(0.2.1 已无此服务),需禁用该插件dsh-better-sidebar需 ≥ 0.28.0(peer 覆盖^0.2.1-rc.1)
v2.0.0 — 能力补齐(ingest / OOB / 交付 / KPI / 复测 / 越权 / 情报)
v2.0.0 —— 能力补齐(路线图 1/2/3/4/5/6/7)
说明:按约定打了 major 号作为里程碑标记。对使用者没有破坏性变更:
预设结构、存储模型(6 表)、既有工具签名与 Web 视图全部保持不变,纯增量。
新增能力
| 面 | 新增 |
|---|---|
| 输入 | pentest_ingest + lib/ingest.mjs:nmap/nuclei/httpx/ffuf/masscan/naabu 确定性解析入库(稳定键去重、来源 sha256、坏行留痕) |
| 回连 | pentest_oob + lib/oob.mjs:local/interactsh 可插拔、AES 解密、状态 0600、回连按 id 去重落成事实(盲注/盲 SSRF/无回显 RCE/XXE/JNDI 的打中验证) |
| 情报 | lib/jsintel.mjs:JS 端点/参数/硬编码密钥(含熵判断)+ 内网地址 + crt.sh 子域 |
| 认证授权 | lib/authz.mjs:JWT(alg=none/弱密钥离线爆破/kid 注入/jku/缺 exp/敏感声明)+ 访问矩阵 + IDOR/BOLA 归类 |
| 交付 | lib/report.mjs + lib/zip.mjs:CVSS 3.1(与官方参考一致)、docx、证据包(sha256 清单)—— 零运行时依赖,zip 容器自己写 |
| 度量 | lib/kpi.mjs:确认率、误报上界、高危确认率、噪声规则榜 + 跨引擎合并(置信度提升) |
| 复测 | lib/retest.mjs:已修复/仍存在/新增/回归(= 上轮标记修复又重现) |
| 工具 | 16 → 19 个(新工具均在决策层,已加入子 agent toolFilter.deny) |
关键修复(都在 2.0.0 之前的分版落地)
- 旧会话打不开:v1.4.0 前注入父会话的合成
tool/call被 dsh 0.2 迁移拒绝 →
33 个会话全部恢复(含 seq 引用重编号、v0 顶层surfaceOp、头部seedLength自洽) - dsh 0.2 预设被整份禁用:dsh 系 peer 改
optional - 渗透视图静默不挂载:不再依赖被移除的
snapshot.current
工程护栏(打包前拦截,各带反向验证)
release-check 30 项,其中三条件对应本周期真实事故:
6b 相对 import 必须随包分发(不再核对固定清单)、6c array 必须带 items、
6e output.schema 必须显式 type+additionalProperties。
测试
test/ 13 个文件、约 300 项断言:ingest 30、oob 25、analysis 53、repair 15、
plus 既有 preset-variants / lossless-json / shot 等。
未完成(已在 ROADMAP.md 注明原因)
- 8 内网/AD/云、9 工程化与 OPSEC:需靶场/容器/宿主调度环境,先出接口设计(ROADMAP 附录)
- 10 知识库沉淀:按实战复盘逐次沉淀,不凭想象堆内容
- 待补的实链路验证:OOB 的 start→回连→poll(工具已确认暴露给模型,是模型那一轮未调用)、
双账号越权靶场、真实站点 JS 抽取
v1.7.0 — 交付物 / KPI / 复测 / 越权 / 前端情报
路线图第 3/4/5/6/7 项的代码部分(一次发布)。
| 路线图 | 交付 |
|---|---|
| 5 交付物 | CVSS 3.1 计算器(与官方参考向量一致:9.8 / 6.1 / 1.8 / 0)、docx 生成、证据包(sha256 清单) |
| 7 降噪度量 | 候选→确认转化率、误报率上界、高危确认率、噪声规则榜;跨引擎合并(同位置同规则族合并 + 置信度提升) |
| 6 复测回归 | 两次评估 diff:已修复/仍存在/新增/回归(回归定义为"上轮标记已修复、本轮又重现") |
| 4 认证授权 | JWT 静态分析(alg=none/弱 HMAC 离线爆破/kid 注入/jku/缺 exp/敏感声明)+ 访问矩阵 + 越权归类(IDOR/BOLA 候选) |
| 3 攻击面(代码部分) | JS 端点/参数/硬编码密钥抽取(含熵判断)+ 内网地址识别 + crt.sh 子域枚举 |
实现要点
- 零运行时依赖:docx 与证据包都是 zip,而 Node 没有 zip 容器 —— 用
lib/zip.mjs
自己写了最小的 ZIP 写入器(deflate/存储 + 中央目录 + EOCD + CRC32),不引第三方包。 - 越权判定不靠猜:
classifyAccessPair(属主响应, 另一身份响应)→
protected/idor-candidate/bola-candidate/indeterminate;
候选不是结论,报告里明确要求人工核对资源归属。 - KPI 用本插件的语义:候选 = 已记录的
kind=vuln事实(未验证),
确认 = findings(带可复现步骤)—— 这样"确认率"才反映真实的降噪效果。
测试
新增 test/analysis.test.mjs 53 项:zip 往返与两种压缩方式、CVSS 参考向量、
docx 部件完整性与 XML 转义(防注入)、证据包哈希、KPI 计算与合并、复测四类结论、
JWT(含真签一个弱密钥令牌做离线命中)、矩阵与越权归类、JS 抽取与 crt.sh 解析。
npm test 13 个测试文件全绿;npm run check 30/30。
v1.6.11 — OOB / 带外回连
路线图第 2 项:OOB / 带外回连。
为什么必须有
盲注、盲 SSRF、无回显 RCE、XXE 外带、JNDI/反序列化注入的「打没打中」只能靠回连确认。
在此之前整库没有任何回连能力(连一处 oob 字样都只在 UI 标签里),等于结构性放弃这一整类漏洞,
poc 纪律也无法闭环。
新增
lib/oob.mjs- Provider 可插拔:
local(自建,明文 JSON 协议,便于内网自控/测试)、
interactsh(公共或自建集群,回连数据 AES-CFB 解密;解密失败退回原文,不丢整批回连) buildPayload:每注入点一个唯一token.域名,DNS 与 HTTP 同一 tokennormalizeInteraction:统一两家后端的字段(协议/来源 IP/时间/原始请求响应/唯一 id)OobState:correlation id 与 secret 落$DSH_HOME/oob/<sessionId>.json(0600),
进程重启后仍能继续 poll;回连按 id 去重,只入库一次
- Provider 可插拔:
pentest_oob工具:start/new/poll/list/stop- 回连落成
kind=http|info事实(带来源 IP、时间、原始请求),可直接作为 PoC 证据 - 子 agent 只负责注入 payload,回连入库仍归决策 agent(已加入
toolFilter.deny)
- 回连落成
测试
新增 test/oob.test.mjs 25 项:payload 构造、字段规范化(含 JSON 字符串形式)、
状态持久化与权限位、去重、AES 往返、无密钥兜底、未知 provider 报错。全部用桩 fetch,不联网。
npm test 12 个测试文件全绿;npm run check 30/30。
v1.6.10 — 修 pentest_ingest 的 output.schema
修复:pentest_ingest 的 output.schema 不合法 → 渗透预设建不了会话。
根因
dsh 对工具输出 schema 的要求与参数不同:必须显式声明
type: "object" 与 additionalProperties。新工具的 output.schema 只写了 properties:
agent-preset/invalid: pentest (@pipadeep/dsh-pentest/pentest):
unsupported JSON schema: schema.type must be string/number/integer/boolean/null/array/object/json, or use oneOf
定位方式
用宿主的 defineTool 直接逐变体压 schema(参数/输出各 5 种写法),发现只有
「output.schema 带 type:"object" + additionalProperties」这一种通过;
本仓库既有的 11 个工具全都这么写,新工具漏了。
修复
- output.schema 补
type: "object"+additionalProperties: false release-check新增第 6e 项:静态扫output: { schema: {,必须同时出现
type: "object"与additionalProperties。反向验证:去掉后立刻报错。- 自检与
pipacodedeep共用,已同步
验证
npm run check 30/30;装上后渗透预设可建会话。
v1.6.9 — 修 pentest_ingest 参数 schema(预设建不了会话)
修复:pentest_ingest 参数 schema 非法 → 渗透预设建不了会话。
症状
装上 v1.6.8 后建渗透会话直接失败:
agent-preset/invalid: pentest (@pipadeep/dsh-pentest/pentest):
unsupported JSON schema: schema.type must be string/number/integer/boolean/null/array/object/json, or use oneOf
根因
新增工具的 files 参数写成 { type: "array", required: true, description } —— 缺 items。
JSON Schema 里数组必须声明 items,dsh 在装配预设时拒绝,于是整份预设不可用。
修复
files补items: { type: "string" }release-check新增第 6c 项:静态扫lib/与preset/源码,
type: "array"必须在同一个对象字面量内声明items。
实现用括号匹配(先把字符串字面量等长屏蔽),不是按窗口长度猜 ——
本仓库原就有 4 处「长 description 之后才有 items」的写法,窗口式会误报。
反向验证:去掉 items 立刻报错。- 自检与
pipacodedeep共用,已同步(那边发 0.1.5)。
验证
npm run check 29/29。
v1.6.8 — 修 files 漏 .mjs(插件加载失败)
紧急修复:lib/ingest.mjs 没进包 → 插件加载失败、预设整份不可用。
症状
装上 v1.6.7 后,渗透预设建不了会话(session/create 失败),宿主日志有加载错误。
根因
package.json 的 files 写的是 lib/**/*.js,没有 lib/**/*.mjs ——
新增的 lib/ingest.mjs 没被打进 tarball,而 lib/pentest.js 里 import "./ingest.mjs"
在用户机器上直接 MODULE_NOT_FOUND,插件加载失败。
这与早期「
scripts/没进 files」是同一类事故:固定清单式的打包自检发现不了配置漂移。
修复
files补lib/**/*.mjsrelease-check新增第 6b 项:从已打包文件里追相对 import,任何目标不在包里就拒绝发版。
反向验证过:把lib/**/*.mjs去掉,6b 立刻报错。- 该自检脚本与
pipacodedeep共用一份,已同步(那边随后发 0.1.5)
验证
npm run check 28/28;装上后预设可建会话,lib/ingest.mjs 随包存在。
v1.6.7 — 武器输出结构化解析(P0)
P0:武器输出 → 结构化落库(路线图第 1 项主体)
问题
代码里没有任何解析器:nmap/nuclei 的输出动辄上千行,靠 agent 逐条 pentest_add_asset /
pentest_add_fact 必然漏项、重复、丢字段,且无法度量覆盖率。
新增
lib/ingest.mjs:纯函数解析器(零依赖、零 I/O、可复现)- nmap
-oXXML → ip/subdomain 资产、port/service fact、脚本输出 info(只收 open 端口) - nuclei
-jsonl→kind=vuln候选(severity / template-id / matcher / extracted) - httpx
-jsonl→ 存活端点 +httpfact(title/tech/webserver/状态码) - ffuf
-of json→ 端点候选 +httpfact - masscan
-oJ/ naabu-json→ 端口 fact kind: auto按内容嗅探,嗅探不出报错而不猜- 坏行/缺字段只记
notes,绝不静默丢数据
- nmap
pentest_ingest工具(决策层):读文件(≤64MB)→ 解析 → 合并去重 → 落库- 去重键:资产
type|value、事实kind|target|detail;重复只合并来源 - 每条记录带
sources=文件名@sha256前12位(溯源) - 资产按父类优先创建,解析器只给逻辑父子(不给 id),id 由工具解析
- 已加入子 agent 的
toolFilter.deny(store 写入仍归决策 agent)
- 去重键:资产
- 明确不产出 finding:nuclei 命中落成
vulnfact,必须验证后才能pentest_add_finding
测试
新增 test/ingest.test.mjs 30 项(真实工具输出样例:类型嗅探、字段完整性、
前缀陷阱、坏行留痕、去重合并、可复现性、坏输入报错)。npm test 共 11 个测试文件全绿。
同时补上已知事故的回归测试与文档(test/repair-v0-logs.test.mjs 15 项 + 旧会话修复章节),
并新增 ROADMAP.md 记录 1-10 项补齐计划的交付物与验收标准。