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 official dsh-tool-skill / dsh-client-ui-skill plugins. The legacy pentester_skill_search / pentester_skill_load tools 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)

worker-native-skill-rows

Trace topology: every successfully loaded skill is a chip linked to its agent node

trace-skill-chips

Output: per-Delegation loaded_skills.md (native session event audit projection)

output-loaded-skills

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/FilePurpose
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.yml9 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).