pentest
Pentest / OSINT Skill
You have real Bash, real filesystem, real process execution, and a fleet of pentest tools one wrapper call away. Use the wrappers — manual curl loops are a fallback, not a default.
Step 0 — Preflight (run first, every session)
python ${CLAUDE_PLUGIN_ROOT}/scripts/ht_preflight.py
Read the verdict and act:
ready→ state the backend in one sentence (e.g. "Running native on macOS" / "Running via Docker on Windows" / "Running native in WSL Ubuntu") and start work.partial→ tell the user what's missing (userecommendations); offer to proceed with reduced coverage.blocked→ stop. Surface the recommendations and wait. Do not substitute manualcurl/Invoke-WebRequestprobes for a missing tool — that misleads the user about coverage.
Re-run preflight if the user installs something, starts Docker, or switches into WSL.
Tool-first defaults
When the ask is "audit / scan / find vulns", reach for:
| Ask | Default chain |
|---|---|
| Subdomain enumeration | subfinder -all → httpx -title -tech-detect |
| Web vuln scan | nuclei -severity medium,high,critical |
| Port scan | nmap -sV -sC (or naabu for fast SYN sweep) |
| Directory / API discovery | ffuf -w wordlist -u https://target/FUZZ |
| Secret hunting | trufflehog filesystem . or gitleaks detect |
| Username / email investigation | holehe → sherlock → maigret |
| TLS audit | nuclei -tags ssl,tls |
| Domain OSINT | amass intel → theharvester |
Anti-patterns: for-looping curl across many paths instead of ffuf / nuclei; hand-parsing TLS output instead of nuclei -tags ssl; saying "I don't have nuclei" when preflight returned ready (you have it via Docker).
The execution model
Every tool runs through ht_run.py, which:
- Reads
ht_env.pyto pick a backend — native on Linux/macOS, WSL on Windows with a real distro, Docker anywhere with Docker Desktop. - Looks up a purpose-built Docker image for the tool if one exists (
instrumentisto/nmap,projectdiscovery/nuclei,caffix/amass, 20+ more). Falls back tokalilinux/kali-rolling. - Executes the command. Auto-retries with
sudo -non permission-denied (native/WSL). - Returns JSON:
status,stdout,stderr,returncode,command.
Only one pre-block: tools flagged interactive. Bypass with --force + --command if you have non-interactive args.
Bundled scripts
All at ${CLAUDE_PLUGIN_ROOT}/scripts/. Emit JSON.
| Script | Purpose |
|---|---|
ht_preflight.py |
Run first. Capability check + setup recommendations. |
ht_search.py |
Query the tool index (--q, --category, --tag, --capability, --os). |
ht_env.py |
Low-level env detect. (Preflight wraps this.) |
ht_run.py |
Execute. --command "..." to override, --args "..." to append, --network-host for LAN, --privileged for raw sockets, --force to bypass the interactive block. |
Golden path
- Preflight — handle verdict per Step 0.
- Read the ask — map to a workflow (
reference/workflows.md) and apply the defaults table. - Find tool ids —
ht_search.py --q "<keyword>". Don't guess; ids are namespaced (e.g.web_attack.Nuclei). - Execute —
ht_run.py <tool_id> --args "...", or--command "<full>"for tools whererunnable=False. Add--network-hostfor LAN,--privilegedfor raw sockets. - Parse status:
ok→ summarize highlights;error→ report stderr, decide whether to retry;fallback→ seereference/runtime-fallbacks.md;timeout→ raise--timeoutor chunk the scan. - Compose —
subfinder → httpx → nuclei,holehe → sherlock → maigret. Feed outputs forward.
Docker image overrides
ht_run.py maps common tools to purpose-built images (faster pulls, proper ENTRYPOINTs):
| Tool | Image |
|---|---|
| NMAP | instrumentisto/nmap |
| Nuclei | projectdiscovery/nuclei |
| Subfinder / Httpx / Katana | projectdiscovery/* |
| Amass | caffix/amass |
| TheHarvester | secsi/theharvester |
| Holehe / Maigret / SpiderFoot | official images |
| TruffleHog / Gitleaks | official images |
| Sqlmap | paoloo/sqlmap |
| Impacket / NetExec | rflathers/impacket, byt3bl33d3r/netexec |
Override with --docker-image my/image for one-offs.
Ad-hoc commands
Bash directly is fine for spot-checks: a single curl -I, arp -a, dig @8.8.8.8 example.com. Reach for ht_run.py whenever:
- The tool is in the index and you want auto image/backend selection.
- You're chaining multiple tools and want uniform JSON output.
- The task is enumeration / scanning / fuzzing at any scale (≥5 requests against a target).
If you're about to write a for loop hitting many paths with curl, stop — use ffuf / nuclei / gobuster instead.
References
${CLAUDE_PLUGIN_ROOT}/skills/pentest/reference/workflows.md— named playbooks${CLAUDE_PLUGIN_ROOT}/skills/pentest/reference/runtime-fallbacks.md— templates per fallback reason