🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

渗透测试编排 fb0sh/dsh-pentester

DeepSeek Harnessv6.5.0
fb0sh6 天前有提交已提供中文文档扫描:含敏感能力

面向 DeepSeek Harness 的最小化 Root-Orchestrator PTES 渗透测试插件。

56.8/100
综合分
80
GitHub 星标
837
npm 周下载
—/5
用户评分

数据截至 2026/10/29 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-pentester
npm 源 · dsh-pentester 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · market
装得上吗
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 6 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-pentester @ 6.5.0
✓Node 引擎要求 ^22.19 || >=24 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/30 09:03:18

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 304 处,展示前 101 条)
  • 读取本地文件
    lib/index.js:455
    text = readFileSync(file, "utf8");
  • 读取本地文件
    lib/index.js:666
    entries = readdirSync(dir, { withFileTypes: true });
  • 读取本地文件
    lib/index.js:743
    text = readFileSync(skillFile, "utf8");
  • 读取本地文件
    lib/index.js:823
    entries = readdirSync(dir, { withFileTypes: true });
  • 读取本地文件
    lib/index.js:840
    total += statSync(full).size;
  • 读取本地文件
    lib/index.js:848
    if (statSync(skillFile).size > 262144) errors.push(diag("skill_manifest_too_large", bundleDir, source, `SKILL.md exceeds ${SKILL_MD_MAX_BYTES} bytes`,
  • 写入本地文件
    lib/index.js:984
    mkdirSync(this.opts.customAgentsRoot, { recursive: true });
  • 写入本地文件
    lib/index.js:985
    mkdirSync(this.opts.customSkillsRoot, { recursive: true });
  • 删除本地文件
    lib/index.js:1368
    rmSync(join(this.opts.customAgentsRoot, id), {
  • 删除本地文件
    lib/index.js:1423
    rmSync(dir, {
  • 删除本地文件
    lib/index.js:1435
    rmSync(join(this.opts.agentOverridesRoot, `${id}.yml`), { force: true });
  • 写入本地文件
    lib/index.js:1444
    mkdirSync(this.opts.agentOverridesRoot, { recursive: true });
  • 写入本地文件
    lib/index.js:1447
    writeFileSync(tmp, serializeAgentOverride(override), "utf8");
  • 写入本地文件
    lib/index.js:1448
    renameSync(tmp, file);
  • 删除本地文件
    lib/index.js:1491
    rmSync(skill.bundlePath, {
  • 写入本地文件
    lib/index.js:1583
    mkdirSync(dir, { recursive: true });
  • 删除本地文件
    lib/index.js:8067
    await rm(ctx.targetRoot, {
  • 删除本地文件
    lib/index.js:9480
    await rm(tmp, { force: true }).catch(() => void 0);
  • 执行外部命令固定命令
    lib/index.js:14389
    execFile("git", [...args], {
  • 发起网络请求
    lib/index.js:15203
    return new EnvHttpProxyAgent();
  • 发起网络请求
    lib/index.js:15217
    response = dispatcher === void 0 ? await fetch(url, {
  • 读取本地文件
    presets/pentester/run-state.mjs:96
    if (!existsSync(file)) return null
  • 读取本地文件
    presets/pentester/run-state.mjs:98
    return JSON.parse(readFileSync(file, 'utf8'))
  • 读取本地文件
    presets/pentester/run-state.mjs:112
    if (!existsSync(file)) return null
  • 读取本地文件
    presets/pentester/run-state.mjs:114
    return JSON.parse(readFileSync(file, 'utf8'))
  • 读取本地文件
    presets/pentester/run-state.mjs:122
    if (!existsSync(head)) return 'main'
  • 读取本地文件
    presets/pentester/run-state.mjs:124
    const content = readFileSync(head, 'utf8').trim()
  • 读取本地文件
    lib/sudo-DtTdcB1Y.js:337
    entries = await readdir(dir);
  • 读取本地文件
    lib/sudo-DtTdcB1Y.js:347
    info = await lstat(abs);
  • 删除本地文件
    lib/sudo-DtTdcB1Y.js:352
    if (!seen.has(rel)) await rm(abs, { force: true }).catch(() => void 0);
  • 读取本地文件
    lib/sudo-DtTdcB1Y.js:357
    if ((await readdir(abs).catch(() => [])).length === 0 && !seen.has(rel) && !excluded.has(entry)) await rm(abs, {
  • 删除本地文件
    lib/sudo-DtTdcB1Y.js:357
    if ((await readdir(abs).catch(() => [])).length === 0 && !seen.has(rel) && !excluded.has(entry)) await rm(abs, {
  • 删除本地文件
    lib/sudo-DtTdcB1Y.js:361
    } else if (!seen.has(rel)) await rm(abs, { force: true }).catch(() => void 0);
  • 发起网络请求
    lib/vendor/dsh-mcp-client-sse.js:124
    return client.request({
  • 发起网络请求
    lib/vendor/dsh-mcp-client-sse.js:131
    return client.request({
  • 读取本地文件
    lib/runtime-B0U-zaML.js:82
    const source = createReadStream(localPath);
  • 写入本地文件
    lib/runtime-B0U-zaML.js:91
    const target = createWriteStream(localPath);
  • 读取本地文件
    lib/runtime-B0U-zaML.js:315
    for (const candidate of [join(here, ".."), join(here, "..", "..")]) if (existsSync(join(candidate, "package.json"))) return candidate;
  • 读取本地文件
    lib/runtime-B0U-zaML.js:389
    if (!existsSync(scriptPath)) throw new Error(`toolbox-catalog: missing ${SCRIPT_REL} at ${scriptPath}`);
  • 读取本地文件
    lib/runtime-B0U-zaML.js:390
    cached = parseKaliToolboxScript(readFileSync(scriptPath, "utf8"));
  • 读取本地文件
    lib/runtime-B0U-zaML.js:920
    entries = await readdir(localDir);
  • 读取本地文件
    lib/runtime-B0U-zaML.js:931
    info = await lstat(abs);
  • 写入本地文件
    lib/runtime-B0U-zaML.js:958
    await mkdir(join(localDir, rel), { recursive: true });
  • 写入本地文件
    lib/runtime-B0U-zaML.js:973
    await mkdir(dirname(target), { recursive: true });
  • 写入本地文件
    lib/runtime-B0U-zaML.js:977
    await rename(tmp, target);
  • 删除本地文件
    lib/runtime-B0U-zaML.js:979
    await rm(tmp, { force: true }).catch(() => void 0);
  • 读取本地文件
    lib/runtime-BB0bKz9z.js:82
    const source = createReadStream(localPath);
  • 写入本地文件
    lib/runtime-BB0bKz9z.js:91
    const target = createWriteStream(localPath);
  • 读取本地文件
    lib/runtime-BB0bKz9z.js:315
    for (const candidate of [join(here, ".."), join(here, "..", "..")]) if (existsSync(join(candidate, "package.json"))) return candidate;
  • 读取本地文件
    lib/runtime-BB0bKz9z.js:389
    if (!existsSync(scriptPath)) throw new Error(`toolbox-catalog: missing ${SCRIPT_REL} at ${scriptPath}`);
  • 读取本地文件
    lib/runtime-BB0bKz9z.js:390
    cached = parseKaliToolboxScript(readFileSync(scriptPath, "utf8"));
  • 读取本地文件
    lib/runtime-BB0bKz9z.js:1053
    entries = await readdir(localDir);
  • 读取本地文件
    lib/runtime-BB0bKz9z.js:1064
    info = await lstat(abs);
  • 写入本地文件
    lib/runtime-BB0bKz9z.js:1091
    await mkdir(join(localDir, rel), { recursive: true });
  • 写入本地文件
    lib/runtime-BB0bKz9z.js:1106
    await mkdir(dirname(target), { recursive: true });
  • 写入本地文件
    lib/runtime-BB0bKz9z.js:1110
    await rename(tmp, target);
  • 删除本地文件
    lib/runtime-BB0bKz9z.js:1112
    await rm(tmp, { force: true }).catch(() => void 0);
  • 读取本地文件
    lib/runtime-CkIju_Cz.js:81
    const source = createReadStream(localPath);
  • 写入本地文件
    lib/runtime-CkIju_Cz.js:90
    const target = createWriteStream(localPath);
  • 读取本地文件
    lib/runtime-CkIju_Cz.js:795
    entries = await readdir(localDir);
  • 读取本地文件
    lib/runtime-CkIju_Cz.js:806
    info = await lstat(abs);
  • 写入本地文件
    lib/runtime-CkIju_Cz.js:846
    await mkdir(dirname(target), { recursive: true });
  • 写入本地文件
    lib/runtime-CkIju_Cz.js:850
    await rename(tmp, target);
  • 删除本地文件
    lib/runtime-CkIju_Cz.js:852
    await rm(tmp, { force: true }).catch(() => void 0);
  • 读取本地文件
    lib/runtime-D5tI6R3t.js:82
    const source = createReadStream(localPath);
  • 写入本地文件
    lib/runtime-D5tI6R3t.js:91
    const target = createWriteStream(localPath);
  • 读取本地文件
    lib/runtime-D5tI6R3t.js:315
    for (const candidate of [join(here, ".."), join(here, "..", "..")]) if (existsSync(join(candidate, "package.json"))) return candidate;
  • 读取本地文件
    lib/runtime-D5tI6R3t.js:389
    if (!existsSync(scriptPath)) throw new Error(`toolbox-catalog: missing ${SCRIPT_REL} at ${scriptPath}`);
  • 读取本地文件
    lib/runtime-D5tI6R3t.js:390
    cached = parseKaliToolboxScript(readFileSync(scriptPath, "utf8"));
  • 读取本地文件
    lib/runtime-D5tI6R3t.js:1053
    entries = await readdir(localDir);
  • 读取本地文件
    lib/runtime-D5tI6R3t.js:1064
    info = await lstat(abs);
  • 写入本地文件
    lib/runtime-D5tI6R3t.js:1091
    await mkdir(join(localDir, rel), { recursive: true });
  • 写入本地文件
    lib/runtime-D5tI6R3t.js:1106
    await mkdir(dirname(target), { recursive: true });
  • 写入本地文件
    lib/runtime-D5tI6R3t.js:1110
    await rename(tmp, target);
  • 删除本地文件
    lib/runtime-D5tI6R3t.js:1112
    await rm(tmp, { force: true }).catch(() => void 0);
  • 读取本地文件
    lib/runtime-DcRIHRYS.js:81
    const source = createReadStream(localPath);
  • 写入本地文件
    lib/runtime-DcRIHRYS.js:90
    const target = createWriteStream(localPath);
  • 读取本地文件
    lib/runtime-DcRIHRYS.js:795
    entries = await readdir(localDir);
  • 读取本地文件
    lib/runtime-DcRIHRYS.js:806
    info = await lstat(abs);
  • 写入本地文件
    lib/runtime-DcRIHRYS.js:833
    await mkdir(join(localDir, rel), { recursive: true });
  • 写入本地文件
    lib/runtime-DcRIHRYS.js:848
    await mkdir(dirname(target), { recursive: true });
  • 写入本地文件
    lib/runtime-DcRIHRYS.js:852
    await rename(tmp, target);
  • 删除本地文件
    lib/runtime-DcRIHRYS.js:854
    await rm(tmp, { force: true }).catch(() => void 0);
  • 读取本地文件
    lib/sudo-CGzKK9iO.js:337
    entries = await readdir(dir);
  • 读取本地文件
    lib/sudo-CGzKK9iO.js:347
    info = await lstat(abs);
  • 删除本地文件
    lib/sudo-CGzKK9iO.js:352
    if (!seen.has(rel)) await rm(abs, { force: true }).catch(() => void 0);
  • 读取本地文件
    lib/sudo-CGzKK9iO.js:357
    if ((await readdir(abs).catch(() => [])).length === 0 && !seen.has(rel) && !excluded.has(entry)) await rm(abs, {
  • 删除本地文件
    lib/sudo-CGzKK9iO.js:357
    if ((await readdir(abs).catch(() => [])).length === 0 && !seen.has(rel) && !excluded.has(entry)) await rm(abs, {
  • 删除本地文件
    lib/sudo-CGzKK9iO.js:361
    } else if (!seen.has(rel)) await rm(abs, { force: true }).catch(() => void 0);
  • 读取本地文件
    lib/workspace-mirror-6mBGN-uN.js:337
    entries = await readdir(dir);
  • 读取本地文件
    lib/workspace-mirror-6mBGN-uN.js:347
    info = await lstat(abs);
  • 删除本地文件
    lib/workspace-mirror-6mBGN-uN.js:352
    if (!seen.has(rel)) await rm(abs, { force: true }).catch(() => void 0);
  • 读取本地文件
    lib/workspace-mirror-6mBGN-uN.js:357
    if ((await readdir(abs).catch(() => [])).length === 0 && !seen.has(rel) && !excluded.has(entry)) await rm(abs, {
  • 删除本地文件
    lib/workspace-mirror-6mBGN-uN.js:357
    if ((await readdir(abs).catch(() => [])).length === 0 && !seen.has(rel) && !excluded.has(entry)) await rm(abs, {
  • 删除本地文件
    lib/workspace-mirror-6mBGN-uN.js:361
    } else if (!seen.has(rel)) await rm(abs, { force: true }).catch(() => void 0);
  • 读取本地文件
    lib/workspace-mirror-DGNfzzvc.js:333
    entries = await readdir(dir);
  • 读取本地文件
    lib/workspace-mirror-DGNfzzvc.js:343
    info = await lstat(abs);
  • 删除本地文件
    lib/workspace-mirror-DGNfzzvc.js:348
    if (!seen.has(rel)) await rm(abs, { force: true }).catch(() => void 0);
  • 读取本地文件
    lib/workspace-mirror-DGNfzzvc.js:353
    if ((await readdir(abs).catch(() => [])).length === 0 && !excluded.has(entry)) await rm(abs, {
  • 删除本地文件
    lib/workspace-mirror-DGNfzzvc.js:353
    if ((await readdir(abs).catch(() => [])).length === 0 && !excluded.has(entry)) await rm(abs, {
  • 删除本地文件
    lib/workspace-mirror-DGNfzzvc.js:357
    } else if (!seen.has(rel)) await rm(abs, { force: true }).catch(() => void 0);
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-agent@deepseek-ai/dsh-agent-preset@deepseek-ai/dsh-agent-preset-registry@deepseek-ai/dsh-api-session-controller@deepseek-ai/dsh-attachment@deepseek-ai/dsh-client-store@deepseek-ai/dsh-client-ui-chat@deepseek-ai/dsh-client-ui-primitives@deepseek-ai/dsh-client-ui-session@deepseek-ai/dsh-llm@deepseek-ai/dsh-persona
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

界面预览

6 张 · 点击查看大图

功能亮点

  • 多Agent渗透测试编排
  • 自动化侦察与漏洞分析

基于 DeepSeek Harness 的多智能体 PTES 渗透测试编排插件,支持自动化侦察、漏洞分析、验证与报告,使用 Docker/Kali 隔离工具箱。

v6.5.02026-10-14
· 6.5.0(2026-10-14) · 问题修复 · 预设:挂载官方压缩组(compaction-basic / command-compact / tool-result-pruner)(#40)(7379abb) · 子代理:兼容新版 Harness 的 startActivation 入口(#38)(422af4d) · 杂项 · 触发 6.5.0 发布(ddaf752)
v6.4.02026-10-13
· 6.4.0 (2026-10-13) · Features · 产出 Tab 重构为结论/资产工作区/素材三段 (46f3dd9) · Bug Fixes · 回填 Agent Edit 的 systemPromptAppend 并支持 custom Skill 编辑/删除 (fa717a1) · 非活动 Pentester 页签改用 display:none,避免探索图残影与点击劫持 (fa503e6)
v6.3.02026-10-10
· 6.3.0 (2026-10-10) · Features · per-asset task layout, Root exec, and exploration UI (cfa00c8)
原文(未汉化)
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。

README

由 DeepSeek 最新模型翻译生成
dsh-pentester 面向 DeepSeek Harness 的最小化 Root-Orchestrator PTES 渗透测试插件。 内置 1011 个渗透测试技能(7 个 bundle + 16 个 standalone),覆盖 Kali 工具、PTES 全阶段、CTF、逆向、白盒审计、漏洞知识库与报告生成。 19 个内置专家智能体按 PTES 阶段编排;MCP 集成支持 STDIO / Streamable HTTP / Legacy SSE 三种 transport(Legacy SSE 可直连 PortSwigger Burp MCP Server,无需代理中转)。PTES 阶段可为该阶段所有 Worker 共享技能 / MCP server,也可配置跨阶段的 Global Worker 共享能力。 唯一事实来源是 docs/plan.md;架构视图见 docs/architecture.md,磁盘布局见 docs/workspace.md,领域术语见 CONTEXT.md。技能能力运行时见 docs/skill-runtime-v4.md(Native DSH Skill 集成)。 渗透会话里的探索链路、资产图与报告视图,参考并融合了 howmp/dsh-pentest 的界面与链路呈现(Goal / Intent / Fact / Asset)。
展开完整文档(README 剩余 1 节)
dsh-pentester

面向 DeepSeek Harness 的最小化 Root-Orchestrator PTES 渗透测试插件。

内置 1011 个渗透测试技能(7 个 bundle + 16 个 standalone),覆盖 Kali 工具、PTES 全阶段、CTF、逆向、白盒审计、漏洞知识库与报告生成。

19 个内置专家智能体按 PTES 阶段编排;MCP 集成支持 STDIO / Streamable HTTP / Legacy SSE 三种 transport(Legacy SSE 可直连 PortSwigger Burp MCP Server,无需代理中转)。PTES 阶段可为该阶段所有 Worker 共享技能 / MCP server,也可配置跨阶段的 Global Worker 共享能力。

唯一事实来源是 docs/plan.md;架构视图见 docs/architecture.md,磁盘布局见 docs/workspace.md,领域术语见 CONTEXT.md。技能能力运行时见 docs/skill-runtime-v4.md(Native DSH Skill 集成)。

渗透会话里的探索链路、资产图与报告视图,参考并融合了 howmp/dsh-pentest 的界面与链路呈现(Goal / Intent / Fact / Asset)。漏洞视图是本仓库自己的实现。编排、持久化与工具面仍以本仓库的 PTES Root-Orchestrator 为准(run.json + Delegation,不引入对方的 sqlite 存储或 pentest_ 工具面)。

⚠️ 免责声明

本项目是网络安全测试工具,仅可用于以下场景:

已获得目标系统所有者明确书面授权的渗透测试、红队演练与安全评估;
* CTF 竞赛、靶场、实验室环境与自有资产的测试;
* 安全教学、研究与工具开发。

使用者必须自行确认测试范围与授权边界。未经授权对第三方系统进行扫描、探测、入侵或任何形式的攻击,在多数国家和地区均属违法行为,由此产生的一切后果由使用者自行承担。

本插件按 "AS IS" 现状提供,不附带任何明示或暗示的担保(包括但不限于适销性、特定用途适用性与不侵权)。作者与贡献者对因使用或滥用本插件而导致的任何直接或间接损失、数据破坏、服务中断、法律纠纷或第三方索赔不承担任何责任。

请特别注意:插件内置的 ask_user 预授权门、RoE / Scope 提示词注入、镜像白名单与容器硬化,是协作约定与风险降低措施,不构成技术防护措施,也不代表任何法律授权;它无法阻止有意的滥用。使用者还需自行遵守所在地法律法规,以及 DeepSeek Harness、Kali 工具集、Burp Suite、第三方 MCP Server 等各组件的许可与使用条款。

下载、安装或使用本插件即表示你已阅读、理解并同意上述条款;若不同意,请勿使用。

Disclaimer (English summary): This project is a security testing tool intended only for authorized penetration testing, red teaming, CTFs, lab environments, education and research. You must obtain explicit written permission from the owner of any system you test. Unauthorized scanning or attacking of third-party systems is illegal in most jurisdictions, and you alone are responsible for your actions. The software is provided "AS IS", without warranty of any kind; the authors and contributors accept no liability for any damage or legal consequence arising from its use or misuse. The built-in pre-authorization gate, RoE/Scope prompts, image allow-list and container hardening are collaborative risk-reduction measures, not a technical safeguard or a legal authorization.

Builtin Skill Pack 独立分发:上述 Builtin Skills 作为独立 GitHub Release Asset 分发,不随 npm package 安装。首次使用时在 Settings → Pentester → Skills → 初始化 Builtin Skills 点击下载安装。Custom Skills 放在 $DSH_HOME/dsh-pentester/skills/,与 Builtin Skill Pack 完全隔离。

Skill Runtime V4:Worker 的 Skill 加载已完全融入 DeepSeek Harness 原生 Skill 生态 —— Delegation 创建时冻结 grant(Host-private snapshot + manifest),Worker 以官方
skill({name}) 工具按需加载,catalog 与会话记录由官方 dsh-tool-skill 产生,
前端直接用官方 Skill Row 渲染。旧 pentester_skill_search / pentester_skill_load 已退役(历史会话仍可回放)。

欢迎提交issues和PR。

详细英文文档见 docs/README.md。

心智模型

User ⇄ DSH Root Session(pentester persona preset) → Root 是唯一 Orchestrator:判断缺口、派发 Delegation、决定推进/回溯阶段 → Root 工具面:pentester_run / pentester_delegate / pentester_cancel_delegation / pentester_advance_stage / pentester_rollback_stage / pentester_exec(仅用户在 Root 会话当面要求时;cwd = task/_root/work) → pentester_run 是唯一生命周期入口(action: start | stop | resume | restart | status) → 一次 IP/URL 列表仍是一个 PentestRun(inScopeAssets);2+ 资产时本阶段每个资产都要有 closed Delegation 的 covers 才能 advance → Root 每次 reasoning 前注入 compact run state(target/branch/stage/delegations) Delegation(并行多个)= 各一个 DSH continuable child session(AgentProfile + 不可变 task_prompt) → Worker 工具:pentester_exec(Runtime 无关)+ 官方 skill tool(child-scoped frozen SkillProvider,Root 不可见) → Runtime:Docker 或 SSH,每个 PentestRun 创建时冻结(Settings → Runtimes);SSH 与 Kali Toolbox 共用期望清单,用到才装,sudo 只问一次 → Worker 的 Skill catalog 由 Harness 官方注入(frozen grant 精确边界) → Worker 写/更新 result.md 作为当前可交付结果(continuable child 跨轮持续)
Deliverable = 文件(workspace/task/<asset>/<NN>-<stage>/D-00N/)

基于 docker 的工具箱

设置界面

仅通过 dockerode 与 docker daemon 交互,定期文件同步,允许远程 docker server,可降低本机资源占用。

工具集详见 docker/kali

添加自己的 Skill

在 ~/.dsh/dsh-pentester/skills/ 下建一个文件夹放一个 SKILL.md 即可:

~/.dsh/dsh-pentester/skills/
└── my-waf-bypass.skill/
└── SKILL.md # name + description + 指令正文

目录热更新,无需重启;在 Settings → Agent Library 里 grant 给某个 Agent 后,之后新建的 Worker 会在原生 skill catalog 中看到它(模型自行决定
skill({name}) 加载)。详见
docs/skill-runtime-v4.md §4.1。

Skill Runtime V4(原生 DSH Skill)

Worker 调用 Skill 与普通 DeepSeek Harness 会话完全同构:Agent Library 冻结 grant → child-scoped frozen SkillProvider → 官方 dsh-tool-skill 的 durable catalog 与 skill({name}) 工具 → 标准的 <skill_content> 结果与官方 Skill Row UI。

Worker 会话里模型自主路由并加载 Skill(官方 Skill Row,与普通 DSH 会话无差异)

Trace 拓扑:每个成功加载的 Skill 是 Agent 节点外侧的一个芯片元素,用线连接

Output:每 Delegation 的 loaded_skills.md(native 会话事件审计投影)

Pentester Settings

Settings → Pentester 提供完整的插件配置面(Overview / Agent Library / Runtimes / Version 四个顶层 Tab):

Overview:状态摘要(Docker / Toolbox / Skills / Agents / MCP)+ PTES 阶段管线(每阶段参与编排的 Agent)

Agent Library:19 个内置专家 Agent(按 PTES 阶段分工,可 Customize 覆盖 skill/MCP 分配)

PTES Assignment(Stage / Global 共享能力)

每个 PTES 阶段除了指派参与编排的 Agent,还可以配置该阶段所有 Worker 共享的 Skills 与 MCP server;页面顶部的 Global Worker Capabilities 则把共享能力下发给所有 Worker 阶段。共享能力是 additive 的(叠加在 Agent 自身能力之上),并在 Delegation 创建时冻结 —— 已创建的 Worker 不受后续配置变化影响。Root 不继承任何共享能力(仍是纯 Orchestrator 的正向 allow-list)。

MCP 三种 Transport(含 PortSwigger Burp 兼容)

MCP Server 支持三种 transport:STDIO(本地进程)、Streamable HTTP(现代远端协议,推荐)、Legacy SSE(旧式 HTTP+SSE 兼容 —— 如 PortSwigger Burp MCP Server,http://127.0.0.1:9876)。Legacy SSE 的 sessionId 握手由官方 MCP SDK 完成,无需手工配置;旧式 server 不再需要 mcp-proxy 中转。

Transport 选择器(完整协议名称,不混淆两种 HTTP 协议)

Burp Suite 以 Legacy SSE 直连:Loaded · 27 tools

Version

Host / Client / Skill Pack 构建版本一目了然(host 与 client bundle 不一致时给出刷新提示):

展示

渗透测试模式

授权确认

问题诊断

使用docker镜像

看板与子代理

各个TAB

时间轴阶段拓扑

阶段产出

子代理自动汇合推进

报告

查看报告

准备

需要 DeepSeek Harness 0.2.x(dsh >=0.2.0-rc.1 <0.3.0;0.1.x 宿主会在安装/启动时被 peerDependencies 兼容闸门明确拒绝)。

已在以下宿主上实测插件激活(5 个 RPC endpoint 注册 + preset / MCP scope 绑定):

| dsh 版本 | 渠道 | 结果 |
| 0.2.0-rc.2 | latest / next | ✅ |
| 0.2.1-alpha.1 | alpha | ✅ |

安装deepseek harness

npm install -g @deepseek-ai/dsh
准备 Docker 镜像
docker pull fb0sh/dsh-pentester-kali:latest

安装

npm 源
dsh plugin --profile web add dsh-pentester@latest

github 源
dsh plugin --profile web add github:fb0sh/dsh-pentester

dsh plugin add 只把包装进 profile 的依赖;还要把它选为 profile bundle(0.2.x 起 preset 与插件行都由 bundle patch 声明):

- GUI:Plugins 页 → 选中 dsh-pentester;
- 或由 Agent 调用 plugin_manager 的 install_bundle;
- 或手工把 "dsh-pentester" 加进 profile package.json 的 dsh.profile.bundles。

首次安装时 pnpm 可能因依赖的构建脚本(ssh2 / cpu-features / protobufjs)而暂停:按 Plugins 页提示允许或拒绝这些脚本后重试即可。

安装后需要重启 dsh

布局

| 目录/文件 | 职责 |
| src/ | model/stages/store、workspace/git、dsh(childId 预留)/delegations/tools、docker/(host/connection/images/runtime)、rpc/settings-store、targets、migrate、host-manifest、invocations、build-id、index |
| src/native-skill/ | Skill Runtime V4:frozen manifest、child-scoped SkillProvider(dsh-pentester-frozen)、agent/created mount seam、native audit 投影、legacy name 迁移 |
| src/agent-library/ | Agent Library 组合根(profiles/skills/bundles/settings v2/watcher) |
| src/pentest/ | pre-engagement/assets/findings 领域逻辑 |
| src/ui/client/ | Settings 的 "Pentester Config" 页 + Pentester Tab(概览 / 阶段 / 资产 / 轨迹 / 探索链路 / 漏洞 / 产出 / 报告) |
| src/ui-view/ | Pentester 数据面板(snapshot / native skill audit 投影 / RPC) |
| agents/*/profile.yml | 19 个 Builtin AgentProfile(Agent Topology V3:18 个进入默认 PTES 编排 + library-only ctf;见 docs/agent-skill-allocation.md) |
| docker/ | Toolbox Dockerfile(kali 等,镜像白名单来源) |
| presets/pentester/ | 0.2.x Root persona preset(preset.patch.yml:@deepseek-ai/dsh-agent-preset 行的 config.plugins)+ run-state.mjs(工具面限制 + native skill provider 挂载 + 动态状态注入 + MCP scope 握手) |

开发

pnpm run check # typecheck + build(含 client bundle)
pnpm test # node --test

Docker host 优先级:Settings(settings.json)> 插件配置 > 本地 socket 自动发现 > DOCKER_HOST > 默认 socket。本地 Docker 按 Worker 白名单顶层目录逐目录 bind(.git/ 与 .dsh-pentester/ 物理上不在容器内);远程 daemon 用共享 volume,阶段边界才做 mirror sync(push/pull 双向排除控制态、原子发布、不跟随 symlink)。
预览分享卡片长什么样 ↓fb0sh/dsh-pentester
分享 · DeepSeek Harness Hub
fb0sh/dsh-pentester

面向 DeepSeek Harness 的最小化 Root-Orchestrator PTES 渗透测试插件。

回到顶部