dsh-pentester
September 6, 2026 · View on GitHub
A minimal Root-Orchestrator PTES penetration testing plugin for DeepSeek Harness.
961 built-in pentesting skills (6 bundles + 5 standalone), covering Kali tooling, the full PTES stage lifecycle, CTF, reverse engineering, vulnerability knowledge bases, and report generation.
The single source of truth is docs/plan.md; see docs/architecture.md for the architecture view, docs/workspace.md for the disk layout, and docs/skill-runtime-v4.md for the skill runtime (Native DSH Skill integration).
Builtin Skill Pack ships separately: the builtin skills above are distributed as a standalone GitHub Release asset, not installed with the npm package. Initialize them on first use via Settings → Pentester → Skills → Initialize Builtin Skills. Custom skills live under
$DSH_HOME/dsh-pentester/skills/, fully isolated from the builtin pack.
Skill Runtime V4: worker skill loading is now part of the native DSH skill ecosystem — grants are frozen per Delegation (host-private snapshot + manifest), workers load skills through the official
skill({name})tool, and the catalog, session records, and conversation UI are produced by the officialdsh-tool-skill/dsh-client-ui-skillplugins. The legacypentester_skill_search/pentester_skill_loadtools are retired (old sessions still replay).
Mental Model
User ⇄ DSH Root Session (pentester persona preset)
→ Root is the sole Orchestrator: identifies gaps, dispatches Delegations,
decides when to advance or roll back stages
→ Root tool surface (5 tools): pentester_run / pentester_delegate /
pentester_cancel_delegation / pentester_advance_stage / pentester_rollback_stage
→ pentester_run is the sole lifecycle entry point
(action: start | stop | resume | restart | status)
→ Compact run state injected before each Root reasoning turn
(target / branch / stage / delegations)
Delegation (multiple in parallel) = one DSH continuable child session each
(AgentProfile + immutable task_prompt)
→ Worker tool surface: pentester_container_exec (dockerode) + the official skill tool (child-scoped frozen SkillProvider; invisible to Root)
→ Worker skill catalog is injected by the Harness itself (exact frozen grant boundary)
→ Worker writes/updates result.md as the current deliverable
(continuable child persists across turns)
Deliverable = files (workspace/stages/<NN>-<stage>/delegations/D-00N/)
Docker-based Toolbox
Interacts with the Docker daemon via dockerode only. Periodic file sync. Supports remote Docker servers to reduce local resource usage.
Tooling is defined in docker/kali.
Adding Your Own Skills
Drop a folder with a SKILL.md under ~/.dsh/dsh-pentester/skills/:
~/.dsh/dsh-pentester/skills/
└── my-waf-bypass.skill/
└── SKILL.md # name + description + instruction body
The directory hot-reloads (no restart). Grant it to an Agent in Settings →
Agent Library, and every newly created worker will see it in its native skill
catalog (the model decides when to call skill({name})). See
skill-runtime-v4.md §4.1.
Skill Runtime V4 (Native DSH Skills)
Worker skill calls are indistinguishable from an ordinary DSH session: the
Agent Library freezes the grant, a child-scoped SkillProvider feeds the
official dsh-tool-skill catalog and skill({name}) tool, and results render
through the official Skill Row.
The worker model routes and loads skills autonomously (official Skill Rows)
![]()
Trace topology: every successfully loaded skill is a chip linked to its agent node
![]()
Output: per-Delegation loaded_skills.md (native session event audit projection)
![]()
Installation
Install DeepSeek Harness:
npm install -g @deepseek-ai/dsh
Pull the toolbox image:
docker pull fb0sh/dsh-pentester-kali:latest
Install the plugin:
# npm registry
dsh plugin --profile web add dsh-pentester@latest
# GitHub
dsh plugin --profile web add github:fb0sh/dsh-pentester
Restart DSH after installation.
Layout
| Directory/File | Purpose |
|---|---|
src/ | model/stages/store, workspace/git, dsh (childId reservation)/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 projection, legacy name migration |
src/agent-library/ | Agent Library composition root (profiles/skills/bundles/settings v2/watcher) |
src/pentest/ | pre-engagement/assets/findings domain logic |
src/ui/client/ | Settings page + Pentester tab (Stages/Trace/Findings/Output) |
src/ui-view/ | Pentester data panel (snapshot / native skill audit projection / RPC) |
agents/*/profile.yml | 9 AgentProfiles (web/recon/threat-model/vulnerability/validation/impact/reporting/active-directory/cloud) |
docker/ | Toolbox Dockerfiles (kali etc., image allowlist source) |
presets/pentester/ | Root persona preset + run-state.mjs (tool restriction + native skill provider mount + dynamic state injection) |
Development
pnpm run check # typecheck + build (includes client bundle)
pnpm test # node --test
Docker host priority: Settings (settings.json) > plugin config > local socket auto-discovery > DOCKER_HOST > default socket. Local Docker bind-mounts each worker-visible top-level directory separately (.git/ and .dsh-pentester/ are physically absent from the container); a remote daemon uses a shared volume with mirror sync at stage boundaries (both directions exclude the host control plane, files publish atomically, symlinks are never followed).