From 9b426ce41dc5c4465ac6af4f64cbaaba5046a977 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 10:04:46 +0000 Subject: [PATCH 1/6] Render verification.env inside the Claude Code Docker container The dockerized claude-code container never received the pentest authorization document, so engagements were not recognized when running pentests there. The injection mechanism was wired only for the host/web path: the rendered .claude/verification-active.md was never mounted, the container could not render it (no blhackbox package, no entrypoint step), and the file is git-ignored so a direct bind-mount would have Docker auto-create it as an empty directory. Mount verification.env (always present in the repo) read-only and render it at container startup via the stdlib-only inject_verification.py + verification.md, baked into the image. This mirrors the host session-start hook, is footgun-free, and needs no host pre-step. If verification.env is absent or not ACTIVE, no document is written and the engagement is treated as unauthorized. --- DOCKER.md | 1 + README.md | 2 +- docker-compose.yml | 4 ++++ docker/claude-code-entrypoint.sh | 27 +++++++++++++++++++++++++++ docker/claude-code.Dockerfile | 7 +++++++ 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/DOCKER.md b/DOCKER.md index dcdf2ad..b324f7c 100644 --- a/DOCKER.md +++ b/DOCKER.md @@ -341,6 +341,7 @@ Portainer CE provides a web dashboard for all blhackbox containers. | `./output/sessions/` | `/root/results/` | Aggregated session JSON files | | `./.claude/skills/` | `/root/.claude/skills/` | Pentesting skills (read-only, claude-code only) | | `./CLAUDE.md` | `/root/CLAUDE.md` | Project instructions (read-only, claude-code only) | +| `./verification.env` | `/root/verification.env` | Pentest authorization config (read-only, claude-code only). The entrypoint renders it into `/root/.claude/verification-active.md` at startup. | --- diff --git a/README.md b/README.md index 730888d..32322d7 100644 --- a/README.md +++ b/README.md @@ -995,7 +995,7 @@ Window: 2026-03-01 09:00 — 2026-03-31 17:00 UTC Authorized by: Jane Smith ``` -**4. Start your session** — Claude Code will automatically pick up the verification document. On Claude Code Web, the session-start hook runs `inject-verification` automatically if `verification.env` exists. +**4. Start your session** — Claude Code will automatically pick up the verification document. On Claude Code Web, the session-start hook runs `inject-verification` automatically if `verification.env` exists. In the Dockerized Claude Code container (`make claude-code`), `verification.env` is mounted read-only and the entrypoint renders it into `/root/.claude/verification-active.md` at startup — no host pre-step required. ### Validation rules diff --git a/docker-compose.yml b/docker-compose.yml index b0dc95a..6a50732 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -345,6 +345,10 @@ services: # Mount skills and project instructions so Claude Code discovers them - ./.claude/skills:/root/.claude/skills:ro - ./CLAUDE.md:/root/CLAUDE.md:ro + # Pentest authorization config — rendered into the active verification + # document (/root/.claude/verification-active.md) at startup by the + # entrypoint, so Claude Code recognizes the engagement authorization. + - ./verification.env:/root/verification.env:ro depends_on: kali-mcp: condition: service_healthy diff --git a/docker/claude-code-entrypoint.sh b/docker/claude-code-entrypoint.sh index f48afb0..4b260e8 100755 --- a/docker/claude-code-entrypoint.sh +++ b/docker/claude-code-entrypoint.sh @@ -80,10 +80,37 @@ ln -sfn /root/reports /root/output/reports ln -sfn /root/results /root/output/sessions ln -sfn /tmp/screenshots /root/output/screenshots +# ── Pentest authorization document ────────────────────────────────── +# Render the mounted verification.env into the active authorization +# document that CLAUDE.md instructs Claude to read at session start. +# Mirrors the host session-start hook. Best-effort: if verification.env +# is absent, AUTHORIZATION_STATUS is not ACTIVE, or required fields are +# missing, no document is written and Claude treats the engagement as +# unauthorized. +render_verification() { + mkdir -p /root/.claude + echo -e " ${BOLD}Authorization${NC}" + if [ ! -f /root/verification.env ]; then + echo -e " [ ${WARN} ] verification.env not mounted — no authorization document" + return + fi + if python3 /opt/blhackbox-verify/inject_verification.py \ + --env /root/verification.env \ + --out /root/.claude/verification-active.md > /tmp/verification.log 2>&1; then + echo -e " [ ${CHECK} ] Active verification document loaded" + else + echo -e " [ ${WARN} ] $(head -n 1 /tmp/verification.log)" + echo -e " ${DIM}Fill verification.env and set AUTHORIZATION_STATUS=ACTIVE on the host.${NC}" + fi +} + # ── Main ──────────────────────────────────────────────────────────── print_banner +render_verification +echo "" + echo -e "${BOLD}Checking service connectivity...${NC}" echo -e "${DIM}Waiting for services to become healthy.${NC}" echo "" diff --git a/docker/claude-code.Dockerfile b/docker/claude-code.Dockerfile index 21fe975..01ff9ed 100644 --- a/docker/claude-code.Dockerfile +++ b/docker/claude-code.Dockerfile @@ -55,6 +55,13 @@ RUN echo '{ \ COPY CLAUDE.md /root/CLAUDE.md COPY .claude/skills /root/.claude/skills +# Verification renderer + template. inject_verification.py is stdlib-only and +# reads its template from the sibling verification.md, so both must live in the +# same directory. The entrypoint runs this at startup to render the mounted +# verification.env into /root/.claude/verification-active.md. +COPY blhackbox/prompts/inject_verification.py /opt/blhackbox-verify/inject_verification.py +COPY blhackbox/prompts/verification.md /opt/blhackbox-verify/verification.md + # Startup script: checks each MCP server, shows status, launches Claude. COPY docker/claude-code-entrypoint.sh /usr/local/bin/claude-code-entrypoint.sh RUN chmod +x /usr/local/bin/claude-code-entrypoint.sh From 6efc57acfa27c897cf7ad840700d2a71e7e3aec4 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 14:30:25 +0000 Subject: [PATCH 2/6] Remove deprecated verification.env authorization gate The verification.env / make inject-verification document gate blocked skill execution and is being replaced by a different document-based method later. Remove it wholesale for internal testing: - Delete inject_verification.py, verification.md template, verification.env - Drop load_verification() and the get_template authorization append - Remove the session-start hook injection step and Makefile target - Strip the 'Verify authorization is active' step from all 11 skills and 11 prompt templates (renumbering the surrounding checklists) - Revert the Docker claude-code verification mount/render wiring - Clean verification sections from CLAUDE.md, README.md, DOCKER.md, mcp/CLAUDE.md, setup.sh, .gitignore, and docs General 'only test what you are authorized to' framing is kept; only the enforced verification.env mechanism is removed. --- .claude/hooks/session-start.sh | 7 - .claude/skills/api-security/SKILL.md | 3 +- .claude/skills/bug-bounty/SKILL.md | 1 - .claude/skills/exploit-dev/SKILL.md | 1 - .claude/skills/full-attack-chain/SKILL.md | 3 +- .claude/skills/full-pentest/SKILL.md | 3 +- .../skills/network-infrastructure/SKILL.md | 3 +- .claude/skills/osint-gathering/SKILL.md | 3 +- .claude/skills/quick-scan/SKILL.md | 3 +- .claude/skills/recon-deep/SKILL.md | 3 +- .claude/skills/vuln-assessment/SKILL.md | 3 +- .claude/skills/web-app-assessment/SKILL.md | 3 +- .gitignore | 3 - CLAUDE.md | 39 +--- DOCKER.md | 1 - Makefile | 7 +- README.md | 142 +----------- blhackbox/mcp/CLAUDE.md | 2 - blhackbox/mcp/server.py | 25 +-- blhackbox/prompts/__init__.py | 13 -- blhackbox/prompts/inject_verification.py | 202 ------------------ blhackbox/prompts/templates/api-security.md | 3 +- blhackbox/prompts/templates/bug-bounty.md | 7 +- blhackbox/prompts/templates/exploit-dev.md | 1 - .../prompts/templates/full-attack-chain.md | 5 +- blhackbox/prompts/templates/full-pentest.md | 3 +- .../templates/network-infrastructure.md | 3 +- .../prompts/templates/osint-gathering.md | 3 +- blhackbox/prompts/templates/quick-scan.md | 1 - blhackbox/prompts/templates/recon-deep.md | 3 +- .../prompts/templates/vuln-assessment.md | 3 +- .../prompts/templates/web-app-assessment.md | 3 +- blhackbox/prompts/verification.md | 171 --------------- docker-compose.yml | 4 - docker/claude-code-entrypoint.sh | 27 --- docker/claude-code.Dockerfile | 7 - docs/pentagi-comparison.md | 1 - setup.sh | 4 +- verification.env | 112 ---------- 39 files changed, 32 insertions(+), 799 deletions(-) delete mode 100644 blhackbox/prompts/inject_verification.py delete mode 100644 blhackbox/prompts/verification.md delete mode 100644 verification.env diff --git a/.claude/hooks/session-start.sh b/.claude/hooks/session-start.sh index ff5e0f8..c9aa49c 100755 --- a/.claude/hooks/session-start.sh +++ b/.claude/hooks/session-start.sh @@ -26,13 +26,6 @@ fi # Export venv bin to PATH for the session echo "export PATH=\"$CLAUDE_PROJECT_DIR/.venv/bin:\$PATH\"" >> "$CLAUDE_ENV_FILE" -# Inject pentest verification document if verification.env is configured. -# This renders the authorization template and writes it to -# .claude/verification-active.md so Claude Code sees it in context. -if [ -f "verification.env" ]; then - .venv/bin/python -m blhackbox.prompts.inject_verification 2>&1 || true -fi - # Run MCP health check (informational — does not block startup) if [ -x ".claude/mcp-health-check.sh" ]; then .claude/mcp-health-check.sh 2>&1 || true diff --git a/.claude/skills/api-security/SKILL.md b/.claude/skills/api-security/SKILL.md index 0d540a4..5096b4a 100644 --- a/.claude/skills/api-security/SKILL.md +++ b/.claude/skills/api-security/SKILL.md @@ -31,8 +31,7 @@ Then gather optional details interactively: > **Before you start:** > 1. Ensure all MCP servers are healthy — run `make mcp-status` -> 2. Verify authorization is active — run `make inject-verification` -> 3. Query each MCP server's tool listing to discover available capabilities +> 2. Query each MCP server's tool listing to discover available capabilities ## Mandatory Tool & Methodology Readiness diff --git a/.claude/skills/bug-bounty/SKILL.md b/.claude/skills/bug-bounty/SKILL.md index bda709f..7346412 100644 --- a/.claude/skills/bug-bounty/SKILL.md +++ b/.claude/skills/bug-bounty/SKILL.md @@ -42,7 +42,6 @@ Never test assets outside the confirmed scope. > **Before you start:** > 1. Confirm scope, out-of-scope, and program rules are set > 2. Ensure all MCP servers are healthy — run `make mcp-status` -> 3. Verify authorization is active — run `make inject-verification` ## Mandatory Tool & Methodology Readiness diff --git a/.claude/skills/exploit-dev/SKILL.md b/.claude/skills/exploit-dev/SKILL.md index 8e78b84..e56a3fe 100644 --- a/.claude/skills/exploit-dev/SKILL.md +++ b/.claude/skills/exploit-dev/SKILL.md @@ -28,7 +28,6 @@ If no context was provided, ask the user: > **Before you start:** > 1. Ensure Kali MCP is healthy — run `make mcp-status` -> 2. Verify authorization is active — run `make inject-verification` ## Mandatory Tool & Methodology Readiness diff --git a/.claude/skills/full-attack-chain/SKILL.md b/.claude/skills/full-attack-chain/SKILL.md index 58c4dc9..6f682a0 100644 --- a/.claude/skills/full-attack-chain/SKILL.md +++ b/.claude/skills/full-attack-chain/SKILL.md @@ -47,8 +47,7 @@ Then gather engagement details interactively: > **Before you start:** > 1. Ensure all MCP servers are healthy — run `make mcp-status` -> 2. Verify authorization is active — run `make inject-verification` -> 3. Query each MCP server's tool listing to discover available capabilities +> 2. Query each MCP server's tool listing to discover available capabilities ## Mandatory Tool & Methodology Readiness diff --git a/.claude/skills/full-pentest/SKILL.md b/.claude/skills/full-pentest/SKILL.md index 3a3f936..89e0fc9 100644 --- a/.claude/skills/full-pentest/SKILL.md +++ b/.claude/skills/full-pentest/SKILL.md @@ -24,8 +24,7 @@ If no target was provided, ask the user: > **Before you start:** > 1. Ensure all MCP servers are healthy — run `make mcp-status` -> 2. Verify authorization is active — run `make inject-verification` -> 3. Query each MCP server's tool listing to discover available capabilities +> 2. Query each MCP server's tool listing to discover available capabilities ## Mandatory Tool & Methodology Readiness diff --git a/.claude/skills/network-infrastructure/SKILL.md b/.claude/skills/network-infrastructure/SKILL.md index f21f8c9..4e75078 100644 --- a/.claude/skills/network-infrastructure/SKILL.md +++ b/.claude/skills/network-infrastructure/SKILL.md @@ -29,8 +29,7 @@ Optionally ask if the user wants to customize: > **Before you start:** > 1. Ensure all MCP servers are healthy — run `make mcp-status` -> 2. Verify authorization is active — run `make inject-verification` -> 3. Query each MCP server's tool listing to discover available capabilities +> 2. Query each MCP server's tool listing to discover available capabilities > 3. Query each server's tool listing to discover available network testing capabilities ## Mandatory Tool & Methodology Readiness diff --git a/.claude/skills/osint-gathering/SKILL.md b/.claude/skills/osint-gathering/SKILL.md index 2950e1a..76ebf7f 100644 --- a/.claude/skills/osint-gathering/SKILL.md +++ b/.claude/skills/osint-gathering/SKILL.md @@ -21,8 +21,7 @@ If no target was provided, ask the user: > **Before you start:** > 1. Ensure all MCP servers are healthy — run `make mcp-status` -> 2. Verify authorization is active — run `make inject-verification` -> 3. Note: This uses **passive techniques only** — no packets sent to target +> 2. Note: This uses **passive techniques only** — no packets sent to target ## Mandatory Tool & Methodology Readiness diff --git a/.claude/skills/quick-scan/SKILL.md b/.claude/skills/quick-scan/SKILL.md index b85e2d8..71c7744 100644 --- a/.claude/skills/quick-scan/SKILL.md +++ b/.claude/skills/quick-scan/SKILL.md @@ -25,8 +25,7 @@ If no target was provided, ask the user: > **Before you start:** > 1. Ensure all MCP servers are healthy — run `make mcp-status` -> 2. Verify authorization is active — run `make inject-verification` -> 3. Query each MCP server's tool listing to discover available capabilities +> 2. Query each MCP server's tool listing to discover available capabilities ## Mandatory Tool & Methodology Readiness diff --git a/.claude/skills/recon-deep/SKILL.md b/.claude/skills/recon-deep/SKILL.md index 7095198..aadf1a3 100644 --- a/.claude/skills/recon-deep/SKILL.md +++ b/.claude/skills/recon-deep/SKILL.md @@ -20,8 +20,7 @@ If no target was provided, ask the user: > **Before you start:** > 1. Ensure all MCP servers are healthy — run `make mcp-status` -> 2. Verify authorization is active — run `make inject-verification` -> 3. Query each server's tool listing to discover available recon capabilities +> 2. Query each server's tool listing to discover available recon capabilities ## Mandatory Tool & Methodology Readiness diff --git a/.claude/skills/vuln-assessment/SKILL.md b/.claude/skills/vuln-assessment/SKILL.md index 954848b..a92a1b9 100644 --- a/.claude/skills/vuln-assessment/SKILL.md +++ b/.claude/skills/vuln-assessment/SKILL.md @@ -29,8 +29,7 @@ Optionally ask: > **Before you start:** > 1. Ensure all MCP servers are healthy — run `make mcp-status` -> 2. Verify authorization is active — run `make inject-verification` -> 3. Query each MCP server's tool listing to discover available capabilities +> 2. Query each MCP server's tool listing to discover available capabilities ## Mandatory Tool & Methodology Readiness diff --git a/.claude/skills/web-app-assessment/SKILL.md b/.claude/skills/web-app-assessment/SKILL.md index 301137c..c78d6ce 100644 --- a/.claude/skills/web-app-assessment/SKILL.md +++ b/.claude/skills/web-app-assessment/SKILL.md @@ -30,8 +30,7 @@ Then ask if authenticated testing is needed: > **Before you start:** > 1. Ensure all MCP servers are healthy — run `make mcp-status` -> 2. Verify authorization is active — run `make inject-verification` -> 3. Query each MCP server's tool listing to discover available capabilities +> 2. Query each MCP server's tool listing to discover available capabilities ## Mandatory Tool & Methodology Readiness diff --git a/.gitignore b/.gitignore index 22a55cd..d52cc82 100644 --- a/.gitignore +++ b/.gitignore @@ -26,9 +26,6 @@ env/ # Environment .env -# Active verification document (rendered from verification.env — contains engagement details) -.claude/verification-active.md - # Loop skill session tracking (local only) .claude/loop-tracker/ diff --git a/CLAUDE.md b/CLAUDE.md index afbdc28..e317af3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,7 +8,7 @@ Behavioral guidelines + project-specific rules. Read the whole file before touch Before making **any** fix, refactor, addition, or change — no matter how small it looks — you must complete all three phases below in order. **No exceptions.** -> **Note on tradeoffs:** Generic coding guidance often says "for trivial tasks, use judgment and skip the ceremony." That shortcut **does not apply here.** This is a security-sensitive pentesting framework where a one-line change can break authorization checks, shell-injection guards, or a stable schema contract. Bias toward caution over speed, always. +> **Note on tradeoffs:** Generic coding guidance often says "for trivial tasks, use judgment and skip the ceremony." That shortcut **does not apply here.** This is a security-sensitive pentesting framework where a one-line change can break shell-injection guards, secret handling, or a stable schema contract. Bias toward caution over speed, always. ### Phase 1: Web Research — Cast a Wide Net @@ -51,7 +51,7 @@ Before writing code, answer these internally: 1. **Root cause** — not the symptom, the actual root cause? 2. **Blast radius** — which other files, modules, behaviors, or contracts does this change affect? 3. **Stable contracts** — does the fix break any stable internal contract that downstream consumers rely on? Examples include the `AggregatedPayload` schema (consumed by `aggregate_results` and report generation), MCP tool signatures, and any documented prompt/template structure. -4. **Security invariants** — does it violate any core safety rule? Shell-injection safety (`shell=False`), secret/API-key handling, Pydantic validation of MCP tool inputs, authorization checks tied to the active verification document. +4. **Security invariants** — does it violate any core safety rule? Shell-injection safety (`shell=False`), secret/API-key handling, Pydantic validation of MCP tool inputs. 5. **Simplicity** — is there a simpler fix that achieves the same result? Only after answering all five — write the fix. @@ -161,39 +161,6 @@ Follow the existing conventions in the repo — don't invent new patterns. Befor --- -## Verification Document — Authorization for Pentesting - -Before executing any pentest template or offensive action, Claude Code **must** check for an active verification document. This document provides the explicit written authorization that Claude requires before performing security testing activities. - -### How it works - -1. **User fills in** `verification.env` in the project root with engagement details (target, scope, testing window, authorized activities, signatory, etc.) -2. **User sets** `AUTHORIZATION_STATUS=ACTIVE` once all fields are populated -3. **User runs** `make inject-verification` (or it runs automatically on session start) -4. The script renders `blhackbox/prompts/verification.md` (template) with the env values and writes the active document to `.claude/verification-active.md` -5. Claude Code reads this file at session start to confirm authorization - -### Checking authorization at runtime - -When a pentest template is loaded (via `get_template` MCP tool), the active verification document is automatically appended as authorization context. If no active verification exists, Claude should inform the user to: - -``` -1. Edit verification.env with your engagement details -2. Set AUTHORIZATION_STATUS=ACTIVE -3. Run: make inject-verification -``` - -### Files - -| File | Purpose | -|------|---------| -| `verification.env` | User-fillable config (engagement details, scope, permissions) | -| `blhackbox/prompts/verification.md` | Template with `{{PLACEHOLDER}}` tokens | -| `blhackbox/prompts/inject_verification.py` | Renders template → active document | -| `.claude/verification-active.md` | Rendered active authorization (git-ignored) | - ---- - ## Self-Check — Are These Guidelines Working? These guidelines are working if: @@ -201,7 +168,7 @@ These guidelines are working if: - Fewer rewrites due to overcomplication - Clarifying questions come **before** implementation, not after mistakes - Every Phase 3 question is answered before code is written -- No `shell=True`, no broken `AggregatedPayload` contracts, no skipped verification checks +- No `shell=True`, no broken `AggregatedPayload` contracts - When research is inconclusive or the codebase review surfaces a surprise, it's named explicitly instead of papered over --- diff --git a/DOCKER.md b/DOCKER.md index b324f7c..dcdf2ad 100644 --- a/DOCKER.md +++ b/DOCKER.md @@ -341,7 +341,6 @@ Portainer CE provides a web dashboard for all blhackbox containers. | `./output/sessions/` | `/root/results/` | Aggregated session JSON files | | `./.claude/skills/` | `/root/.claude/skills/` | Pentesting skills (read-only, claude-code only) | | `./CLAUDE.md` | `/root/CLAUDE.md` | Project instructions (read-only, claude-code only) | -| `./verification.env` | `/root/verification.env` | Pentest authorization config (read-only, claude-code only). The entrypoint renders it into `/root/.claude/verification-active.md` at startup. | --- diff --git a/Makefile b/Makefile index 0caeb76..dc7622f 100644 --- a/Makefile +++ b/Makefile @@ -8,8 +8,7 @@ push-all wordlists report \ check-mcp mcp-status tool-inventory security-scan \ logs-hexstrike logs-boaz \ - hexstrike-bridge boaz-bridge \ - inject-verification + hexstrike-bridge boaz-bridge COMPOSE := docker compose @@ -210,10 +209,6 @@ wordlists: ## Download common wordlists report: ## Generate report for a session (requires SESSION env var) blhackbox report --session $(SESSION) --format pdf -# ── Verification ───────────────────────────────────────────────── -inject-verification: ## Render verification.env into active authorization document - python -m blhackbox.prompts.inject_verification - # ── Build and push (Docker Hub: crhacky/blhackbox) ────────────── push-all: ## Build and push all custom images to Docker Hub docker build -f docker/kali-mcp.Dockerfile -t crhacky/blhackbox:kali-mcp . diff --git a/README.md b/README.md index 32322d7..776e24c 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ | **Advanced** | [Advanced Usage & FAQ](#advanced-usage--faq) | | **Reference** | [Components](#components) · [Output Files](#output-files) · [CLI Reference](#cli-reference) · [Makefile Shortcuts](#makefile-shortcuts) · [Docker Hub Images](#docker-hub-images) | | **Operations** | [Prompt Flow](#how-prompts-flow-through-the-system) · [MCP Gateway](#do-i-need-the-mcp-gateway) · [Portainer Setup](#portainer-setup) · [Neo4j](#neo4j-optional) · [Troubleshooting](#troubleshooting) | -| **Security** | [Authorization & Verification](#authorization--verification) · [Security Notes](#security-notes) | +| **Security** | [Security Notes](#security-notes) | | **Project** | [Project Structure](#project-structure) · [Build from Source](#build-from-source-optional) · [License](#license) | --- @@ -323,19 +323,6 @@ docker compose pull docker compose up -d ``` -**Set up authorization** (required before running pentests): - -```bash -# 5. Fill in engagement details -nano verification.env -# Set AUTHORIZATION_STATUS=ACTIVE after completing all fields - -# 6. Render the active verification document -make inject-verification -``` - -See [Authorization & Verification](#authorization--verification) for details. - **Verify everything is running:** ```bash @@ -471,7 +458,7 @@ Claude Code on [claude.ai/code](https://claude.ai/code) works as a web-based cod ### Steps 1. Go to [claude.ai/code](https://claude.ai/code) and open this repository -2. The session-start hook auto-installs dependencies and injects verification +2. The session-start hook auto-installs dependencies and runs an MCP health check 3. Type `/mcp` to verify — you should see `blhackbox` with its tools 4. Use a skill: `/quick-scan example.com` @@ -652,7 +639,7 @@ The repo has directory-scoped `CLAUDE.md` files that enforce local development r | File | Rules | |:--|:--| -| `blhackbox/mcp/CLAUDE.md` | MCP tool validation, verification document handling | +| `blhackbox/mcp/CLAUDE.md` | MCP tool validation and development rules | | `blhackbox/models/CLAUDE.md` | `AggregatedPayload` schema contract, PoC fields mandatory | | `blhackbox/backends/CLAUDE.md` | `shell=False` enforcement, tool allowlisting | | `blhackbox/reporting/CLAUDE.md` | Report path conventions, WeasyPrint compatibility | @@ -672,29 +659,6 @@ output/ Reports follow the naming convention: `output/reports/reports-DDMMYYYY/report--DDMMYYYY.md` -### How do I set up authorization for a lab/CTF? - -Minimal self-authorized setup in `verification.env`: - -```bash -AUTHORIZATION_STATUS=ACTIVE -ENGAGEMENT_ID=LAB-2026-001 -AUTHORIZATION_DATE=2026-03-15 -EXPIRATION_DATE=2026-12-31 -AUTHORIZING_ORGANIZATION=My Lab -TESTER_NAME=Your Name -TARGET_1=192.168.1.0/24 -TARGET_1_TYPE=network -TESTING_START=2026-03-15 00:00 -TESTING_END=2026-12-31 23:59 -SIGNATORY_NAME=Your Name -SIGNATURE_DATE=2026-03-15 -``` - -Then: `make inject-verification` - -See [Authorization & Verification](#authorization--verification) for the full setup. - --- ## How Prompts Flow Through the System @@ -876,7 +840,6 @@ blhackbox mcp # Start MCP server | `make logs-kali` | Tail Kali MCP logs (includes Metasploit) | | `make logs-wireshark` | Tail WireMCP logs | | `make logs-screenshot` | Tail Screenshot MCP logs | -| `make inject-verification` | Render verification.env → active authorization document | | `make push-all` | Build and push all images to Docker Hub | --- @@ -929,101 +892,10 @@ Stores `AggregatedPayload` results as a graph after each session. Useful for rec --- -## Authorization & Verification - -Before running any pentest template, blhackbox requires an **active verification document** — explicit written authorization confirming you have permission to test the target. Without it, Claude Code will refuse to execute offensive actions. - -### How it works - -``` -verification.env You fill in engagement details (target, scope, - │ testing window, authorized activities, signatory) - │ - ▼ -inject_verification.py Renders the template with your values - │ - ▼ -verification.md Template with {{PLACEHOLDER}} tokens - │ - ▼ -.claude/verification- Active document loaded into Claude Code session. - active.md Automatically appended to every pentest template. -``` - -When you load a pentest template (via the `get_template` MCP tool), the active verification document is automatically appended as authorization context. If none exists, Claude will prompt you to set one up. - -### Step-by-step setup - -**1. Edit `verification.env`** in the project root: - -```bash -nano verification.env # or vim, code, etc. -``` - -Fill in **all** fields across the 6 sections: - -| Section | Fields | -|:--|:--| -| **Engagement ID** | `ENGAGEMENT_ID`, `AUTHORIZATION_DATE`, `EXPIRATION_DATE`, `AUTHORIZING_ORGANIZATION`, `TESTER_NAME`, `TESTER_EMAIL`, `CLIENT_CONTACT_NAME`, `CLIENT_CONTACT_EMAIL` | -| **Scope** | `TARGET_1` through `TARGET_3` (with `_TYPE` and `_NOTES`), `OUT_OF_SCOPE`, `ENGAGEMENT_TYPE`, `CREDENTIALS` | -| **Activities** | Toggle each `PERMIT_*` field (`x` = allowed, blank = denied): recon, scanning, enumeration, exploitation, data extraction, credential testing, post-exploitation, traffic capture, screenshots | -| **Testing Window** | `TESTING_START`, `TESTING_END`, `TIMEZONE`, `EMERGENCY_CONTACT`, `EMERGENCY_PHONE` | -| **Legal** | `APPLICABLE_STANDARDS`, `REPORT_CLASSIFICATION`, `REPORT_DELIVERY` | -| **Signature** | `SIGNATORY_NAME`, `SIGNATORY_TITLE`, `SIGNATORY_ORGANIZATION`, `SIGNATURE_DATE`, `DIGITAL_SIGNATURE` | - -**2. Activate** — set the status field: - -```bash -AUTHORIZATION_STATUS=ACTIVE -``` - -**3. Inject** — render the active document: - -```bash -make inject-verification -``` - -Or directly: `python -m blhackbox.prompts.inject_verification` - -On success: - -``` -Verification document activated → .claude/verification-active.md -Engagement: PENTEST-2026-001 -Targets: example.com, 10.0.0.0/24 -Window: 2026-03-01 09:00 — 2026-03-31 17:00 UTC -Authorized by: Jane Smith -``` - -**4. Start your session** — Claude Code will automatically pick up the verification document. On Claude Code Web, the session-start hook runs `inject-verification` automatically if `verification.env` exists. In the Dockerized Claude Code container (`make claude-code`), `verification.env` is mounted read-only and the entrypoint renders it into `/root/.claude/verification-active.md` at startup — no host pre-step required. - -### Validation rules - -The injection script validates before rendering: - -- `AUTHORIZATION_STATUS` must be `ACTIVE` -- All required fields must be filled (`ENGAGEMENT_ID`, `AUTHORIZATION_DATE`, `EXPIRATION_DATE`, `AUTHORIZING_ORGANIZATION`, `TESTER_NAME`, `TARGET_1`, `TESTING_START`, `TESTING_END`, `SIGNATORY_NAME`, `SIGNATURE_DATE`) -- `EXPIRATION_DATE` must not be in the past - -If any check fails, the script exits with an error explaining what to fix. - -### Files involved - -| File | Purpose | -|:--|:--| -| `verification.env` | User-fillable config with engagement details, scope, and permissions | -| `blhackbox/prompts/verification.md` | Template with `{{PLACEHOLDER}}` tokens | -| `blhackbox/prompts/inject_verification.py` | Renders the template into the active document | -| `.claude/verification-active.md` | Rendered active authorization (git-ignored) | - -For a minimal self-authorized lab setup, see [How do I set up authorization for a lab/CTF?](#how-do-i-set-up-authorization-for-a-labctf) in the Advanced FAQ. - ---- - ## Security Notes - **Docker socket** — MCP Gateway (optional) and Portainer mount `/var/run/docker.sock`. This grants effective root on the host. Never expose ports 8080 or 9443 to the public internet. -- **Authorization** — Set up a [verification document](#authorization--verification) before running any pentest. Claude Code will not execute offensive actions without active authorization. The rendered document (`.claude/verification-active.md`) is git-ignored. +- **Authorization** — Only test systems you have explicit written permission to assess. Unauthorized scanning or exploitation is illegal. - **Neo4j** — Set a strong password in `.env`. Never use defaults in production. - **Portainer** — Uses HTTPS with a self-signed certificate. Create a strong admin password on first run. @@ -1037,7 +909,6 @@ blhackbox/ ├── CLAUDE.md Project-wide development rules ├── .claude/ │ ├── settings.json Claude Code hooks config -│ ├── verification-active.md Rendered authorization (git-ignored) │ ├── hooks/ │ │ ├── session-start.sh Auto-setup for web sessions │ │ └── loop-detector.sh MCP tool loop detection (Reflector pattern) @@ -1057,7 +928,6 @@ blhackbox/ │ ├── reports/ Generated pentest reports │ ├── screenshots/ PoC evidence captures │ └── sessions/ Aggregated session JSONs -├── verification.env Pentest authorization config ├── .mcp.json MCP server config (Claude Code Web) ├── docker/ │ ├── kali-mcp.Dockerfile Kali Linux + Metasploit Framework @@ -1081,9 +951,7 @@ blhackbox/ │ │ └── CLAUDE.md Backend safety rules (shell=False) │ ├── prompts/ │ │ ├── templates/ 11 pentest template .md files -│ │ ├── claude_playbook.md Pentest playbook for MCP host -│ │ ├── verification.md Authorization template -│ │ └── inject_verification.py Renders template → active document +│ │ └── claude_playbook.md Pentest playbook for MCP host │ ├── reporting/ │ │ ├── html_generator.py, pdf_generator.py, md_generator.py │ │ └── CLAUDE.md Reporting path conventions diff --git a/blhackbox/mcp/CLAUDE.md b/blhackbox/mcp/CLAUDE.md index 79399fe..2c4d2ca 100644 --- a/blhackbox/mcp/CLAUDE.md +++ b/blhackbox/mcp/CLAUDE.md @@ -2,8 +2,6 @@ - All MCP tool inputs **must** be validated with Pydantic models - Never break the `aggregate_results` or `get_template` tool contracts — these are the primary interface for MCP clients -- When `get_template` is called, always append the active verification document if it exists (via `load_verification()`) -- If no active verification document exists, append the warning section instructing the user to configure `verification.env` - The MCP server runs in **stdio** transport mode for Claude Code Web and as a CLI command (`blhackbox mcp`) - All tool functions must be type-annotated and include docstrings - Error responses must be structured and informative — never return raw tracebacks to MCP clients diff --git a/blhackbox/mcp/server.py b/blhackbox/mcp/server.py index b0ae5d3..ee37aa8 100644 --- a/blhackbox/mcp/server.py +++ b/blhackbox/mcp/server.py @@ -595,7 +595,7 @@ async def _do_list_templates() -> str: async def _do_get_template(args: dict[str, Any]) -> str: - from blhackbox.prompts import load_template, load_verification + from blhackbox.prompts import load_template name = args["name"] target = args.get("target") @@ -604,29 +604,6 @@ async def _do_get_template(args: dict[str, Any]) -> str: except (ValueError, FileNotFoundError) as exc: return json.dumps({"error": str(exc)}) - # Append active verification document as authorization context - verification = load_verification() - if verification: - content += ( - "\n\n---\n\n" - "## ACTIVE AUTHORIZATION DOCUMENT\n\n" - "The following verification document confirms explicit written " - "authorization for all activities described above.\n\n" - + verification - ) - else: - content += ( - "\n\n---\n\n" - "## ⚠ NO ACTIVE AUTHORIZATION DOCUMENT\n\n" - "No verification document found. Before executing this template, " - "the operator must:\n\n" - "1. Edit `verification.env` with engagement details\n" - "2. Set `AUTHORIZATION_STATUS=ACTIVE`\n" - "3. Run `make inject-verification`\n\n" - "This generates the explicit written authorization required " - "for penetration testing activities.\n" - ) - return content diff --git a/blhackbox/prompts/__init__.py b/blhackbox/prompts/__init__.py index 9078982..c99060b 100644 --- a/blhackbox/prompts/__init__.py +++ b/blhackbox/prompts/__init__.py @@ -75,16 +75,3 @@ def load_playbook() -> str: """Load the Claude pentest playbook.""" path = _PROMPTS_DIR / "claude_playbook.md" return path.read_text(encoding="utf-8") - - -def load_verification() -> str | None: - """Load the active verification document if it exists. - - Returns: - The rendered verification document content, or ``None`` if no - active verification document has been generated yet. - """ - active_path = _PROMPTS_DIR.parent.parent / ".claude" / "verification-active.md" - if active_path.exists(): - return active_path.read_text(encoding="utf-8") - return None diff --git a/blhackbox/prompts/inject_verification.py b/blhackbox/prompts/inject_verification.py deleted file mode 100644 index 5a8c225..0000000 --- a/blhackbox/prompts/inject_verification.py +++ /dev/null @@ -1,202 +0,0 @@ -"""Inject verification document into the Claude Code session context. - -Reads ``verification.env`` from the project root, renders the -``verification.md`` template with the configured values, and writes -the active document to ``.claude/verification-active.md``. - -The session-start hook (or ``make inject-verification``) calls this -script so that the rendered authorization document is present in -the Claude Code context before any pentest prompt templates run. - -Usage:: - - python -m blhackbox.prompts.inject_verification [--env PATH] [--out PATH] -""" - -from __future__ import annotations - -import argparse -import re -import sys -from datetime import UTC, datetime -from pathlib import Path -from typing import Any - - -def _parse_env_file(env_path: Path) -> dict[str, str]: - """Parse a simple KEY=VALUE env file, ignoring comments and blanks.""" - values: dict[str, str] = {} - for line in env_path.read_text(encoding="utf-8").splitlines(): - line = line.strip() - if not line or line.startswith("#"): - continue - if "=" not in line: - continue - key, _, value = line.partition("=") - values[key.strip()] = value.strip() - return values - - -def _validate_required_fields(env: dict[str, str]) -> list[str]: - """Return a list of missing required fields.""" - required = [ - "AUTHORIZATION_STATUS", - "ENGAGEMENT_ID", - "AUTHORIZATION_DATE", - "EXPIRATION_DATE", - "AUTHORIZING_ORGANIZATION", - "TESTER_NAME", - "TARGET_1", - "TESTING_START", - "TESTING_END", - "SIGNATORY_NAME", - "SIGNATURE_DATE", - ] - return [f for f in required if not env.get(f)] - - -def _check_expiration(env: dict[str, str]) -> str | None: - """Return an error message if the authorization has expired.""" - exp = env.get("EXPIRATION_DATE", "") - if not exp: - return None - try: - exp_date = datetime.strptime(exp, "%Y-%m-%d").date() - today = datetime.now(UTC).date() - if exp_date < today: - return f"Authorization expired on {exp}." - except ValueError: - return f"Invalid EXPIRATION_DATE format: {exp!r} (expected YYYY-MM-DD)." - return None - - -def render_verification(env: dict[str, str], template_text: str) -> str: - """Replace ``{{PLACEHOLDER}}`` tokens in the template with env values.""" - def _replace(match: re.Match[str]) -> str: - key = match.group(1) - return env.get(key, match.group(0)) - - return re.sub(r"\{\{(\w+)\}\}", _replace, template_text) - - -def inject( - env_path: Path | None = None, - out_path: Path | None = None, -) -> dict[str, Any]: - """Run the full injection pipeline. - - Returns: - Dict with ``status``, ``output_path``, and optional ``warnings``. - """ - project_root = Path(__file__).resolve().parents[2] - - if env_path is None: - env_path = project_root / "verification.env" - if out_path is None: - out_path = project_root / ".claude" / "verification-active.md" - - result: dict[str, Any] = {"warnings": []} - - # --- Read env --- - if not env_path.exists(): - return { - "status": "error", - "message": ( - f"verification.env not found at {env_path}. " - "Copy verification.env and fill in your engagement details." - ), - } - - env = _parse_env_file(env_path) - - # --- Check status --- - status = env.get("AUTHORIZATION_STATUS", "PENDING").upper() - if status != "ACTIVE": - return { - "status": "inactive", - "message": ( - "AUTHORIZATION_STATUS is not ACTIVE. " - "Set AUTHORIZATION_STATUS=ACTIVE in verification.env " - "after filling in all fields." - ), - } - - # --- Validate required fields --- - missing = _validate_required_fields(env) - if missing: - return { - "status": "error", - "message": ( - f"Missing required fields in verification.env: {', '.join(missing)}. " - "Fill in all required fields before activating." - ), - } - - # --- Check expiration --- - exp_err = _check_expiration(env) - if exp_err: - return {"status": "expired", "message": exp_err} - - # --- Read template --- - template_path = Path(__file__).parent / "verification.md" - if not template_path.exists(): - return { - "status": "error", - "message": f"Verification template not found: {template_path}", - } - - template_text = template_path.read_text(encoding="utf-8") - - # --- Render --- - rendered = render_verification(env, template_text) - - # --- Write active document --- - out_path.parent.mkdir(parents=True, exist_ok=True) - out_path.write_text(rendered, encoding="utf-8") - - result["status"] = "active" - result["output_path"] = str(out_path) - targets = ", ".join( - env.get(f"TARGET_{i}", "") - for i in range(1, 4) - if env.get(f"TARGET_{i}") - ) - result["message"] = ( - f"Verification document activated → {out_path}\n" - f"Engagement: {env.get('ENGAGEMENT_ID', 'N/A')}\n" - f"Targets: {targets}\n" - f"Window: {env.get('TESTING_START', '?')} — " - f"{env.get('TESTING_END', '?')} {env.get('TIMEZONE', 'UTC')}\n" - f"Authorized by: {env.get('SIGNATORY_NAME', 'N/A')}" - ) - return result - - -def main() -> None: - """CLI entry point.""" - parser = argparse.ArgumentParser( - description="Inject pentest verification into Claude Code session." - ) - parser.add_argument( - "--env", - type=Path, - default=None, - help="Path to verification.env (default: /verification.env)", - ) - parser.add_argument( - "--out", - type=Path, - default=None, - help="Output path (default: /.claude/verification-active.md)", - ) - args = parser.parse_args() - - result = inject(env_path=args.env, out_path=args.out) - print(result["message"]) - - if result["status"] not in ("active",): - sys.exit(1) - - -if __name__ == "__main__": - main() diff --git a/blhackbox/prompts/templates/api-security.md b/blhackbox/prompts/templates/api-security.md index a9ff49f..f993fb3 100644 --- a/blhackbox/prompts/templates/api-security.md +++ b/blhackbox/prompts/templates/api-security.md @@ -36,8 +36,7 @@ TARGET = "[TARGET_API_BASE_URL]" > 2. If you have API documentation (Swagger/OpenAPI), set `API_DOCS_URL` > 3. If testing authenticated endpoints, fill in the optional auth fields above > 4. Ensure all MCP servers are healthy — run `make mcp-status` -> 5. Verify authorization is active — run `make inject-verification` -> 6. Query each server's tool listing to discover available API testing capabilities +> 5. Query each server's tool listing to discover available API testing capabilities ## Mandatory Tool & Methodology Readiness diff --git a/blhackbox/prompts/templates/bug-bounty.md b/blhackbox/prompts/templates/bug-bounty.md index 0b70ae4..b689ad8 100644 --- a/blhackbox/prompts/templates/bug-bounty.md +++ b/blhackbox/prompts/templates/bug-bounty.md @@ -38,10 +38,9 @@ PROGRAM_RULES = "[PROGRAM_RULES]" > **Before you start:** > 1. Confirm all placeholders above (`TARGET`, `SCOPE`, `OUT_OF_SCOPE`, > `PROGRAM_RULES`) are set with actual program details -> 2. Double-check the scope — never test out-of-scope assets -> 3. Ensure all MCP servers are healthy — run `make mcp-status` -> 4. Verify authorization is active — run `make inject-verification` -> 5. Query each server's tool listing to discover available hunting capabilities +> 1. Double-check the scope — never test out-of-scope assets +> 2. Ensure all MCP servers are healthy — run `make mcp-status` +> 3. Query each server's tool listing to discover available hunting capabilities ## Mandatory Tool & Methodology Readiness diff --git a/blhackbox/prompts/templates/exploit-dev.md b/blhackbox/prompts/templates/exploit-dev.md index bb6d984..55b54c5 100644 --- a/blhackbox/prompts/templates/exploit-dev.md +++ b/blhackbox/prompts/templates/exploit-dev.md @@ -25,7 +25,6 @@ TARGET = "[TARGET]" > **Before you start:** > 1. Confirm the `TARGET` placeholder above is set to your actual target/vulnerability > 2. Ensure all MCP servers are healthy — run `make mcp-status` -> 3. Verify authorization is active — run `make inject-verification` ## Mandatory Tool & Methodology Readiness diff --git a/blhackbox/prompts/templates/full-attack-chain.md b/blhackbox/prompts/templates/full-attack-chain.md index f3bb78d..a3af0b5 100644 --- a/blhackbox/prompts/templates/full-attack-chain.md +++ b/blhackbox/prompts/templates/full-attack-chain.md @@ -74,9 +74,8 @@ REPORT_FORMAT = "[REPORT_FORMAT]" > **Before you start:** > 1. Confirm all placeholders above (`TARGET`, `SCOPE`, `OUT_OF_SCOPE`, > `ENGAGEMENT_TYPE`, `CREDENTIALS`, `REPORT_FORMAT`) are set -> 2. Ensure all MCP servers are healthy — run `make mcp-status` -> 3. Verify authorization is active — run `make inject-verification` -> 4. Query each server's tool listing to discover available capabilities +> 1. Ensure all MCP servers are healthy — run `make mcp-status` +> 2. Query each server's tool listing to discover available capabilities --- diff --git a/blhackbox/prompts/templates/full-pentest.md b/blhackbox/prompts/templates/full-pentest.md index 726f96c..b57a859 100644 --- a/blhackbox/prompts/templates/full-pentest.md +++ b/blhackbox/prompts/templates/full-pentest.md @@ -24,8 +24,7 @@ TARGET = "[TARGET]" > **Before you start:** > 1. Confirm the `TARGET` placeholder above is set to your actual target > 2. Ensure all MCP servers are healthy — run `make mcp-status` -> 3. Verify authorization is active — run `make inject-verification` -> 4. Query each server's tool listing at the start to discover available capabilities +> 3. Query each server's tool listing at the start to discover available capabilities ## Mandatory Tool & Methodology Readiness diff --git a/blhackbox/prompts/templates/network-infrastructure.md b/blhackbox/prompts/templates/network-infrastructure.md index 371525e..75ebe6b 100644 --- a/blhackbox/prompts/templates/network-infrastructure.md +++ b/blhackbox/prompts/templates/network-infrastructure.md @@ -31,8 +31,7 @@ TARGET = "[TARGET]" > 1. Confirm the `TARGET` placeholder above is set to your target IP, range, or domain > 2. Set optional `PORTS`, `SCAN_RATE`, and `EXCLUDES` if needed > 3. Ensure all MCP servers are healthy — run `make mcp-status` -> 4. Verify authorization is active — run `make inject-verification` -> 5. Query each server's tool listing to discover available network testing capabilities +> 4. Query each server's tool listing to discover available network testing capabilities ## Mandatory Tool & Methodology Readiness diff --git a/blhackbox/prompts/templates/osint-gathering.md b/blhackbox/prompts/templates/osint-gathering.md index 016720d..fd1b1f4 100644 --- a/blhackbox/prompts/templates/osint-gathering.md +++ b/blhackbox/prompts/templates/osint-gathering.md @@ -21,8 +21,7 @@ TARGET = "[TARGET]" > **Before you start:** > 1. Confirm the `TARGET` placeholder above is set to your target domain > 2. Ensure all MCP servers are healthy — run `make mcp-status` -> 3. Verify authorization is active — run `make inject-verification` -> 4. Note: This template uses **passive techniques only** — no packets sent to target +> 3. Note: This template uses **passive techniques only** — no packets sent to target ## Mandatory Tool & Methodology Readiness diff --git a/blhackbox/prompts/templates/quick-scan.md b/blhackbox/prompts/templates/quick-scan.md index 727996d..0f95df5 100644 --- a/blhackbox/prompts/templates/quick-scan.md +++ b/blhackbox/prompts/templates/quick-scan.md @@ -25,7 +25,6 @@ TARGET = "[TARGET]" > **Before you start:** > 1. Confirm the `TARGET` placeholder above is set to your actual target > 2. Ensure all MCP servers are healthy — run `make mcp-status` -> 3. Verify authorization is active — run `make inject-verification` ## Mandatory Tool & Methodology Readiness diff --git a/blhackbox/prompts/templates/recon-deep.md b/blhackbox/prompts/templates/recon-deep.md index bdc3268..8acf312 100644 --- a/blhackbox/prompts/templates/recon-deep.md +++ b/blhackbox/prompts/templates/recon-deep.md @@ -20,8 +20,7 @@ TARGET = "[TARGET]" > **Before you start:** > 1. Confirm the `TARGET` placeholder above is set to your actual target > 2. Ensure all MCP servers are healthy — run `make mcp-status` -> 3. Verify authorization is active — run `make inject-verification` -> 4. Query each server's tool listing to discover available recon capabilities +> 3. Query each server's tool listing to discover available recon capabilities ## Mandatory Tool & Methodology Readiness diff --git a/blhackbox/prompts/templates/vuln-assessment.md b/blhackbox/prompts/templates/vuln-assessment.md index 63e5e27..eed2c6b 100644 --- a/blhackbox/prompts/templates/vuln-assessment.md +++ b/blhackbox/prompts/templates/vuln-assessment.md @@ -30,8 +30,7 @@ TARGET = "[TARGET]" > 1. Confirm the `TARGET` placeholder above is set to your actual target > 2. Set `FOCUS_AREA` if you want to narrow the assessment scope > 3. Ensure all MCP servers are healthy — run `make mcp-status` -> 4. Verify authorization is active — run `make inject-verification` -> 5. Query each server's tool listing to discover available scanning capabilities +> 4. Query each server's tool listing to discover available scanning capabilities ## Mandatory Tool & Methodology Readiness diff --git a/blhackbox/prompts/templates/web-app-assessment.md b/blhackbox/prompts/templates/web-app-assessment.md index 2db4442..84f08b0 100644 --- a/blhackbox/prompts/templates/web-app-assessment.md +++ b/blhackbox/prompts/templates/web-app-assessment.md @@ -32,8 +32,7 @@ TARGET = "[TARGET]" > 1. Confirm the `TARGET` placeholder above is set to your web application URL > 2. If testing authenticated areas, fill in the optional auth fields above > 3. Ensure all MCP servers are healthy — run `make mcp-status` -> 4. Verify authorization is active — run `make inject-verification` -> 5. Query each server's tool listing to discover available web testing capabilities +> 4. Query each server's tool listing to discover available web testing capabilities ## Mandatory Tool & Methodology Readiness diff --git a/blhackbox/prompts/verification.md b/blhackbox/prompts/verification.md deleted file mode 100644 index 794e85f..0000000 --- a/blhackbox/prompts/verification.md +++ /dev/null @@ -1,171 +0,0 @@ -# Penetration Testing Authorization & Verification Document - -## AUTHORIZATION STATUS: {{AUTHORIZATION_STATUS}} - -> **This document constitutes explicit written authorization for penetration testing -> and security assessment activities.** It is loaded into the Claude Code session -> context to confirm that all operations requested via blhackbox prompt templates -> are legally and contractually authorized. - ---- - -## Section 1 — Engagement Identification - -| Field | Value | -|-------|-------| -| **Engagement ID** | {{ENGAGEMENT_ID}} | -| **Document Version** | 1.0 | -| **Authorization Date** | {{AUTHORIZATION_DATE}} | -| **Expiration Date** | {{EXPIRATION_DATE}} | -| **Authorizing Organization** | {{AUTHORIZING_ORGANIZATION}} | -| **Authorized Tester / Company** | {{TESTER_NAME}} | -| **Tester Contact Email** | {{TESTER_EMAIL}} | -| **Client Contact Name** | {{CLIENT_CONTACT_NAME}} | -| **Client Contact Email** | {{CLIENT_CONTACT_EMAIL}} | - ---- - -## Section 2 — Scope Definition - -### 2A: In-Scope Targets - -| # | Target (Domain / IP / CIDR / URL) | Type | Notes | -|---|-----------------------------------|------|-------| -| 1 | {{TARGET_1}} | {{TARGET_1_TYPE}} | {{TARGET_1_NOTES}} | -| 2 | {{TARGET_2}} | {{TARGET_2_TYPE}} | {{TARGET_2_NOTES}} | -| 3 | {{TARGET_3}} | {{TARGET_3_TYPE}} | {{TARGET_3_NOTES}} | - -> Add or remove rows as needed. Every target listed here is explicitly authorized. - -### 2B: Out-of-Scope / Exclusions - -{{OUT_OF_SCOPE}} - -> List any hosts, IPs, services, or actions explicitly excluded from testing. -> Example: "Production database at db.example.com", "Third-party CDN assets", -> "DoS/DDoS testing", "Social engineering of employees" - -### 2C: Engagement Type - -- **Testing approach:** {{ENGAGEMENT_TYPE}} - - `black-box` — No prior knowledge of target infrastructure - - `grey-box` — Limited credentials or documentation provided - - `white-box` — Full access to source code, architecture docs, credentials - -### 2D: Provided Credentials (if grey-box / white-box) - -{{CREDENTIALS}} - -> Format: `service: username:password` or `API key: sk-xxx...` -> Write "N/A" for black-box engagements. - ---- - -## Section 3 — Authorized Activities - -The following activities are explicitly authorized for all in-scope targets: - -### 3A: Permitted Testing Activities - -- [{{PERMIT_RECON}}] **Reconnaissance** — Passive and active information gathering (OSINT, DNS, WHOIS, subdomain enumeration, certificate transparency) -- [{{PERMIT_SCANNING}}] **Scanning** — Port scanning, service detection, vulnerability scanning, technology fingerprinting -- [{{PERMIT_ENUMERATION}}] **Enumeration** — Directory discovery, parameter fuzzing, CMS detection, web application mapping -- [{{PERMIT_EXPLOITATION}}] **Exploitation** — Active exploitation of discovered vulnerabilities including SQL injection, XSS, RCE, LFI, SSRF, authentication bypass, IDOR, XXE, file upload, deserialization -- [{{PERMIT_DATA_EXTRACTION}}] **Data extraction** — Proof-of-concept data extraction from exploited vulnerabilities (capped at 5 rows per database table) -- [{{PERMIT_CREDENTIAL_TESTING}}] **Credential testing** — Brute-force, default credential checks, credential reuse across services -- [{{PERMIT_POST_EXPLOITATION}}] **Post-exploitation** — Privilege escalation, lateral movement, persistence assessment, internal enumeration from compromised positions -- [{{PERMIT_TRAFFIC_CAPTURE}}] **Traffic capture** — Packet capture and analysis during testing for evidence collection -- [{{PERMIT_SCREENSHOT}}] **Evidence capture** — Screenshots of vulnerable pages, admin panels, exploitation results - -### 3B: Restrictions & Boundaries - -{{RESTRICTIONS}} - -> List any restrictions on testing (e.g., "No testing between 02:00-06:00 UTC", -> "Do not modify production data", "Do not attempt physical access"). -> Write "No additional restrictions" if none apply. - ---- - -## Section 4 — Testing Window - -| Field | Value | -|-------|-------| -| **Start Date/Time** | {{TESTING_START}} | -| **End Date/Time** | {{TESTING_END}} | -| **Timezone** | {{TIMEZONE}} | -| **Emergency Contact** | {{EMERGENCY_CONTACT}} | -| **Emergency Phone** | {{EMERGENCY_PHONE}} | - -> Testing must occur within this window. If the window needs extension, -> obtain written approval from the client contact. - ---- - -## Section 5 — Legal & Compliance - -### 5A: Authorization Confirmation - -By filling out and activating this document, the authorizing organization confirms: - -1. **Ownership or authorization**: The authorizing organization owns or has explicit - legal authority over all in-scope targets listed in Section 2A. -2. **Informed consent**: The authorizing organization understands that penetration - testing may temporarily impact system availability or performance. -3. **Legal compliance**: This engagement complies with all applicable local, national, - and international laws and regulations. -4. **Data handling**: Extracted data samples (PoC evidence) will be included in the - pentest report and handled per the agreed confidentiality terms. -5. **Third-party systems**: Any third-party systems in scope have separate written - authorization from their respective owners, or are confirmed to be fully controlled - by the authorizing organization. - -### 5B: Applicable Standards - -{{APPLICABLE_STANDARDS}} - -> Examples: "OWASP Testing Guide v4.2", "PTES", "NIST SP 800-115", -> "PCI DSS Requirement 11.3", "SOC 2 Type II", "ISO 27001 Annex A.12.6" - -### 5C: Report Classification - -- **Report classification:** {{REPORT_CLASSIFICATION}} - - Options: `CONFIDENTIAL`, `RESTRICTED`, `INTERNAL` -- **Report delivery method:** {{REPORT_DELIVERY}} - - Options: `encrypted-email`, `secure-portal`, `in-person`, `local-only` - ---- - -## Section 6 — Digital Signature - -| Field | Value | -|-------|-------| -| **Authorized by (name)** | {{SIGNATORY_NAME}} | -| **Title / Role** | {{SIGNATORY_TITLE}} | -| **Organization** | {{SIGNATORY_ORGANIZATION}} | -| **Date signed** | {{SIGNATURE_DATE}} | -| **Digital signature / reference** | {{DIGITAL_SIGNATURE}} | - -> This may be a PGP signature, a reference to a signed contract (e.g., -> "SOW-2024-0042 Section 4.2"), or "SELF-AUTHORIZED" for testing your own assets. - ---- - -## Activation - -**This document becomes active when:** - -1. All `{{PLACEHOLDER}}` fields above are filled in with real values -2. The `verification.env` configuration file is populated with matching values -3. The `AUTHORIZATION_STATUS` field at the top reads `ACTIVE` -4. The testing window (Section 4) includes the current date - -**When active, this document provides explicit written authorization for Claude Code -to execute all permitted activities (Section 3A) against all in-scope targets -(Section 2A) using the blhackbox MCP framework and prompt templates.** - ---- - -*This authorization document is generated by the blhackbox framework. -Unauthorized testing is illegal. Only use against targets you have explicit -written authorization to test.* diff --git a/docker-compose.yml b/docker-compose.yml index 6a50732..b0dc95a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -345,10 +345,6 @@ services: # Mount skills and project instructions so Claude Code discovers them - ./.claude/skills:/root/.claude/skills:ro - ./CLAUDE.md:/root/CLAUDE.md:ro - # Pentest authorization config — rendered into the active verification - # document (/root/.claude/verification-active.md) at startup by the - # entrypoint, so Claude Code recognizes the engagement authorization. - - ./verification.env:/root/verification.env:ro depends_on: kali-mcp: condition: service_healthy diff --git a/docker/claude-code-entrypoint.sh b/docker/claude-code-entrypoint.sh index 4b260e8..f48afb0 100755 --- a/docker/claude-code-entrypoint.sh +++ b/docker/claude-code-entrypoint.sh @@ -80,37 +80,10 @@ ln -sfn /root/reports /root/output/reports ln -sfn /root/results /root/output/sessions ln -sfn /tmp/screenshots /root/output/screenshots -# ── Pentest authorization document ────────────────────────────────── -# Render the mounted verification.env into the active authorization -# document that CLAUDE.md instructs Claude to read at session start. -# Mirrors the host session-start hook. Best-effort: if verification.env -# is absent, AUTHORIZATION_STATUS is not ACTIVE, or required fields are -# missing, no document is written and Claude treats the engagement as -# unauthorized. -render_verification() { - mkdir -p /root/.claude - echo -e " ${BOLD}Authorization${NC}" - if [ ! -f /root/verification.env ]; then - echo -e " [ ${WARN} ] verification.env not mounted — no authorization document" - return - fi - if python3 /opt/blhackbox-verify/inject_verification.py \ - --env /root/verification.env \ - --out /root/.claude/verification-active.md > /tmp/verification.log 2>&1; then - echo -e " [ ${CHECK} ] Active verification document loaded" - else - echo -e " [ ${WARN} ] $(head -n 1 /tmp/verification.log)" - echo -e " ${DIM}Fill verification.env and set AUTHORIZATION_STATUS=ACTIVE on the host.${NC}" - fi -} - # ── Main ──────────────────────────────────────────────────────────── print_banner -render_verification -echo "" - echo -e "${BOLD}Checking service connectivity...${NC}" echo -e "${DIM}Waiting for services to become healthy.${NC}" echo "" diff --git a/docker/claude-code.Dockerfile b/docker/claude-code.Dockerfile index 01ff9ed..21fe975 100644 --- a/docker/claude-code.Dockerfile +++ b/docker/claude-code.Dockerfile @@ -55,13 +55,6 @@ RUN echo '{ \ COPY CLAUDE.md /root/CLAUDE.md COPY .claude/skills /root/.claude/skills -# Verification renderer + template. inject_verification.py is stdlib-only and -# reads its template from the sibling verification.md, so both must live in the -# same directory. The entrypoint runs this at startup to render the mounted -# verification.env into /root/.claude/verification-active.md. -COPY blhackbox/prompts/inject_verification.py /opt/blhackbox-verify/inject_verification.py -COPY blhackbox/prompts/verification.md /opt/blhackbox-verify/verification.md - # Startup script: checks each MCP server, shows status, launches Claude. COPY docker/claude-code-entrypoint.sh /usr/local/bin/claude-code-entrypoint.sh RUN chmod +x /usr/local/bin/claude-code-entrypoint.sh diff --git a/docs/pentagi-comparison.md b/docs/pentagi-comparison.md index aec2a8e..f9bb98f 100644 --- a/docs/pentagi-comparison.md +++ b/docs/pentagi-comparison.md @@ -239,7 +239,6 @@ PentAGI's Adviser uses a stronger model for strategic analysis before execution. | **Workflow templates** | 10 production-ready slash command skills | No equivalent | | **PoC rigor** | Mandatory `evidence`, `poc_steps`, `poc_payload` fields | No enforced PoC structure | | **Protocol standard** | MCP-native (works with any MCP client) | Custom API | -| **Authorization framework** | verification.env with legal workflow | No equivalent | | **Metasploit integration** | Full msfconsole + msfvenom via CLI | Basic Metasploit | | **Report formats** | MD + PDF + HTML with AggregatedPayload contract | Less structured | diff --git a/setup.sh b/setup.sh index 54ba906..7e13140 100755 --- a/setup.sh +++ b/setup.sh @@ -314,9 +314,7 @@ print_summary() { echo -e " ${BOLD}MCP Gateway:${NC} ${CYAN}http://localhost:8080${NC}" fi echo -e " ${BOLD}For pentesting:${NC}" - echo -e " 1. Edit ${CYAN}verification.env${NC} with your engagement details" - echo -e " 2. Run ${CYAN}make inject-verification${NC}" - echo -e " 3. Use a pentest template: ${DIM}full-pentest, quick-scan, etc.${NC}" + echo -e " Use a pentest template or skill: ${DIM}full-pentest, quick-scan, etc.${NC}" echo "" } diff --git a/verification.env b/verification.env deleted file mode 100644 index 7ce5aca..0000000 --- a/verification.env +++ /dev/null @@ -1,112 +0,0 @@ -# ┌──────────────────────────────────────────────────────────────────────┐ -# │ BLHACKBOX — Penetration Testing Authorization Configuration │ -# │ │ -# │ Fill in ALL fields below, then run: │ -# │ make inject-verification │ -# │ or: │ -# │ python -m blhackbox.prompts.inject_verification │ -# │ │ -# │ This generates the active verification document that gets loaded │ -# │ into your Claude Code session as explicit written authorization. │ -# └──────────────────────────────────────────────────────────────────────┘ - -# ── Section 1: Engagement Identification ───────────────────────────── -# Set to ACTIVE when all fields are filled and testing is authorized. -AUTHORIZATION_STATUS=PENDING - -# Unique engagement identifier (e.g., "PENTEST-2026-001", "SOW-2026-042") -ENGAGEMENT_ID= - -# Date this authorization was granted (YYYY-MM-DD) -AUTHORIZATION_DATE= - -# Date this authorization expires (YYYY-MM-DD) -EXPIRATION_DATE= - -# Organization that owns or controls the target assets -AUTHORIZING_ORGANIZATION= - -# Person or company performing the test -TESTER_NAME= -TESTER_EMAIL= - -# Client-side point of contact -CLIENT_CONTACT_NAME= -CLIENT_CONTACT_EMAIL= - -# ── Section 2: Scope Definition ────────────────────────────────────── -# In-scope targets. Add up to 10. Leave unused slots empty. -# Format: domain.com, 10.0.0.0/24, https://app.example.com -TARGET_1= -TARGET_1_TYPE= -TARGET_1_NOTES= - -TARGET_2= -TARGET_2_TYPE= -TARGET_2_NOTES= - -TARGET_3= -TARGET_3_TYPE= -TARGET_3_NOTES= - -# Explicitly excluded from testing (comma-separated or "None") -OUT_OF_SCOPE=None - -# Engagement type: black-box, grey-box, white-box -ENGAGEMENT_TYPE=black-box - -# Credentials for grey-box/white-box (or "N/A") -CREDENTIALS=N/A - -# ── Section 3: Authorized Activities ───────────────────────────────── -# Mark each with "x" to permit or leave blank to deny. -# Example: PERMIT_RECON=x (permitted) -# PERMIT_RECON= (not permitted) -PERMIT_RECON=x -PERMIT_SCANNING=x -PERMIT_ENUMERATION=x -PERMIT_EXPLOITATION=x -PERMIT_DATA_EXTRACTION=x -PERMIT_CREDENTIAL_TESTING=x -PERMIT_POST_EXPLOITATION=x -PERMIT_TRAFFIC_CAPTURE=x -PERMIT_SCREENSHOT=x - -# Additional restrictions (free text, or "No additional restrictions") -RESTRICTIONS=No additional restrictions - -# ── Section 4: Testing Window ──────────────────────────────────────── -# Format: YYYY-MM-DD HH:MM -TESTING_START= -TESTING_END= -TIMEZONE=UTC - -# Who to call if something goes wrong during testing -EMERGENCY_CONTACT= -EMERGENCY_PHONE= - -# ── Section 5: Legal & Compliance ──────────────────────────────────── -# Applicable standards (comma-separated) -APPLICABLE_STANDARDS=OWASP Testing Guide v4.2, PTES - -# Report classification: CONFIDENTIAL, RESTRICTED, INTERNAL -REPORT_CLASSIFICATION=CONFIDENTIAL - -# How the report will be delivered: encrypted-email, secure-portal, in-person, local-only -REPORT_DELIVERY=local-only - -# ── Section 6: Digital Signature ───────────────────────────────────── -# Name of the person authorizing this engagement -SIGNATORY_NAME= - -# Title or role (e.g., "CISO", "CTO", "Asset Owner") -SIGNATORY_TITLE= - -# Organization of the signatory -SIGNATORY_ORGANIZATION= - -# Date signed (YYYY-MM-DD) -SIGNATURE_DATE= - -# Digital signature reference (PGP sig, contract ref, or "SELF-AUTHORIZED") -DIGITAL_SIGNATURE= From 5557ab6ac2e86623b6d407680d80d53e1519b6b1 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 14:32:13 +0000 Subject: [PATCH 3/6] Loosen skills and templates for adaptive, judgment-driven execution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Skills followed their phase scripts off a cliff when a tool errored, demanded an API key, or returned unexpected output. Reframe the readiness section opener from a hard gate to a default playbook, and add a new 'Adapt, recover, and think' step to all 11 skills and 11 templates that explicitly empowers the LLM to: diagnose and fix malformed tool commands before retrying, fall back gracefully when a tool needs an unavailable API key/token, switch tools on failure/timeout, reason about unexpected output, and deviate from the plan when the situation calls for it — with the outcome (proven impact) as the goal rather than literal step compliance. --- .claude/skills/api-security/SKILL.md | 29 +++++++++++++++++-- .claude/skills/bug-bounty/SKILL.md | 29 +++++++++++++++++-- .claude/skills/exploit-dev/SKILL.md | 29 +++++++++++++++++-- .claude/skills/full-attack-chain/SKILL.md | 29 +++++++++++++++++-- .claude/skills/full-pentest/SKILL.md | 29 +++++++++++++++++-- .../skills/network-infrastructure/SKILL.md | 29 +++++++++++++++++-- .claude/skills/osint-gathering/SKILL.md | 29 +++++++++++++++++-- .claude/skills/quick-scan/SKILL.md | 29 +++++++++++++++++-- .claude/skills/recon-deep/SKILL.md | 29 +++++++++++++++++-- .claude/skills/vuln-assessment/SKILL.md | 29 +++++++++++++++++-- .claude/skills/web-app-assessment/SKILL.md | 29 +++++++++++++++++-- blhackbox/prompts/templates/api-security.md | 29 +++++++++++++++++-- blhackbox/prompts/templates/bug-bounty.md | 29 +++++++++++++++++-- blhackbox/prompts/templates/exploit-dev.md | 29 +++++++++++++++++-- .../prompts/templates/full-attack-chain.md | 29 +++++++++++++++++-- blhackbox/prompts/templates/full-pentest.md | 29 +++++++++++++++++-- .../templates/network-infrastructure.md | 29 +++++++++++++++++-- .../prompts/templates/osint-gathering.md | 29 +++++++++++++++++-- blhackbox/prompts/templates/quick-scan.md | 29 +++++++++++++++++-- blhackbox/prompts/templates/recon-deep.md | 29 +++++++++++++++++-- .../prompts/templates/vuln-assessment.md | 29 +++++++++++++++++-- .../prompts/templates/web-app-assessment.md | 29 +++++++++++++++++-- 22 files changed, 594 insertions(+), 44 deletions(-) diff --git a/.claude/skills/api-security/SKILL.md b/.claude/skills/api-security/SKILL.md index 5096b4a..15112f8 100644 --- a/.claude/skills/api-security/SKILL.md +++ b/.claude/skills/api-security/SKILL.md @@ -35,8 +35,10 @@ Then gather optional details interactively: ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -64,6 +66,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/.claude/skills/bug-bounty/SKILL.md b/.claude/skills/bug-bounty/SKILL.md index 7346412..b0c2ebf 100644 --- a/.claude/skills/bug-bounty/SKILL.md +++ b/.claude/skills/bug-bounty/SKILL.md @@ -45,8 +45,10 @@ Never test assets outside the confirmed scope. ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -74,6 +76,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/.claude/skills/exploit-dev/SKILL.md b/.claude/skills/exploit-dev/SKILL.md index e56a3fe..5bf8458 100644 --- a/.claude/skills/exploit-dev/SKILL.md +++ b/.claude/skills/exploit-dev/SKILL.md @@ -31,8 +31,10 @@ If no context was provided, ask the user: ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -60,6 +62,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/.claude/skills/full-attack-chain/SKILL.md b/.claude/skills/full-attack-chain/SKILL.md index 6f682a0..92beed1 100644 --- a/.claude/skills/full-attack-chain/SKILL.md +++ b/.claude/skills/full-attack-chain/SKILL.md @@ -51,8 +51,10 @@ Then gather engagement details interactively: ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -80,6 +82,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/.claude/skills/full-pentest/SKILL.md b/.claude/skills/full-pentest/SKILL.md index 89e0fc9..5b1ac59 100644 --- a/.claude/skills/full-pentest/SKILL.md +++ b/.claude/skills/full-pentest/SKILL.md @@ -28,8 +28,10 @@ If no target was provided, ask the user: ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -57,6 +59,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/.claude/skills/network-infrastructure/SKILL.md b/.claude/skills/network-infrastructure/SKILL.md index 4e75078..5bb5515 100644 --- a/.claude/skills/network-infrastructure/SKILL.md +++ b/.claude/skills/network-infrastructure/SKILL.md @@ -34,8 +34,10 @@ Optionally ask if the user wants to customize: ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -63,6 +65,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/.claude/skills/osint-gathering/SKILL.md b/.claude/skills/osint-gathering/SKILL.md index 76ebf7f..a27f22a 100644 --- a/.claude/skills/osint-gathering/SKILL.md +++ b/.claude/skills/osint-gathering/SKILL.md @@ -25,8 +25,10 @@ If no target was provided, ask the user: ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -54,6 +56,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/.claude/skills/quick-scan/SKILL.md b/.claude/skills/quick-scan/SKILL.md index 71c7744..f7b17b5 100644 --- a/.claude/skills/quick-scan/SKILL.md +++ b/.claude/skills/quick-scan/SKILL.md @@ -29,8 +29,10 @@ If no target was provided, ask the user: ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -58,6 +60,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/.claude/skills/recon-deep/SKILL.md b/.claude/skills/recon-deep/SKILL.md index aadf1a3..1aa74ff 100644 --- a/.claude/skills/recon-deep/SKILL.md +++ b/.claude/skills/recon-deep/SKILL.md @@ -24,8 +24,10 @@ If no target was provided, ask the user: ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -53,6 +55,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/.claude/skills/vuln-assessment/SKILL.md b/.claude/skills/vuln-assessment/SKILL.md index a92a1b9..5f9417f 100644 --- a/.claude/skills/vuln-assessment/SKILL.md +++ b/.claude/skills/vuln-assessment/SKILL.md @@ -33,8 +33,10 @@ Optionally ask: ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -62,6 +64,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/.claude/skills/web-app-assessment/SKILL.md b/.claude/skills/web-app-assessment/SKILL.md index c78d6ce..1aa8ba0 100644 --- a/.claude/skills/web-app-assessment/SKILL.md +++ b/.claude/skills/web-app-assessment/SKILL.md @@ -34,8 +34,10 @@ Then ask if authenticated testing is needed: ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -63,6 +65,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/blhackbox/prompts/templates/api-security.md b/blhackbox/prompts/templates/api-security.md index f993fb3..b36317b 100644 --- a/blhackbox/prompts/templates/api-security.md +++ b/blhackbox/prompts/templates/api-security.md @@ -40,8 +40,10 @@ TARGET = "[TARGET_API_BASE_URL]" ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -69,6 +71,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/blhackbox/prompts/templates/bug-bounty.md b/blhackbox/prompts/templates/bug-bounty.md index b689ad8..b3d7c98 100644 --- a/blhackbox/prompts/templates/bug-bounty.md +++ b/blhackbox/prompts/templates/bug-bounty.md @@ -44,8 +44,10 @@ PROGRAM_RULES = "[PROGRAM_RULES]" ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -73,6 +75,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/blhackbox/prompts/templates/exploit-dev.md b/blhackbox/prompts/templates/exploit-dev.md index 55b54c5..b74fff1 100644 --- a/blhackbox/prompts/templates/exploit-dev.md +++ b/blhackbox/prompts/templates/exploit-dev.md @@ -28,8 +28,10 @@ TARGET = "[TARGET]" ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -57,6 +59,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/blhackbox/prompts/templates/full-attack-chain.md b/blhackbox/prompts/templates/full-attack-chain.md index a3af0b5..7b1f294 100644 --- a/blhackbox/prompts/templates/full-attack-chain.md +++ b/blhackbox/prompts/templates/full-attack-chain.md @@ -12,8 +12,10 @@ data extraction, and post-exploitation — with comprehensive reporting. ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -41,6 +43,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/blhackbox/prompts/templates/full-pentest.md b/blhackbox/prompts/templates/full-pentest.md index b57a859..fe80ed0 100644 --- a/blhackbox/prompts/templates/full-pentest.md +++ b/blhackbox/prompts/templates/full-pentest.md @@ -28,8 +28,10 @@ TARGET = "[TARGET]" ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -57,6 +59,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/blhackbox/prompts/templates/network-infrastructure.md b/blhackbox/prompts/templates/network-infrastructure.md index 75ebe6b..7a0a069 100644 --- a/blhackbox/prompts/templates/network-infrastructure.md +++ b/blhackbox/prompts/templates/network-infrastructure.md @@ -35,8 +35,10 @@ TARGET = "[TARGET]" ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -64,6 +66,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/blhackbox/prompts/templates/osint-gathering.md b/blhackbox/prompts/templates/osint-gathering.md index fd1b1f4..4cecbd9 100644 --- a/blhackbox/prompts/templates/osint-gathering.md +++ b/blhackbox/prompts/templates/osint-gathering.md @@ -25,8 +25,10 @@ TARGET = "[TARGET]" ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -54,6 +56,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/blhackbox/prompts/templates/quick-scan.md b/blhackbox/prompts/templates/quick-scan.md index 0f95df5..c557da3 100644 --- a/blhackbox/prompts/templates/quick-scan.md +++ b/blhackbox/prompts/templates/quick-scan.md @@ -28,8 +28,10 @@ TARGET = "[TARGET]" ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -57,6 +59,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/blhackbox/prompts/templates/recon-deep.md b/blhackbox/prompts/templates/recon-deep.md index 8acf312..7930a9f 100644 --- a/blhackbox/prompts/templates/recon-deep.md +++ b/blhackbox/prompts/templates/recon-deep.md @@ -24,8 +24,10 @@ TARGET = "[TARGET]" ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -53,6 +55,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/blhackbox/prompts/templates/vuln-assessment.md b/blhackbox/prompts/templates/vuln-assessment.md index eed2c6b..082a6da 100644 --- a/blhackbox/prompts/templates/vuln-assessment.md +++ b/blhackbox/prompts/templates/vuln-assessment.md @@ -34,8 +34,10 @@ TARGET = "[TARGET]" ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -63,6 +65,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- diff --git a/blhackbox/prompts/templates/web-app-assessment.md b/blhackbox/prompts/templates/web-app-assessment.md index 84f08b0..dc2b1d1 100644 --- a/blhackbox/prompts/templates/web-app-assessment.md +++ b/blhackbox/prompts/templates/web-app-assessment.md @@ -36,8 +36,10 @@ TARGET = "[TARGET]" ## Mandatory Tool & Methodology Readiness -Do **not** start the skill's execution plan until this readiness pass is complete. -This is Phase 0 for every blhackbox skill. +Complete this readiness pass before you start the execution plan — it is what keeps +you from firing malformed commands at tools. This is Phase 0 for every blhackbox skill. +Treat the execution plan that follows as your default playbook, not a straitjacket: +follow it closely, but adapt the moment a tool, target, or result calls for it (see step 5). 1. **Inventory 100% of usable capabilities first.** - Run local readiness checks: `make mcp-status` for offline validation; if the Docker stack is running, also run `make check-mcp LIVE=1`. @@ -65,6 +67,29 @@ This is Phase 0 for every blhackbox skill. - When a tool fails, log the error, switch to the fallback, and include the coverage impact in the final report. - Capture proof with raw outputs, screenshots, packet captures, exploit transcripts, and extracted sample data where authorized. +5. **Adapt, recover, and think — never follow the plan off a cliff.** + The phases below are a proven default sequence, not a rigid script. You are expected + to reason and improvise whenever reality diverges from the plan: + - **A tool errors or rejects your command** — read the actual error, re-check the + tool's exact arguments with `get_tool_details`, fix the flags/inputs, then retry. + Most failures are wrong syntax, a missing input, or an unescaped value. Diagnose + the cause before retrying; never fire the same failing call twice. + - **A tool needs an API key or token you don't have** (e.g. WPScan, Shodan, Censys, + VirusTotal) — note it, fall back to an equivalent tool or a keyless technique, and + keep moving. Never stall waiting for a key; log it in the issues report and proceed. + - **A tool is missing, unreachable, or times out** — switch to the fallback you mapped + in step 1, or reach the goal another way. Documented coverage gaps are acceptable; + getting stuck is not. + - **Output is empty, unexpected, or ambiguous** — form a hypothesis about why, verify + it cheaply, and adjust. Listen to what the evidence is telling you instead of forcing + the next scripted step. + - **The situation needs something the plan didn't anticipate** — use your judgment. Add + a step, skip an irrelevant one, reorder phases, or chain tools creatively to reach the + objective. Briefly record why you deviated. + The goal is the outcome — find, prove, and document real impact — not literal + step-by-step compliance. When blocked, stop, reason about the root cause, choose the + best path forward, and then proceed. + --- From 8dc6f272a1fd9b44654b6c4385fe9731ff296a35 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 14:41:34 +0000 Subject: [PATCH 4/6] Audit MCP servers; surface optional recon API keys in setup + docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MCP server audit (all except BOAZ): kali-mcp, wire-mcp, screenshot-mcp, the core blhackbox server, and the local backend are well-formed — all subprocess execution is shell=False with argument lists, tool output is structured, and the mcp>=1.23.0 FastMCP/SSE usage is valid. No command-construction or injection bugs found. API keys — researched how each recon tool consumes keys (sourced) and made the requirement explicit instead of a mid-recon surprise: - Every recon tool runs WITHOUT keys; keys only widen passive-source coverage. wpscan auto-loads WPSCAN_API_TOKEN; subfinder reads {SOURCE}_API_KEY env vars or its provider-config.yaml; theHarvester and amass use their own config files; nuclei/httpx/katana/gobuster/ffuf/ nikto/whatweb/wafw00f/dnsenum/fierce/dnsrecon are fully keyless. - .env.example: new 'Optional recon/OSINT API keys' block. - docker-compose: pass WPSCAN_API_TOKEN + subfinder source keys into the kali-mcp and hexstrike-ai containers (all default-empty, optional). - README: new 'Optional API keys' subsection under Prerequisites. - setup.sh: completion note pointing users to the optional keys in .env. - tools_catalog.json: add an 'api_key' hint to subfinder/amass/ theharvester/wpscan so get_tool_details tells the LLM upfront whether a key helps and that the tool runs without one. Reliability fix: screenshot-mcp hardcoded Playwright wait_until='networkidle', which routinely times out on live sites with analytics/websockets. Make it a parameter defaulting to 'load' (Playwright's recommended condition). Test guardrail: update test_skill_readiness for the loosened readiness wording and assert the new adaptive step is present. --- .env.example | 22 ++++++++++++++++++++-- README.md | 20 ++++++++++++++++++++ blhackbox/data/tools_catalog.json | 12 ++++++++---- docker-compose.yml | 11 ++++++++++- screenshot-mcp/server.py | 10 +++++++++- setup.sh | 5 +++++ tests/test_skill_readiness.py | 5 ++++- 7 files changed, 76 insertions(+), 9 deletions(-) diff --git a/.env.example b/.env.example index f098a98..5187449 100644 --- a/.env.example +++ b/.env.example @@ -23,9 +23,27 @@ KALI_MCP_PORT=9001 # Max timeout (seconds) for long-running Kali tool scans. KALI_MAX_TIMEOUT=600 -# WPScan API token for vulnerability database lookups. -# Free tier: https://wpscan.com/api (25 requests/day) + +# ── Optional recon / OSINT API keys ─────────────────────────────── +# IMPORTANT: every recon tool runs WITHOUT any of these keys. Keys only +# widen passive-source coverage (more subdomains, vuln data, OSINT hits). +# Add only the ones you have; leave the rest commented out. See the +# "Optional API keys" section of the README for the full picture. +# +# WPScan — adds the WordPress vulnerability database. wpscan auto-loads +# this variable (no CLI flag needed). Free tier: https://wpscan.com/api (25 req/day) # WPSCAN_API_TOKEN=your_token_here +# +# subfinder passive sources — read from these env vars (or from +# ~/.config/subfinder/provider-config.yaml). Add the providers you use: +# VIRUSTOTAL_API_KEY= +# SHODAN_API_KEY= +# SECURITYTRAILS_API_KEY= +# +# theHarvester and amass read keys from their OWN config files, not env +# vars (see the README "Optional API keys" section to mount them): +# theHarvester → ~/.theHarvester/api-keys.yaml (or /etc/theHarvester/) +# amass → ~/.config/amass/datasources.yaml # ── Screenshot MCP Server ───────────────────────────────────────── # Port exposed on the host for direct SSE connections (http://localhost:9004/sse). diff --git a/README.md b/README.md index 776e24c..9813c25 100644 --- a/README.md +++ b/README.md @@ -274,6 +274,26 @@ The `output/` directory is created automatically by `setup.sh`. For manual insta - At least **8 GB RAM** recommended (7 containers in the default stack) - An **Anthropic API key** from [console.anthropic.com](https://console.anthropic.com) (required for Claude Code) +### Optional API keys + +**Every recon tool works without any API key.** Keys are never required — they only +widen passive-source coverage (more subdomains, vulnerability data, and OSINT hits). +A tool with no key simply skips the sources that need one and keeps going, so you can +add keys later (or never). To add them, put the values in your `.env` (copy +`.env.example` first) and restart the stack: + +| Tool | Key | How it's read | What it adds | +|:--|:--|:--|:--| +| `wpscan` | `WPSCAN_API_TOKEN` | Auto-loaded from `.env` (passed into the container) | WordPress vulnerability database. Free tier: [wpscan.com/api](https://wpscan.com/api) (25 req/day) | +| `subfinder` | `VIRUSTOTAL_API_KEY`, `SHODAN_API_KEY`, `SECURITYTRAILS_API_KEY`, … | From `.env` env vars, or `~/.config/subfinder/provider-config.yaml` | Extra passive subdomain sources | +| `theHarvester` | shodan, hunter, securitytrails, censys, … | Config file `api-keys.yaml` (mount into the container to use) | Extra OSINT sources (keyless sources like crt.sh, certspotter, OTX still work) | +| `amass` | per-source keys | Config file `~/.config/amass/datasources.yaml` (mount to use) | Extra data sources | + +The fully keyless tools — `nuclei`, `httpx`, `katana`, `gobuster`, `ffuf`, `nikto`, +`whatweb`, `wafw00f`, `dnsenum`, `fierce`, `dnsrecon`, `nmap`, `sqlmap`, and the rest — +need no configuration at all. Run `get_tool_details()` and check the `api_key` +field to see whether a specific tool benefits from a key. + --- ## Installation diff --git a/blhackbox/data/tools_catalog.json b/blhackbox/data/tools_catalog.json index b4a4b5c..60fa90e 100644 --- a/blhackbox/data/tools_catalog.json +++ b/blhackbox/data/tools_catalog.json @@ -13,7 +13,8 @@ ], "example_params": { "target": "example.com" - } + }, + "api_key": "Optional — runs without keys. Extra passive sources (VirusTotal, Shodan, SecurityTrails, etc.) activate via env vars in .env or ~/.config/subfinder/provider-config.yaml. Sources with no key are skipped, not fatal." }, { "category": "dns", @@ -29,7 +30,8 @@ ], "example_params": { "target": "example.com" - } + }, + "api_key": "Optional — runs without keys. Data-source keys (read from ~/.config/amass/datasources.yaml) only widen coverage; amass works standalone." }, { "category": "dns", @@ -90,7 +92,8 @@ ], "example_params": { "target": "example.com" - } + }, + "api_key": "Optional — runs without keys (keyless sources: crtsh, certspotter, duckduckgo, otx, rapiddns, etc.). Key-required sources (shodan, hunter, securitytrails, censys) read from api-keys.yaml; missing keys produce warnings, not failure." }, { "category": "intelligence", @@ -601,7 +604,8 @@ ], "example_params": { "target": "https://example.com" - } + }, + "api_key": "Optional — scans without one. wpscan auto-loads WPSCAN_API_TOKEN (set in .env) to add WordPress vulnerability data. Free tier: https://wpscan.com/api (25 req/day)." }, { "category": "web", diff --git a/docker-compose.yml b/docker-compose.yml index b0dc95a..e20537b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -106,8 +106,12 @@ services: privileged: true init: true environment: - # WPScan API token for vulnerability database lookups (Issue #15) + # WPScan API token — wpscan auto-loads this; adds the WP vuln database. WPSCAN_API_TOKEN: "${WPSCAN_API_TOKEN:-}" + # Optional subfinder passive-source keys (all optional; recon runs without them). + VIRUSTOTAL_API_KEY: "${VIRUSTOTAL_API_KEY:-}" + SHODAN_API_KEY: "${SHODAN_API_KEY:-}" + SECURITYTRAILS_API_KEY: "${SECURITYTRAILS_API_KEY:-}" # Max timeout for long-running scans (Issue #8) KALI_MAX_TIMEOUT: "${KALI_MAX_TIMEOUT:-600}" # Metasploit timeout for msfconsole commands @@ -213,6 +217,11 @@ services: init: true environment: HEXSTRIKE_PORT: "8888" + # Optional recon keys — all tools run without them (see README). + WPSCAN_API_TOKEN: "${WPSCAN_API_TOKEN:-}" + VIRUSTOTAL_API_KEY: "${VIRUSTOTAL_API_KEY:-}" + SHODAN_API_KEY: "${SHODAN_API_KEY:-}" + SECURITYTRAILS_API_KEY: "${SECURITYTRAILS_API_KEY:-}" ports: - "${HEXSTRIKE_API_PORT:-8888}:8888" volumes: diff --git a/screenshot-mcp/server.py b/screenshot-mcp/server.py index f156578..f5f0078 100644 --- a/screenshot-mcp/server.py +++ b/screenshot-mcp/server.py @@ -139,6 +139,7 @@ async def take_screenshot( full_page: bool = False, wait_for_selector: str = "", wait_timeout: int = 0, + wait_until: str = "load", output_path: str = "", ) -> str: """Capture a screenshot of a web page via headless Chromium. @@ -150,6 +151,10 @@ async def take_screenshot( full_page: Capture the full scrollable page (default false) wait_for_selector: CSS selector to wait for before capture wait_timeout: Extra milliseconds to wait after page load (0-30000) + wait_until: Navigation wait condition — 'load' (default), 'domcontentloaded', + 'networkidle', or 'commit'. 'networkidle' often times out on live sites + with analytics/websockets; prefer 'load' and use wait_for_selector or + wait_timeout when you need specific content to render. output_path: Custom output file path (optional) Returns: @@ -158,6 +163,9 @@ async def take_screenshot( if not url.startswith(("http://", "https://")): return json.dumps({"error": "URL must start with http:// or https://"}) + if wait_until not in ("load", "domcontentloaded", "networkidle", "commit"): + wait_until = "load" + width = _clamp(width, 1, MAX_WIDTH) height = _clamp(height, 1, MAX_HEIGHT) wait_timeout = _clamp(wait_timeout, 0, 30000) @@ -171,7 +179,7 @@ async def take_screenshot( ) page = await context.new_page() - await page.goto(url, timeout=NAVIGATION_TIMEOUT, wait_until="networkidle") + await page.goto(url, timeout=NAVIGATION_TIMEOUT, wait_until=wait_until) if wait_for_selector: await page.wait_for_selector(wait_for_selector, timeout=NAVIGATION_TIMEOUT) diff --git a/setup.sh b/setup.sh index 7e13140..3a37859 100755 --- a/setup.sh +++ b/setup.sh @@ -316,6 +316,11 @@ print_summary() { echo -e " ${BOLD}For pentesting:${NC}" echo -e " Use a pentest template or skill: ${DIM}full-pentest, quick-scan, etc.${NC}" echo "" + echo -e " ${BOLD}Optional API keys${NC} ${DIM}(none required — all tools run without them):${NC}" + echo -e " Add keys to ${CYAN}.env${NC} to widen recon coverage, then restart the stack." + echo -e " ${DIM}WPSCAN_API_TOKEN (WordPress vulns), VIRUSTOTAL_API_KEY / SHODAN_API_KEY /${NC}" + echo -e " ${DIM}SECURITYTRAILS_API_KEY (subfinder sources). See README → Optional API keys.${NC}" + echo "" } # ── Parse Arguments ────────────────────────────────────────────────── diff --git a/tests/test_skill_readiness.py b/tests/test_skill_readiness.py index 44e672b..7265df6 100644 --- a/tests/test_skill_readiness.py +++ b/tests/test_skill_readiness.py @@ -18,7 +18,10 @@ def test_skill_and_template_files_discovered() -> None: def test_all_skills_require_tool_and_methodology_readiness() -> None: required_phrases = [ "## Mandatory Tool & Methodology Readiness", - "Do **not** start the skill's execution plan until this readiness pass is complete.", + "Complete this readiness pass before you start the execution plan", + # The readiness methodology stays, but skills must also empower adaptive, + # judgment-driven recovery instead of following the plan off a cliff. + "Adapt, recover, and think", "Inventory 100% of usable capabilities first.", "Build a working tool matrix before execution", "closest supported profile", From 8ed9cf58be6038384e6516eb01e3fc26f105f847 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 15:14:17 +0000 Subject: [PATCH 5/6] Migrate all MCP servers from SSE to Streamable HTTP; document all keys/tokens SSE was deprecated in the March 2025 MCP spec revision in favor of Streamable HTTP. Migrate every blhackbox MCP server to the current transport and wire the whole architecture (clients, gateway, health checks, tests, docs) to match. Transport migration (verified against the installed mcp SDK 1.27.2): - kali/wire/screenshot (FastMCP): default transport "sse" -> "streamable-http"; add a dedicated /health route to kali and wire (screenshot already had one). Streamable HTTP serves at /mcp. - hexstrike-mcp: fastmcp.sse_app() -> fastmcp.streamable_http_app(). - boaz-mcp: low-level SseServerTransport -> StreamableHTTPSessionManager, served at the exact /mcp path via a Route with an ASGI class instance (Mount would 307-redirect /mcp -> /mcp/ and break POST clients). Connection wiring: - blhackbox-mcp.json + claude-code container .mcp.json: type "sse" -> "http", url /sse -> /mcp. - Gateway catalog: transport_type sse -> streamable, url /sse -> /mcp. - compose / Makefile / check_mcp_servers.py health probes: a bare GET to /mcp returns HTTP 4xx (urlopen raises), so urlopen-based checks target /health; the curl-based container entrypoint targets /mcp. Keys & tokens: - setup.sh now prints a complete keys/tokens reference: the one required key (ANTHROPIC_API_KEY, Docker client only) plus every optional recon key with what it unlocks and where to get it. WPSCAN_API_TOKEN is auto-read by wpscan from env; SHODAN/VIRUSTOTAL/SECURITYTRAILS feed subfinder passive sources; theHarvester/amass use their own config files. Tests and docs updated to the new transport throughout. Full suite: 197 passed. Runtime-verified the streamable-http handshake (initialize -> 200 + session id) for both the FastMCP and the boaz session-manager paths. --- .env.example | 12 +++--- DOCKER.md | 36 ++++++++-------- Makefile | 8 ++-- README.md | 36 ++++++++-------- blhackbox-mcp-catalog.yaml | 22 +++++----- blhackbox-mcp.json | 28 ++++++------- blhackbox/mcp/server.py | 6 +-- boaz-mcp/README.md | 4 +- boaz-mcp/server.py | 67 +++++++++++++++++++----------- docker-compose.yml | 24 +++++------ docker/claude-code-entrypoint.sh | 22 +++++----- docker/claude-code.Dockerfile | 28 ++++++------- docs/mcp-server-review.md | 14 +++---- hexstrike-mcp/README.md | 4 +- hexstrike-mcp/server.py | 12 +++--- kali-mcp/server.py | 14 ++++++- screenshot-mcp/server.py | 4 +- scripts/check_mcp_servers.py | 13 +++--- setup.sh | 28 +++++++++++++ tests/test_boaz_mcp.py | 5 +-- tests/test_compose_integrations.py | 14 +++---- tests/test_hexstrike_mcp.py | 5 +-- wire-mcp/server.py | 16 ++++++- 23 files changed, 248 insertions(+), 174 deletions(-) diff --git a/.env.example b/.env.example index 5187449..dac1af7 100644 --- a/.env.example +++ b/.env.example @@ -18,8 +18,9 @@ # ══════════════════════════════════════════════════════════════════════ # ── Kali MCP Server ────────────────────────────────────────────── -# Port exposed on the host for direct SSE connections (http://localhost:9001/sse). -# Claude Code (Docker) uses the internal URL http://kali-mcp:9001/sse instead. +# Port exposed on the host for direct Streamable HTTP connections +# (http://localhost:9001/mcp). Claude Code (Docker) uses the internal URL +# http://kali-mcp:9001/mcp instead. KALI_MCP_PORT=9001 # Max timeout (seconds) for long-running Kali tool scans. KALI_MAX_TIMEOUT=600 @@ -46,8 +47,9 @@ KALI_MAX_TIMEOUT=600 # amass → ~/.config/amass/datasources.yaml # ── Screenshot MCP Server ───────────────────────────────────────── -# Port exposed on the host for direct SSE connections (http://localhost:9004/sse). -# Claude Code (Docker) uses the internal URL http://screenshot-mcp:9004/sse instead. +# Port exposed on the host for direct Streamable HTTP connections +# (http://localhost:9004/mcp). Claude Code (Docker) uses the internal URL +# http://screenshot-mcp:9004/mcp instead. SCREENSHOT_MCP_PORT=9004 # ── Metasploit (integrated in Kali MCP) ─────────────────────────── @@ -59,7 +61,7 @@ MSF_TIMEOUT=300 # ── MCP Gateway (optional — only for Claude Desktop / ChatGPT) ───── # Enable the gateway with: docker compose --profile gateway up -d # Claude Code in Docker does NOT need the gateway — it connects -# directly to each MCP server via SSE over the Docker network. +# directly to each MCP server via Streamable HTTP over the Docker network. MCP_GATEWAY_PORT=8080 # ── Neo4j (optional — for cross-session memory) ──────────────────── diff --git a/DOCKER.md b/DOCKER.md index dcdf2ad..f21f637 100644 --- a/DOCKER.md +++ b/DOCKER.md @@ -51,22 +51,22 @@ docker compose pull # pull ALL images (custom + official) in one command In v2, **Claude (or ChatGPT) IS the orchestrator** natively via MCP. -### Claude Code in Docker — Direct SSE (no gateway) +### Claude Code in Docker — Direct Streamable HTTP (no gateway) ``` -Claude Code ──┬──▶ Kali MCP (SSE :9001) +Claude Code ──┬──▶ Kali MCP (HTTP:9001) (container) │ 70+ tools: nmap, sqlmap, hydra, msfconsole, msfvenom… │ - ├──▶ WireMCP (SSE :9003) + ├──▶ WireMCP (HTTP:9003) │ 7 tools: packet capture, pcap analysis, credential extraction │ - ├──▶ Screenshot MCP (SSE :9004) + ├──▶ Screenshot MCP (HTTP:9004) │ 4 tools: web screenshots, element capture, annotations │ - ├──▶ BOAZ MCP (SSE :9005) + ├──▶ BOAZ MCP (HTTP:9005) │ upstream BOAZ-MCP Gamma tools │ - ├──▶ HexStrike MCP (SSE :9006) + ├──▶ HexStrike MCP (HTTP:9006) │ upstream HexStrike Gamma tool suite │ │ After collecting raw outputs, Claude structures them directly: @@ -192,8 +192,8 @@ Skills are available in the container via two mechanisms: | `wire-mcp` | `crhacky/blhackbox:wire-mcp` | `9003` | default | Wireshark / tshark (7 tools) | | `screenshot-mcp` | `crhacky/blhackbox:screenshot-mcp` | `9004` | default | Screenshot MCP (headless Chromium, 4 tools) | | `hexstrike-ai` | `crhacky/blhackbox:hexstrike-ai` | `8888` | default | HexStrike Gamma API | -| `hexstrike-bridge-mcp` | `crhacky/blhackbox:hexstrike-mcp` | `9006` | default | HexStrike Gamma MCP server (SSE) | -| `boaz-mcp` | `crhacky/blhackbox:boaz-mcp` | `9005` | default | BOAZ-MCP Gamma server (SSE) | +| `hexstrike-bridge-mcp` | `crhacky/blhackbox:hexstrike-mcp` | `9006` | default | HexStrike Gamma MCP server (Streamable HTTP) | +| `boaz-mcp` | `crhacky/blhackbox:boaz-mcp` | `9005` | default | BOAZ-MCP Gamma server (Streamable HTTP) | | `portainer` | `portainer/portainer-ce:latest` | `9443` | default | Docker management UI (HTTPS) | | `claude-code` | `crhacky/blhackbox:claude-code` | — | `claude-code` | Claude Code CLI client (Docker) | | `mcp-gateway` | `docker/mcp-gateway:latest` | `8080` | `gateway` | Single MCP entry point (host clients) | @@ -203,18 +203,18 @@ Skills are available in the container via two mechanisms: ## MCP Connection Modes -### Claude Code in Docker (Direct SSE — no gateway) +### Claude Code in Docker (Direct Streamable HTTP — no gateway) The Claude Code container's `.mcp.json` connects directly to each server: ```json { "mcpServers": { - "kali": { "type": "sse", "url": "http://kali-mcp:9001/sse" }, - "wireshark": { "type": "sse", "url": "http://kali-mcp:9003/sse" }, - "screenshot": { "type": "sse", "url": "http://screenshot-mcp:9004/sse" }, - "boaz": { "type": "sse", "url": "http://boaz-mcp:9005/sse" }, - "hexstrike": { "type": "sse", "url": "http://hexstrike-bridge-mcp:9006/sse" } + "kali": { "type": "http", "url": "http://kali-mcp:9001/mcp" }, + "wireshark": { "type": "http", "url": "http://kali-mcp:9003/mcp" }, + "screenshot": { "type": "http", "url": "http://screenshot-mcp:9004/mcp" }, + "boaz": { "type": "http", "url": "http://boaz-mcp:9005/mcp" }, + "hexstrike": { "type": "http", "url": "http://hexstrike-bridge-mcp:9006/mcp" } } } ``` @@ -260,7 +260,7 @@ Requires `--profile gateway` (`make up-gateway`). | | | |:--|:--| | **Base** | `kalilinux/kali-rolling` | -| **Transport** | SSE on port 9001 | +| **Transport** | Streamable HTTP on port 9001 | | **Privileged** | Yes (raw socket access) | | **Entrypoint** | `entrypoint.sh` (starts PostgreSQL for MSF DB, then MCP server) | @@ -275,7 +275,7 @@ Requires `--profile gateway` (`make up-gateway`). | | | |:--|:--| | **Base** | `debian:bookworm-slim` | -| **Transport** | SSE on port 9003 | +| **Transport** | Streamable HTTP on port 9003 | | **Privileged** | Yes (packet capture) | | **Entrypoint** | WireMCP server (`server.py`) | @@ -288,7 +288,7 @@ Requires `--profile gateway` (`make up-gateway`). | | | |:--|:--| | **Base** | `python:3.13-slim` | -| **Transport** | SSE on port 9004 | +| **Transport** | Streamable HTTP on port 9004 | | **Entrypoint** | Screenshot MCP server (FastMCP + Playwright headless Chromium) | **Tools (4):** `take_screenshot` (full-page web capture), `take_element_screenshot` (CSS selector targeting), `annotate_screenshot` (labels and highlight boxes), `list_screenshots` (evidence inventory) @@ -299,7 +299,7 @@ Requires `--profile gateway` (`make up-gateway`). |:--|:--| | **Base** | `node:22-slim` | | **Entrypoint** | `claude-code-entrypoint.sh` (health checks + launch) | -| **MCP config** | Direct SSE to each server (no gateway dependency) | +| **MCP config** | Direct Streamable HTTP to each server (no gateway dependency) | | **Skills** | 11 pentesting skills mounted from `.claude/skills/` | | **Requires** | `ANTHROPIC_API_KEY` in `.env` | diff --git a/Makefile b/Makefile index dc7622f..021f086 100644 --- a/Makefile +++ b/Makefile @@ -132,10 +132,10 @@ health: ## Quick health check of all MCP servers @echo "\033[1m MCP Server Health Check\033[0m" @echo "\033[2m ──────────────────────────────────────\033[0m" @printf " %-22s " "Kali MCP (9001)"; \ - docker exec blhackbox-kali-mcp python3 -c "import urllib.request; urllib.request.urlopen('http://localhost:9001/sse')" > /dev/null 2>&1 \ + docker exec blhackbox-kali-mcp python3 -c "import urllib.request; urllib.request.urlopen('http://localhost:9001/health')" > /dev/null 2>&1 \ && echo "\033[32m[OK]\033[0m" || echo "\033[31m[FAIL]\033[0m" @printf " %-22s " "WireMCP (9003)"; \ - docker exec blhackbox-wire-mcp python3 -c "import urllib.request; urllib.request.urlopen('http://localhost:9003/sse')" > /dev/null 2>&1 \ + docker exec blhackbox-wire-mcp python3 -c "import urllib.request; urllib.request.urlopen('http://localhost:9003/health')" > /dev/null 2>&1 \ && echo "\033[32m[OK]\033[0m" || echo "\033[31m[FAIL]\033[0m" @printf " %-22s " "Screenshot MCP (9004)"; \ docker exec blhackbox-screenshot-mcp python3 -c "import urllib.request; urllib.request.urlopen('http://localhost:9004/health')" > /dev/null 2>&1 \ @@ -144,10 +144,10 @@ health: ## Quick health check of all MCP servers docker exec blhackbox-hexstrike-ai python3 -c "import urllib.request; urllib.request.urlopen('http://localhost:8888/health')" > /dev/null 2>&1 \ && echo "\033[32m[OK]\033[0m" || echo "\033[31m[FAIL]\033[0m" @printf " %-22s " "HexStrike MCP (9006)"; \ - docker exec blhackbox-hexstrike-mcp python -c "import urllib.request; urllib.request.urlopen('http://localhost:9006/sse')" > /dev/null 2>&1 \ + docker exec blhackbox-hexstrike-mcp python -c "import urllib.request; urllib.request.urlopen('http://localhost:9006/health')" > /dev/null 2>&1 \ && echo "\033[32m[OK]\033[0m" || echo "\033[31m[FAIL]\033[0m" @printf " %-22s " "BOAZ MCP (9005)"; \ - docker exec blhackbox-boaz-mcp python -c "import urllib.request; urllib.request.urlopen('http://localhost:9005/sse')" > /dev/null 2>&1 \ + docker exec blhackbox-boaz-mcp python -c "import urllib.request; urllib.request.urlopen('http://localhost:9005/health')" > /dev/null 2>&1 \ && echo "\033[32m[OK]\033[0m" || echo "\033[31m[FAIL]\033[0m" @printf " %-22s " "MCP Gateway (8080)"; \ docker inspect --format='{{.State.Running}}' blhackbox-mcp-gateway 2>/dev/null | grep -q "true" \ diff --git a/README.md b/README.md index 9813c25..739fe32 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ Everything runs inside Docker containers. No tools are installed on your host ma ## Architecture -Claude Code in Docker connects **directly** to each MCP server via SSE over the internal Docker network — no MCP Gateway needed. +Claude Code in Docker connects **directly** to each MCP server via Streamable HTTP over the internal Docker network — no MCP Gateway needed. ``` YOU (the user) @@ -81,25 +81,25 @@ YOU (the user) CLAUDE CODE (Docker container on blhackbox_net) │ │ Reads your prompt, decides which tools to call. - │ Connects directly to each MCP server via SSE. + │ Connects directly to each MCP server via Streamable HTTP. │ - ├── kali (SSE :9001) ──────────────▶ KALI MCP SERVER + ├── kali (HTTP:9001) ──────────────▶ KALI MCP SERVER │ 70+ tools: nmap, nikto, gobuster, sqlmap, │ hydra, msfconsole, msfvenom, searchsploit… │ - ├── wireshark (SSE :9003) ─────────▶ WIREMCP SERVER + ├── wireshark (HTTP:9003) ─────────▶ WIREMCP SERVER │ 7 tools: packet capture, pcap analysis, │ credential extraction │ - ├── screenshot (SSE :9004) ────────▶ SCREENSHOT MCP SERVER + ├── screenshot (HTTP:9004) ────────▶ SCREENSHOT MCP SERVER │ 4 tools: web page screenshots, element │ capture, annotations │ - ├── boaz (SSE :9005) ───────────────▶ BOAZ-MCP GAMMA SERVER - │ upstream BOAZ MCP tools via SSE + ├── boaz (HTTP:9005) ───────────────▶ BOAZ-MCP GAMMA SERVER + │ upstream BOAZ MCP tools via Streamable HTTP │ - ├── hexstrike (SSE :9006) ──────────▶ HEXSTRIKE GAMMA MCP SERVER - │ upstream HexStrike tool suite via SSE + ├── hexstrike (HTTP:9006) ──────────▶ HEXSTRIKE GAMMA MCP SERVER + │ upstream HexStrike tool suite via Streamable HTTP │ │ After collecting raw outputs, Claude structures them directly: │ get_payload_schema() → parse/dedup/correlate → aggregate_results() @@ -220,8 +220,8 @@ The default stack also includes the HexStrike and BOAZ MCP integrations: | Profile | Services | Ports | Purpose | |:--|:--|:--:|:--| -| default | `hexstrike-ai`, `hexstrike-bridge-mcp` | `8888`, `9006` | Run a capsulated HexStrike Gamma API and expose the upstream HexStrike MCP tool suite over SSE. | -| default | `boaz-mcp` | `9005` | Run the upstream `BOAZ-MCP_gamma` server over SSE with `BOAZ_gamma` available at `/opt/BOAZ_gamma` and `./output/boaz-lab` mounted as workspace. | +| default | `hexstrike-ai`, `hexstrike-bridge-mcp` | `8888`, `9006` | Run a capsulated HexStrike Gamma API and expose the upstream HexStrike MCP tool suite over Streamable HTTP. | +| default | `boaz-mcp` | `9005` | Run the upstream `BOAZ-MCP_gamma` server over Streamable HTTP with `BOAZ_gamma` available at `/opt/BOAZ_gamma` and `./output/boaz-lab` mounted as workspace. | Start everything with the normal stack command: @@ -400,7 +400,7 @@ RETURN ip, p, s ## Tutorial 1: Claude Code (Docker) — Recommended -Claude Code runs entirely inside a Docker container on the same network as all blhackbox services. It connects **directly** to each MCP server via SSE — no MCP Gateway, no host install, no Node.js. +Claude Code runs entirely inside a Docker container on the same network as all blhackbox services. It connects **directly** to each MCP server via Streamable HTTP — no MCP Gateway, no host install, no Node.js. ### Step 1 — Start the stack @@ -700,7 +700,7 @@ STEP 2 ─ AI DECIDES WHICH TOOLS TO USE │ ▼ STEP 3 ─ TOOLS EXECUTE IN DOCKER CONTAINERS - Claude Code (Docker) connects directly via SSE. + Claude Code (Docker) connects directly via Streamable HTTP. Claude Desktop / ChatGPT connect via the MCP Gateway. Each tool runs in its container and returns raw text. │ @@ -730,7 +730,7 @@ STEP 7 ─ (OPTIONAL) RESULTS STORED IN NEO4J | MCP Client | Gateway? | How it connects | |:--|:--:|:--| -| **Claude Code (Docker)** | No | Direct SSE to each MCP server over Docker network | +| **Claude Code (Docker)** | No | Direct Streamable HTTP to each MCP server over Docker network | | **Claude Code (Web)** | No | Stdio MCP server from `.mcp.json` | | **Claude Desktop** | **Yes** | Host GUI app → `localhost:8080/mcp` gateway | | **ChatGPT / OpenAI** | **Yes** | Host GUI/web app → `localhost:8080/mcp` gateway | @@ -741,7 +741,7 @@ The MCP Gateway (`docker/mcp-gateway:latest`) aggregates all MCP servers behind make up-gateway # starts core stack + gateway ``` -> **Why optional?** The gateway adds complexity, requires Docker socket access, and is designed for Docker Desktop environments. On headless Linux servers, direct SSE is simpler and more reliable. +> **Why optional?** The gateway adds complexity, requires Docker socket access, and is designed for Docker Desktop environments. On headless Linux servers, direct Streamable HTTP is simpler and more reliable. --- @@ -886,9 +886,9 @@ All custom images are published to `crhacky/blhackbox`: | `crhacky/blhackbox:wire-mcp` | WireMCP Server (tshark, 7 tools) | | `crhacky/blhackbox:screenshot-mcp` | Screenshot MCP Server (headless Chromium, 4 tools) | | `crhacky/blhackbox:hexstrike-ai` | HexStrike Gamma API container | -| `crhacky/blhackbox:hexstrike-mcp` | Upstream HexStrike Gamma MCP server over SSE | -| `crhacky/blhackbox:boaz-mcp` | Upstream BOAZ-MCP Gamma server over SSE | -| `crhacky/blhackbox:claude-code` | Claude Code CLI client (direct SSE to MCP servers) | +| `crhacky/blhackbox:hexstrike-mcp` | Upstream HexStrike Gamma MCP server over Streamable HTTP | +| `crhacky/blhackbox:boaz-mcp` | Upstream BOAZ-MCP Gamma server over Streamable HTTP | +| `crhacky/blhackbox:claude-code` | Claude Code CLI client (direct Streamable HTTP to MCP servers) | Official images pulled directly: diff --git a/blhackbox-mcp-catalog.yaml b/blhackbox-mcp-catalog.yaml index 25f094b..601b7ff 100644 --- a/blhackbox-mcp-catalog.yaml +++ b/blhackbox-mcp-catalog.yaml @@ -19,8 +19,8 @@ registry: title: "Kali MCP Server" type: "server" remote: - url: "http://kali-mcp:9001/sse" - transport_type: sse + url: "http://kali-mcp:9001/mcp" + transport_type: streamable wire-mcp: description: "Wireshark/tshark — 7 tools: packet capture, pcap analysis, credential extraction, stream following" @@ -28,29 +28,29 @@ registry: type: "server" remote: # wire-mcp shares kali-mcp's network namespace for traffic visibility - url: "http://kali-mcp:9003/sse" - transport_type: sse + url: "http://kali-mcp:9003/mcp" + transport_type: streamable screenshot-mcp: description: "Headless Chromium screenshots — 4 tools: take_screenshot, take_element_screenshot, list_screenshots, annotate_screenshot" title: "Screenshot MCP Server" type: "server" remote: - url: "http://screenshot-mcp:9004/sse" - transport_type: sse + url: "http://screenshot-mcp:9004/mcp" + transport_type: streamable hexstrike-bridge-mcp: description: "HexStrike Gamma MCP — upstream tool surface connected to the local HexStrike API container" title: "HexStrike MCP Server" type: "server" remote: - url: "http://hexstrike-bridge-mcp:9006/sse" - transport_type: sse + url: "http://hexstrike-bridge-mcp:9006/mcp" + transport_type: streamable boaz-mcp: - description: "BOAZ MCP — upstream BOAZ-MCP Gamma server exposed over SSE" + description: "BOAZ MCP — upstream BOAZ-MCP Gamma server exposed over Streamable HTTP" title: "BOAZ MCP Server" type: "server" remote: - url: "http://boaz-mcp:9005/sse" - transport_type: sse + url: "http://boaz-mcp:9005/mcp" + transport_type: streamable diff --git a/blhackbox-mcp.json b/blhackbox-mcp.json index 4e7e289..33bc972 100644 --- a/blhackbox-mcp.json +++ b/blhackbox-mcp.json @@ -1,9 +1,9 @@ { "mcpServers": { "kali": { - "type": "sse", - "url": "http://localhost:9001/sse", - "description": "Kali Linux security tools + Metasploit Framework \u2014 70+ tools including msfconsole, msfvenom, nmap, sqlmap, hydra, etc. Connects via SSE to docker compose service on port 9001." + "type": "http", + "url": "http://localhost:9001/mcp", + "description": "Kali Linux security tools + Metasploit Framework — 70+ tools including msfconsole, msfvenom, nmap, sqlmap, hydra, etc. Connects via Streamable HTTP to docker compose service on port 9001." }, "wireshark": { "command": "docker", @@ -16,12 +16,12 @@ "--privileged", "crhacky/blhackbox:wire-mcp" ], - "description": "WireMCP Server \u2014 Wireshark/tshark for packet capture and network analysis (7 tools)" + "description": "WireMCP Server — Wireshark/tshark for packet capture and network analysis (7 tools)" }, "screenshot": { - "type": "sse", - "url": "http://localhost:9004/sse", - "description": "Screenshot MCP Server \u2014 headless Chromium screenshots for bug bounty PoC evidence capture (4 tools)" + "type": "http", + "url": "http://localhost:9004/mcp", + "description": "Screenshot MCP Server — headless Chromium screenshots for bug bounty PoC evidence capture (4 tools)" }, "blhackbox": { "command": "blhackbox", @@ -29,17 +29,17 @@ "mcp" ], "env": {}, - "description": "blhackbox core MCP server \u2014 recon, tool execution, graph queries, report generation" + "description": "blhackbox core MCP server — recon, tool execution, graph queries, report generation" }, "hexstrike": { - "type": "sse", - "url": "http://localhost:9006/sse", - "description": "HexStrike MCP Server \u2014 full upstream HexStrike Gamma MCP service connected to the HexStrike API container." + "type": "http", + "url": "http://localhost:9006/mcp", + "description": "HexStrike MCP Server — full upstream HexStrike Gamma MCP service connected to the HexStrike API container." }, "boaz": { - "type": "sse", - "url": "http://localhost:9005/sse", - "description": "BOAZ MCP Server \u2014 upstream BOAZ-MCP Gamma server exposed over SSE." + "type": "http", + "url": "http://localhost:9005/mcp", + "description": "BOAZ MCP Server — upstream BOAZ-MCP Gamma server exposed over Streamable HTTP." } } } diff --git a/blhackbox/mcp/server.py b/blhackbox/mcp/server.py index ee37aa8..c511066 100644 --- a/blhackbox/mcp/server.py +++ b/blhackbox/mcp/server.py @@ -785,7 +785,7 @@ async def _do_get_payload_schema() -> str: async def _screenshot_request(endpoint: str, payload: dict[str, Any]) -> str: - """Send a request to the screenshot-mcp SSE server's tool endpoint.""" + """Send a request to the screenshot-mcp server's tool endpoint.""" import httpx from blhackbox.config import settings @@ -805,8 +805,8 @@ async def _screenshot_request(endpoint: str, payload: dict[str, Any]) -> str: return json.dumps({ "error": ( "Screenshot MCP server not reachable. " - "Use the screenshot MCP server directly via SSE at " - f"{base_url}/sse or ensure the screenshot-mcp container is running." + "Use the screenshot MCP server directly via Streamable HTTP at " + f"{base_url}/mcp or ensure the screenshot-mcp container is running." ), }) diff --git a/boaz-mcp/README.md b/boaz-mcp/README.md index b00e268..1591cfb 100644 --- a/boaz-mcp/README.md +++ b/boaz-mcp/README.md @@ -1,6 +1,6 @@ # BOAZ MCP -The default Docker stack runs the upstream `BOAZ-MCP_gamma` server on SSE port `9005`. The upstream server is cloned into the image unchanged and is loaded by `boaz-mcp/server.py`, which only adapts the upstream stdio MCP server to the same SSE transport style used by the other blhackbox MCP containers. +The default Docker stack runs the upstream `BOAZ-MCP_gamma` server on Streamable HTTP port `9005`. The upstream server is cloned into the image unchanged and is loaded by `boaz-mcp/server.py`, which only adapts the upstream stdio MCP server to the same Streamable HTTP transport style used by the other blhackbox MCP containers. The image also clones `BOAZ_gamma` into `/opt/BOAZ_gamma` and sets `BOAZ_PATH=/opt/BOAZ_gamma`. The service mounts `./output/boaz-lab` as an operator workspace. @@ -18,4 +18,4 @@ Run manually for local adapter checks: python boaz-mcp/server.py ``` -Default SSE port: `9005`. +Default Streamable HTTP endpoint: `http://localhost:9005/mcp` (health probe at `/health`). diff --git a/boaz-mcp/server.py b/boaz-mcp/server.py index c19ed3f..4db7df3 100644 --- a/boaz-mcp/server.py +++ b/boaz-mcp/server.py @@ -1,29 +1,49 @@ -"""SSE entrypoint for the upstream BOAZ-MCP Gamma server. +"""Streamable HTTP entrypoint for the upstream BOAZ-MCP Gamma server. This file does not reimplement BOAZ tools. It loads the unmodified upstream `boaz_mcp.server.BoazMCPServer` from BOAZ-MCP_gamma and exposes that low-level -MCP server over SSE so it behaves like the other blhackbox Docker MCP services. +MCP server over Streamable HTTP so it behaves like the other blhackbox Docker +MCP services. """ from __future__ import annotations +import contextlib import os import sys +from collections.abc import AsyncIterator from pathlib import Path from typing import Any import uvicorn -from mcp.server.sse import SseServerTransport +from mcp.server.streamable_http_manager import StreamableHTTPSessionManager from starlette.applications import Starlette from starlette.requests import Request -from starlette.responses import JSONResponse, Response -from starlette.routing import Mount, Route +from starlette.responses import JSONResponse +from starlette.routing import Route +from starlette.types import Receive, Scope, Send DEFAULT_BOAZ_MCP_PATH = Path(os.environ.get("BOAZ_MCP_PATH", "/opt/BOAZ-MCP_gamma")) DEFAULT_HOST = os.environ.get("BOAZ_MCP_HOST", "0.0.0.0") DEFAULT_PORT = int(os.environ.get("BOAZ_MCP_PORT", "9005")) +class _StreamableHTTPASGIApp: + """ASGI wrapper around the session manager's request handler. + + Mounting the handler with a Starlette ``Route`` whose endpoint is a class + instance (rather than ``Mount``) serves the Streamable HTTP transport at the + exact ``/mcp`` path, matching the FastMCP-based servers. ``Mount`` would + redirect ``/mcp`` to ``/mcp/`` and break clients that POST to ``/mcp``. + """ + + def __init__(self, session_manager: StreamableHTTPSessionManager) -> None: + self.session_manager = session_manager + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + await self.session_manager.handle_request(scope, receive, send) + + def _add_upstream_to_path(upstream_path: Path = DEFAULT_BOAZ_MCP_PATH) -> None: """Make the cloned upstream BOAZ-MCP_gamma package importable.""" resolved = upstream_path.expanduser().resolve() @@ -40,21 +60,13 @@ def _load_upstream_mcp_server(upstream_path: Path = DEFAULT_BOAZ_MCP_PATH) -> An def create_app(upstream_path: Path = DEFAULT_BOAZ_MCP_PATH) -> Starlette: - """Create a Starlette SSE app around the upstream BOAZ MCP server.""" + """Create a Starlette Streamable HTTP app around the upstream BOAZ MCP server.""" upstream_server = _load_upstream_mcp_server(upstream_path) - sse = SseServerTransport("/messages/") - - async def handle_sse(scope: Any, receive: Any, send: Any) -> Response: - async with sse.connect_sse(scope, receive, send) as streams: - await upstream_server.run( - streams[0], - streams[1], - upstream_server.create_initialization_options(), - ) - return Response() - - async def sse_endpoint(request: Request) -> Response: - return await handle_sse(request.scope, request.receive, request._send) # type: ignore[attr-defined] + session_manager = StreamableHTTPSessionManager( + app=upstream_server, + json_response=False, + stateless=False, + ) async def health(_: Request) -> JSONResponse: return JSONResponse( @@ -62,21 +74,28 @@ async def health(_: Request) -> JSONResponse: "status": "ok", "service": "boaz-mcp", "upstream": "BOAZ-MCP_gamma", - "transport": "sse", + "transport": "streamable-http", } ) + @contextlib.asynccontextmanager + async def lifespan(_: Starlette) -> AsyncIterator[None]: + # The session manager's task group must be running for the duration of + # the app; handle_request fails otherwise. + async with session_manager.run(): + yield + return Starlette( routes=[ Route("/health", endpoint=health, methods=["GET"]), - Route("/sse", endpoint=sse_endpoint, methods=["GET"]), - Mount("/messages/", app=sse.handle_post_message), - ] + Route("/mcp", endpoint=_StreamableHTTPASGIApp(session_manager)), + ], + lifespan=lifespan, ) def main() -> None: - """Run BOAZ-MCP Gamma over SSE.""" + """Run BOAZ-MCP Gamma over Streamable HTTP.""" uvicorn.run(create_app(), host=DEFAULT_HOST, port=DEFAULT_PORT) diff --git a/docker-compose.yml b/docker-compose.yml index e20537b..9747449 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,9 +9,9 @@ # docker compose build Build all custom images locally # # MCP servers (core — always started): -# kali-mcp (FastMCP SSE, port 9001) — Kali Linux security tools (70+) + Metasploit Framework -# wire-mcp (FastMCP SSE, port 9003) — Wireshark/tshark (7 tools) -# screenshot-mcp (FastMCP SSE, port 9004) — Headless Chromium screenshots (4 tools) +# kali-mcp (FastMCP Streamable HTTP, port 9001) — Kali Linux security tools (70+) + Metasploit Framework +# wire-mcp (FastMCP Streamable HTTP, port 9003) — Wireshark/tshark (7 tools) +# screenshot-mcp (FastMCP Streamable HTTP, port 9004) — Headless Chromium screenshots (4 tools) # # Integrated MCP services in the default stack: # hexstrike-ai (port 8888) — HexStrike Gamma API @@ -23,7 +23,7 @@ # structures them into an AggregatedPayload, then validates via the # aggregate_results tool. # -# Claude Code (Docker) connects directly to MCP servers via SSE. +# Claude Code (Docker) connects directly to MCP servers via Streamable HTTP. # Claude Desktop / ChatGPT connect via the MCP Gateway (--profile gateway). # # Claude Desktop config (requires --profile gateway): @@ -89,9 +89,9 @@ services: condition: service_healthy # -- KALI MCP SERVER ------------------------------------------------------- - # Host-based clients can connect directly via SSE at http://localhost:9001/sse - # without the MCP Gateway. Claude Code (Docker) uses the internal URL - # http://kali-mcp:9001/sse instead. + # Host-based clients can connect directly via Streamable HTTP at + # http://localhost:9001/mcp without the MCP Gateway. Claude Code (Docker) + # uses the internal URL http://kali-mcp:9001/mcp instead. # # Includes Metasploit Framework (msfconsole, msfvenom) — Metasploit tools # are integrated directly into kali-mcp via CLI execution (`msfconsole -qx`). @@ -121,7 +121,7 @@ services: ports: - "${KALI_MCP_PORT:-9001}:9001" healthcheck: - test: ["CMD-SHELL", "python3 -c \"import urllib.request; urllib.request.urlopen('http://localhost:9001/sse')\""] + test: ["CMD-SHELL", "python3 -c \"import urllib.request; urllib.request.urlopen('http://localhost:9001/health')\""] interval: 15s timeout: 10s retries: 10 @@ -160,7 +160,7 @@ services: kali-mcp: condition: service_healthy healthcheck: - test: ["CMD-SHELL", "python3 -c \"import urllib.request; urllib.request.urlopen('http://localhost:9003/sse')\""] + test: ["CMD-SHELL", "python3 -c \"import urllib.request; urllib.request.urlopen('http://localhost:9003/health')\""] interval: 15s timeout: 10s retries: 5 @@ -203,7 +203,7 @@ services: # -- HEXSTRIKE GAMMA API + FULL MCP SERVER --------------------------------- # Runs with the default stack like the other MCP services. The API service # capsules HexStrike Gamma; the MCP service exposes the upstream tool suite - # over SSE on port 9006. + # over Streamable HTTP on port 9006. hexstrike-ai: image: crhacky/blhackbox:hexstrike-ai build: @@ -262,7 +262,7 @@ services: # -- BOAZ MCP SERVER -------------------------------------------------------- # Runs with the default stack like the other MCP services. The image carries # the unmodified upstream BOAZ-MCP Gamma server plus a BOAZ_gamma checkout. - # blhackbox only adds the SSE entrypoint used by the container. + # blhackbox only adds the Streamable HTTP entrypoint used by the container. boaz-mcp: image: crhacky/blhackbox:boaz-mcp build: @@ -326,7 +326,7 @@ services: # Enable with: docker compose --profile claude-code up -d # Then run: docker compose run --rm claude-code # - # Connects DIRECTLY to each MCP server via SSE over the Docker network. + # Connects DIRECTLY to each MCP server via Streamable HTTP over the Docker network. # Does NOT require the MCP Gateway. claude-code: image: crhacky/blhackbox:claude-code diff --git a/docker/claude-code-entrypoint.sh b/docker/claude-code-entrypoint.sh index f48afb0..cd6e30d 100755 --- a/docker/claude-code-entrypoint.sh +++ b/docker/claude-code-entrypoint.sh @@ -43,10 +43,10 @@ check_service() { local timeout="${3:-3}" curl -s --max-time "$timeout" -o /dev/null "$url" 2>/dev/null local rc=$? - # Exit code 28 = curl connected but the transfer timed out. This is - # expected for SSE/streaming endpoints (like /sse) that keep the - # connection open indefinitely. Treat it the same as 0 (success): - # the server is up and responding. + # A bare GET to the Streamable HTTP endpoint (/mcp) returns an HTTP 4xx + # (no MCP session/headers) — curl still exits 0 because it received a + # response, which confirms the server is up. Exit code 28 (transfer + # timed out) is also treated as success for any endpoint that streams. [ "$rc" -eq 0 ] || [ "$rc" -eq 28 ] } @@ -93,34 +93,34 @@ MCP_FAIL=0 REST_OK=0 REST_FAIL=0 -# -- MCP Servers (Claude Code connects via SSE) -- +# -- MCP Servers (Claude Code connects via Streamable HTTP) -- echo -e " ${BOLD}MCP Servers${NC}" -if wait_for_service "Kali MCP" "http://kali-mcp:9001/sse"; then +if wait_for_service "Kali MCP" "http://kali-mcp:9001/mcp"; then MCP_OK=$((MCP_OK + 1)) else MCP_FAIL=$((MCP_FAIL + 1)) fi # WireMCP shares kali-mcp's network namespace, so use kali-mcp hostname -if wait_for_service "WireMCP" "http://kali-mcp:9003/sse"; then +if wait_for_service "WireMCP" "http://kali-mcp:9003/mcp"; then MCP_OK=$((MCP_OK + 1)) else MCP_FAIL=$((MCP_FAIL + 1)) fi -if wait_for_service "Screenshot MCP" "http://screenshot-mcp:9004/sse"; then +if wait_for_service "Screenshot MCP" "http://screenshot-mcp:9004/mcp"; then MCP_OK=$((MCP_OK + 1)) else MCP_FAIL=$((MCP_FAIL + 1)) fi -if wait_for_service "BOAZ MCP" "http://boaz-mcp:9005/sse"; then +if wait_for_service "BOAZ MCP" "http://boaz-mcp:9005/mcp"; then MCP_OK=$((MCP_OK + 1)) else MCP_FAIL=$((MCP_FAIL + 1)) fi -if wait_for_service "HexStrike MCP" "http://hexstrike-bridge-mcp:9006/sse"; then +if wait_for_service "HexStrike MCP" "http://hexstrike-bridge-mcp:9006/mcp"; then MCP_OK=$((MCP_OK + 1)) else MCP_FAIL=$((MCP_FAIL + 1)) @@ -143,7 +143,7 @@ fi echo "" echo -e "${DIM}──────────────────────────────────────────────────${NC}" -echo -e " ${BOLD}MCP servers (connected via SSE):${NC}" +echo -e " ${BOLD}MCP servers (connected via Streamable HTTP):${NC}" echo -e " kali ${DIM}Kali Linux security tools + Metasploit (70+ tools)${NC}" echo -e " wireshark ${DIM}WireMCP — tshark packet capture & analysis${NC}" echo -e " screenshot ${DIM}Screenshot MCP — headless Chromium evidence capture${NC}" diff --git a/docker/claude-code.Dockerfile b/docker/claude-code.Dockerfile index 21fe975..28b338b 100644 --- a/docker/claude-code.Dockerfile +++ b/docker/claude-code.Dockerfile @@ -2,7 +2,7 @@ # Usage: # docker compose --profile claude-code run --rm claude-code # -# Connects DIRECTLY to each MCP server via SSE on the internal +# Connects DIRECTLY to each MCP server via Streamable HTTP on the internal # blhackbox_net network. No MCP Gateway required. No host-side install. FROM node:22-slim @@ -20,30 +20,30 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ WORKDIR /root -# Pre-configure MCP to connect directly to each FastMCP server via SSE. -# Wire-MCP shares kali-mcp's network namespace, so it's accessed via -# kali-mcp hostname on port 9003. +# Pre-configure MCP to connect directly to each FastMCP server via +# Streamable HTTP. Wire-MCP shares kali-mcp's network namespace, so it's +# accessed via the kali-mcp hostname on port 9003. RUN echo '{ \ "mcpServers": { \ "kali": { \ - "type": "sse", \ - "url": "http://kali-mcp:9001/sse" \ + "type": "http", \ + "url": "http://kali-mcp:9001/mcp" \ }, \ "wireshark": { \ - "type": "sse", \ - "url": "http://kali-mcp:9003/sse" \ + "type": "http", \ + "url": "http://kali-mcp:9003/mcp" \ }, \ "screenshot": { \ - "type": "sse", \ - "url": "http://screenshot-mcp:9004/sse" \ + "type": "http", \ + "url": "http://screenshot-mcp:9004/mcp" \ }, \ "boaz": { \ - "type": "sse", \ - "url": "http://boaz-mcp:9005/sse" \ + "type": "http", \ + "url": "http://boaz-mcp:9005/mcp" \ }, \ "hexstrike": { \ - "type": "sse", \ - "url": "http://hexstrike-bridge-mcp:9006/sse" \ + "type": "http", \ + "url": "http://hexstrike-bridge-mcp:9006/mcp" \ } \ } \ }' > .mcp.json diff --git a/docs/mcp-server-review.md b/docs/mcp-server-review.md index 900a340..cd945ff 100644 --- a/docs/mcp-server-review.md +++ b/docs/mcp-server-review.md @@ -4,13 +4,13 @@ | Server | Transport | Port | Primary role | Tools / capability surface | |---|---:|---:|---|---| -| `kali-mcp` | SSE | `9001` | Kali security-tool execution and Metasploit CLI workflows | 70+ allow-listed command tools including recon, web, exploitation, wireless, forensics, and utility commands | -| `wire-mcp` | SSE | `9003` | Wireshark/tshark packet capture and pcap analysis | Capture, pcap read, conversations, statistics, credential extraction, stream following, interface listing | -| `screenshot-mcp` | SSE | `9004` | Headless Chromium evidence capture | Page screenshots, element screenshots, screenshot listing, annotation | +| `kali-mcp` | Streamable HTTP | `9001` | Kali security-tool execution and Metasploit CLI workflows | 70+ allow-listed command tools including recon, web, exploitation, wireless, forensics, and utility commands | +| `wire-mcp` | Streamable HTTP | `9003` | Wireshark/tshark packet capture and pcap analysis | Capture, pcap read, conversations, statistics, credential extraction, stream following, interface listing | +| `screenshot-mcp` | Streamable HTTP | `9004` | Headless Chromium evidence capture | Page screenshots, element screenshots, screenshot listing, annotation | | `blhackbox` | stdio | n/a | Core orchestration, graph/reporting, templates, catalogue discovery | Tool execution, graph queries, reports, template retrieval, result aggregation, payload schema, catalogue search | | Docker MCP Gateway | streaming HTTP | `8080` | Optional host-client aggregation proxy | Proxies Kali, WireMCP, Screenshot MCP, BOAZ MCP, and HexStrike MCP through the Docker catalog | -| `boaz-mcp` | SSE | `9005` | Default BOAZ MCP service | Upstream BOAZ-MCP Gamma server exposed over SSE | -| `hexstrike-bridge-mcp` | SSE | `9006` | Default HexStrike Gamma MCP service | Upstream HexStrike Gamma MCP server loaded unchanged and exposed over SSE, connected to `hexstrike-ai` | +| `boaz-mcp` | Streamable HTTP | `9005` | Default BOAZ MCP service | Upstream BOAZ-MCP Gamma server exposed over Streamable HTTP | +| `hexstrike-bridge-mcp` | Streamable HTTP | `9006` | Default HexStrike Gamma MCP service | Upstream HexStrike Gamma MCP server loaded unchanged and exposed over Streamable HTTP, connected to `hexstrike-ai` | ## Changes made in this review @@ -32,7 +32,7 @@ ### Kali MCP -- The Docker Compose service exposes `http://localhost:9001/sse` and has an HTTP healthcheck against `/sse`. +- The Docker Compose service exposes the Streamable HTTP endpoint `http://localhost:9001/mcp` and has an HTTP healthcheck against the dedicated `/health` route. - The server has an explicit allowlist instead of unrestricted arbitrary execution. - Tool output is consistently structured with `stdout`, `stderr`, `exit_code`, `tool_name`, `timestamp`, and `target`. - Recommendation: keep the allowlist, but prefer high-level wrappers for dangerous/high-impact workflows where possible. @@ -40,7 +40,7 @@ ### WireMCP - `wire-mcp` shares `kali-mcp`'s network namespace to observe Kali-generated traffic. -- Gateway catalog points WireMCP to `http://kali-mcp:9003/sse`, matching the shared namespace design. +- Gateway catalog points WireMCP to `http://kali-mcp:9003/mcp`, matching the shared namespace design. - Recommendation: preserve this network-mode design; add pcap fixture tests in a future PR if sample pcaps can be committed safely. ### Screenshot MCP diff --git a/hexstrike-mcp/README.md b/hexstrike-mcp/README.md index 705ea6b..11bf131 100644 --- a/hexstrike-mcp/README.md +++ b/hexstrike-mcp/README.md @@ -1,7 +1,7 @@ # HexStrike MCP -The default Docker stack runs the upstream `hexstrike-ai_gamma` MCP server on SSE port `9006`. The upstream server is cloned into the image unchanged and is loaded by `hexstrike-mcp/server.py`, which only adapts the upstream FastMCP server to the same container entrypoint style used by the other blhackbox MCP containers. +The default Docker stack runs the upstream `hexstrike-ai_gamma` MCP server on Streamable HTTP port `9006`. The upstream server is cloned into the image unchanged and is loaded by `hexstrike-mcp/server.py`, which only adapts the upstream FastMCP server to the same container entrypoint style used by the other blhackbox MCP containers. The adapter points the upstream MCP server at `HEXSTRIKE_URL=http://hexstrike-ai:8888`, where the default stack runs the HexStrike Gamma API. -Default SSE port: `9006`. +Default Streamable HTTP endpoint: `http://localhost:9006/mcp` (health probe at `/health`). diff --git a/hexstrike-mcp/server.py b/hexstrike-mcp/server.py index 185754f..f6a669f 100644 --- a/hexstrike-mcp/server.py +++ b/hexstrike-mcp/server.py @@ -1,9 +1,9 @@ -"""SSE entrypoint for the upstream HexStrike AI Gamma MCP server. +"""Streamable HTTP entrypoint for the upstream HexStrike AI Gamma MCP server. This file does not reimplement HexStrike tools. It loads the unmodified upstream `hexstrike_mcp.py` module from a cloned `hexstrike-ai_gamma` checkout and runs -its FastMCP server over SSE so it behaves like the other blhackbox Docker MCP -services. +its FastMCP server over Streamable HTTP so it behaves like the other blhackbox +Docker MCP services. """ from __future__ import annotations @@ -82,7 +82,7 @@ def create_app( allowed_hosts, allowed_origins, ) - app = fastmcp.sse_app() + app = fastmcp.streamable_http_app() async def health(_: Request) -> JSONResponse: return JSONResponse( @@ -91,7 +91,7 @@ async def health(_: Request) -> JSONResponse: "service": "hexstrike-bridge-mcp", "upstream": "hexstrike-ai_gamma", "hexstrike_url": server_url, - "transport": "sse", + "transport": "streamable-http", } ) @@ -100,7 +100,7 @@ async def health(_: Request) -> JSONResponse: def main() -> None: - """Run HexStrike AI Gamma MCP over SSE.""" + """Run HexStrike AI Gamma MCP over Streamable HTTP.""" uvicorn.run(create_app(), host=DEFAULT_HOST, port=DEFAULT_PORT) diff --git a/kali-mcp/server.py b/kali-mcp/server.py index d09722b..686c165 100644 --- a/kali-mcp/server.py +++ b/kali-mcp/server.py @@ -92,6 +92,18 @@ mcp = FastMCP("kali-mcp", host="0.0.0.0", port=MCP_PORT) +@mcp.custom_route("/health", methods=["GET"]) +async def health_check(request): # type: ignore[no-untyped-def] + """Lightweight health probe for Docker and Makefile checks. + + The Streamable HTTP endpoint (/mcp) only answers MCP protocol requests, + so container health checks target this dedicated route instead. + """ + from starlette.responses import JSONResponse + + return JSONResponse({"status": "healthy", "service": "kali-mcp", "port": MCP_PORT}) + + # --------------------------------------------------------------------------- # Helper: run a subprocess and return structured result # --------------------------------------------------------------------------- @@ -986,7 +998,7 @@ async def get_exploit_code( # --------------------------------------------------------------------------- if __name__ == "__main__": - transport = os.environ.get("MCP_TRANSPORT", "sse") + transport = os.environ.get("MCP_TRANSPORT", "streamable-http") logger.info( "Starting Kali Linux MCP Server (%s on port %d, allowed tools: %d, msf: %s)", transport, MCP_PORT, len(ALLOWED_TOOLS), diff --git a/screenshot-mcp/server.py b/screenshot-mcp/server.py index f5f0078..1be7601 100644 --- a/screenshot-mcp/server.py +++ b/screenshot-mcp/server.py @@ -9,7 +9,7 @@ - list_screenshots → List captured screenshots with metadata - annotate_screenshot → Add text/box annotations to a screenshot for PoC docs -Transport: FastMCP SSE on port 9004. +Transport: FastMCP Streamable HTTP on port 9004. """ from __future__ import annotations @@ -488,6 +488,6 @@ async def annotate_screenshot( # --------------------------------------------------------------------------- if __name__ == "__main__": - transport = os.environ.get("MCP_TRANSPORT", "sse") + transport = os.environ.get("MCP_TRANSPORT", "streamable-http") logger.info("Starting Screenshot MCP server (%s on port %d)", transport, MCP_PORT) mcp.run(transport=transport) diff --git a/scripts/check_mcp_servers.py b/scripts/check_mcp_servers.py index feb55f2..0d1ef39 100644 --- a/scripts/check_mcp_servers.py +++ b/scripts/check_mcp_servers.py @@ -42,13 +42,16 @@ class Endpoint: LIVE_ENDPOINTS = [ - Endpoint("kali-mcp", "http://localhost:9001/sse"), - Endpoint("wire-mcp", "http://localhost:9003/sse"), + # Health probes use each server's dedicated /health route. A bare GET to + # the Streamable HTTP endpoint (/mcp) returns HTTP 4xx, which urlopen + # raises on — so health checks target /health (200) instead. + Endpoint("kali-mcp", "http://localhost:9001/health"), + Endpoint("wire-mcp", "http://localhost:9003/health"), Endpoint("screenshot-mcp", "http://localhost:9004/health"), Endpoint("mcp-gateway", "http://localhost:8080/mcp", required=False), Endpoint("hexstrike-api", "http://localhost:8888/health"), - Endpoint("hexstrike-bridge", "http://localhost:9006/sse"), - Endpoint("boaz-mcp", "http://localhost:9005/sse"), + Endpoint("hexstrike-bridge", "http://localhost:9006/health"), + Endpoint("boaz-mcp", "http://localhost:9005/health"), ] @@ -107,7 +110,7 @@ def run_checks(live: bool) -> list[CheckResult]: def main() -> int: parser = argparse.ArgumentParser(description="Validate blhackbox MCP servers") - parser.add_argument("--live", action="store_true", help="Check live HTTP/SSE endpoints") + parser.add_argument("--live", action="store_true", help="Check live HTTP endpoints") parser.add_argument("--json", action="store_true", help="Emit JSON") args = parser.parse_args() diff --git a/setup.sh b/setup.sh index 3a37859..9293d4c 100755 --- a/setup.sh +++ b/setup.sh @@ -175,6 +175,34 @@ configure_env() { echo -e " ${CHECK} NEO4J_PASSWORD configured" fi + # --- Keys & tokens reference --- + # Print the full list of keys/tokens the framework can use so the user + # knows exactly what to provide. Only ANTHROPIC_API_KEY (Docker client) is + # ever required; every pentest tool runs without the rest — they only widen + # passive recon coverage and extra data sources. + echo "" + echo -e " ${BOLD}Keys & tokens${NC} ${DIM}(edit .env to add them, then restart the stack):${NC}" + echo "" + echo -e " ${BOLD}Required${NC}" + echo -e " ${CYAN}ANTHROPIC_API_KEY${NC} ${DIM}Only for Claude Code inside Docker (--profile${NC}" + echo -e " ${DIM}claude-code). Not needed for Claude Code Web/host.${NC}" + echo -e " ${DIM}→ https://console.anthropic.com/settings/keys${NC}" + echo "" + echo -e " ${BOLD}Optional — widen recon (all tools work without them)${NC}" + echo -e " ${CYAN}WPSCAN_API_TOKEN${NC} ${DIM}WordPress vuln database; wpscan auto-reads it.${NC}" + echo -e " ${DIM}→ https://wpscan.com/api (free: 25 req/day)${NC}" + echo -e " ${CYAN}SHODAN_API_KEY${NC} ${DIM}subfinder passive source + Shodan host data.${NC}" + echo -e " ${DIM}→ https://account.shodan.io${NC}" + echo -e " ${CYAN}VIRUSTOTAL_API_KEY${NC} ${DIM}subfinder passive source.${NC}" + echo -e " ${DIM}→ https://www.virustotal.com/gui/my-apikey${NC}" + echo -e " ${CYAN}SECURITYTRAILS_API_KEY${NC} ${DIM}subfinder passive source (subdomains/history).${NC}" + echo -e " ${DIM}→ https://securitytrails.com/app/account/credentials${NC}" + echo -e " ${CYAN}OPENAI_API_KEY${NC} ${DIM}Only for ChatGPT/OpenAI MCP clients (host-based).${NC}" + echo -e " ${DIM}→ https://platform.openai.com/api-keys${NC}" + echo "" + echo -e " ${DIM}theHarvester and amass read keys from their OWN config files, not${NC}" + echo -e " ${DIM}env vars: ~/.theHarvester/api-keys.yaml and ~/.config/amass/datasources.yaml${NC}" + echo "" } diff --git a/tests/test_boaz_mcp.py b/tests/test_boaz_mcp.py index 7f83345..6258184 100644 --- a/tests/test_boaz_mcp.py +++ b/tests/test_boaz_mcp.py @@ -1,4 +1,4 @@ -"""Tests for the BOAZ-MCP Gamma SSE adapter.""" +"""Tests for the BOAZ-MCP Gamma Streamable HTTP adapter.""" from __future__ import annotations @@ -40,8 +40,7 @@ def test_boaz_adapter_uses_upstream_package(tmp_path: Path, monkeypatch) -> None app = module.create_app(upstream) route_paths = {getattr(route, "path", "") for route in app.routes} assert "/health" in route_paths - assert "/sse" in route_paths - assert "/messages" in route_paths or "/messages/" in route_paths + assert "/mcp" in route_paths def test_boaz_dockerfile_clones_upstream_repos() -> None: diff --git a/tests/test_compose_integrations.py b/tests/test_compose_integrations.py index 40c0f94..734d29f 100644 --- a/tests/test_compose_integrations.py +++ b/tests/test_compose_integrations.py @@ -37,8 +37,8 @@ def test_integration_ports_are_documented_in_configs() -> None: assert 'HEXSTRIKE_REF: "${HEXSTRIKE_REF:-master}"' in compose assert "hexstrike-bridge-mcp" in catalog assert "boaz-mcp" in catalog - assert mcp_json["mcpServers"]["hexstrike"]["url"] == "http://localhost:9006/sse" - assert mcp_json["mcpServers"]["boaz"]["url"] == "http://localhost:9005/sse" + assert mcp_json["mcpServers"]["hexstrike"]["url"] == "http://localhost:9006/mcp" + assert mcp_json["mcpServers"]["boaz"]["url"] == "http://localhost:9005/mcp" def test_integration_dockerfiles_exist() -> None: @@ -70,11 +70,11 @@ def test_claude_code_container_wires_all_default_mcp_servers() -> None: ) for expected in [ - "http://kali-mcp:9001/sse", - "http://kali-mcp:9003/sse", - "http://screenshot-mcp:9004/sse", - "http://boaz-mcp:9005/sse", - "http://hexstrike-bridge-mcp:9006/sse", + "http://kali-mcp:9001/mcp", + "http://kali-mcp:9003/mcp", + "http://screenshot-mcp:9004/mcp", + "http://boaz-mcp:9005/mcp", + "http://hexstrike-bridge-mcp:9006/mcp", ]: assert expected in dockerfile assert expected in entrypoint diff --git a/tests/test_hexstrike_mcp.py b/tests/test_hexstrike_mcp.py index c71964d..74261c9 100644 --- a/tests/test_hexstrike_mcp.py +++ b/tests/test_hexstrike_mcp.py @@ -1,4 +1,4 @@ -"""Tests for the HexStrike AI Gamma SSE adapter.""" +"""Tests for the HexStrike AI Gamma Streamable HTTP adapter.""" from __future__ import annotations @@ -44,8 +44,7 @@ def test_hexstrike_adapter_uses_upstream_package(tmp_path: Path, monkeypatch) -> app = module.create_app(upstream, "http://hexstrike-ai:8888", 1) route_paths = {getattr(route, "path", "") for route in app.routes} assert "/health" in route_paths - assert "/sse" in route_paths - assert "/messages" in route_paths or "/messages/" in route_paths + assert "/mcp" in route_paths def test_hexstrike_adapter_allows_internal_docker_hostname(tmp_path: Path, monkeypatch) -> None: # type: ignore[no-untyped-def] diff --git a/wire-mcp/server.py b/wire-mcp/server.py index 308edc1..e213626 100644 --- a/wire-mcp/server.py +++ b/wire-mcp/server.py @@ -13,7 +13,7 @@ - follow_stream — reconstruct a TCP/UDP stream - list_interfaces — list available capture interfaces -Transport: FastMCP SSE on port 9003. +Transport: FastMCP Streamable HTTP on port 9003. """ from __future__ import annotations @@ -38,6 +38,18 @@ mcp = FastMCP("wire-mcp", host="0.0.0.0", port=MCP_PORT) +@mcp.custom_route("/health", methods=["GET"]) +async def health_check(request): # type: ignore[no-untyped-def] + """Lightweight health probe for Docker and Makefile checks. + + The Streamable HTTP endpoint (/mcp) only answers MCP protocol requests, + so container health checks target this dedicated route instead. + """ + from starlette.responses import JSONResponse + + return JSONResponse({"status": "healthy", "service": "wire-mcp", "port": MCP_PORT}) + + async def _run_tshark(args: list[str], timeout: int = 60) -> dict: """Run a tshark command and return structured output.""" tshark = shutil.which("tshark") @@ -350,7 +362,7 @@ async def list_interfaces() -> str: # --------------------------------------------------------------------------- if __name__ == "__main__": - transport = os.environ.get("MCP_TRANSPORT", "sse") + transport = os.environ.get("MCP_TRANSPORT", "streamable-http") logger.info( "Starting WireMCP Server (%s on port %d)", transport, MCP_PORT, From dc59b33b1cbcec23d5c7dfd89edfe4d7807fb41f Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 17:44:11 +0000 Subject: [PATCH 6/6] Add containerized DeepSeek (Reasonix) agent as an alternative MCP client The linked deepseek-ai/awesome-deepseek-agent is a curated list, not a tool, so this integrates a concrete agent from it: Reasonix (esengine/DeepSeek- Reasonix), a DeepSeek-native, MIT-licensed terminal coding agent that DeepSeek officially endorses. Why Reasonix: it auto-reads a Claude-Code-style .mcp.json from the project root and maps mcpServers (type/url/headers, ${VAR} expansion) field-for-field onto its plugins, and its http transport IS Streamable HTTP (configuring sse returns an error). So it reuses the claude-code container's exact MCP wiring against the five servers, made possible by the recent SSE->Streamable HTTP migration. Added (mirrors the claude-code container pattern; does not replace it): - docker/deepseek.Dockerfile: node:22-slim, `npm install -g reasonix`, bakes the same .mcp.json (type http, /mcp URLs) plus a reasonix.toml whose provider reads the key from api_key_env = "DEEPSEEK_API_KEY" (never written to disk, so the first-run wizard is skipped and the container runs non-interactively). - docker/deepseek-entrypoint.sh: health-checks each MCP server, warns if DEEPSEEK_API_KEY is unset, then `exec reasonix code`. - docker-compose.yml: new `deepseek` service under profiles: ["deepseek"], depends_on all five MCP servers healthy. - Makefile: `make deepseek` target; deepseek profile added to down/clean/nuke/ status; build+push entries. - setup.sh: prompts for DEEPSEEK_API_KEY (or --deepseek-key), lists it in the keys reference, and surfaces `make deepseek` in the summary. - .env.example: DEEPSEEK_API_KEY alongside ANTHROPIC_API_KEY (each required only for its own in-Docker agent). - CI build matrix: deepseek image entry (keeps the publish-matrix test green). - README.md / DOCKER.md: tutorial, tables, and a container spec. - tests: assert the deepseek container wires all five MCP servers over /mcp and that the service/profile/provider are present. Full suite: 199 passed. Verified the rendered .mcp.json is valid JSON and the reasonix.toml parses as valid TOML. --- .env.example | 13 +- .github/workflows/build-and-push.yml | 4 + DOCKER.md | 18 ++- Makefile | 24 +++- README.md | 37 +++++- docker-compose.yml | 49 ++++++++ docker/deepseek-entrypoint.sh | 172 +++++++++++++++++++++++++++ docker/deepseek.Dockerfile | 64 ++++++++++ setup.sh | 34 +++++- tests/test_compose_integrations.py | 31 +++++ 10 files changed, 431 insertions(+), 15 deletions(-) create mode 100755 docker/deepseek-entrypoint.sh create mode 100644 docker/deepseek.Dockerfile diff --git a/.env.example b/.env.example index dac1af7..2b94dc6 100644 --- a/.env.example +++ b/.env.example @@ -7,11 +7,18 @@ # ╚══════════════════════════════════════════════════════════════════════╝ # ══════════════════════════════════════════════════════════════════════ -# ██ REQUIRED — Claude Code in Docker will not start without this ██ +# ██ AGENT API KEYS — needed only for the in-Docker agent you run ██ # ══════════════════════════════════════════════════════════════════════ -# Get your key at: https://console.anthropic.com/settings/keys -# Uncomment and set your key: +# Pick the agent you want to run inside Docker and set its key. Neither is +# needed for Claude Code on the host / Claude Code Web. +# +# Claude Code container (--profile claude-code / `make claude-code`): +# Get your key at: https://console.anthropic.com/settings/keys # ANTHROPIC_API_KEY=sk-ant-... +# +# DeepSeek (Reasonix) container (--profile deepseek / `make deepseek`): +# Get your key at: https://platform.deepseek.com/api_keys +# DEEPSEEK_API_KEY=sk-... # ══════════════════════════════════════════════════════════════════════ # OPTIONAL — Defaults work out of the box diff --git a/.github/workflows/build-and-push.yml b/.github/workflows/build-and-push.yml index 37b69af..6d8b71d 100644 --- a/.github/workflows/build-and-push.yml +++ b/.github/workflows/build-and-push.yml @@ -52,6 +52,10 @@ jobs: dockerfile: docker/claude-code.Dockerfile tag_prefix: "claude-code-" scout: false + - service: deepseek + dockerfile: docker/deepseek.Dockerfile + tag_prefix: "deepseek-" + scout: false - service: hexstrike-ai dockerfile: docker/hexstrike-ai.Dockerfile tag_prefix: "hexstrike-ai-" diff --git a/DOCKER.md b/DOCKER.md index f21f637..4b89068 100644 --- a/DOCKER.md +++ b/DOCKER.md @@ -27,6 +27,7 @@ Seven custom images are published to `crhacky/blhackbox` on Docker Hub: | **WireMCP** | `crhacky/blhackbox:wire-mcp` | `docker/wire-mcp.Dockerfile` | `debian:bookworm-slim` | | **Screenshot MCP** | `crhacky/blhackbox:screenshot-mcp` | `docker/screenshot-mcp.Dockerfile` | `python:3.13-slim` | | **Claude Code** | `crhacky/blhackbox:claude-code` | `docker/claude-code.Dockerfile` | `node:22-slim` | +| **DeepSeek (Reasonix)** | `crhacky/blhackbox:deepseek` | `docker/deepseek.Dockerfile` | `node:22-slim` | | **HexStrike API** | `crhacky/blhackbox:hexstrike-ai` | `docker/hexstrike-ai.Dockerfile` | `kalilinux/kali-rolling` | | **HexStrike MCP** | `crhacky/blhackbox:hexstrike-mcp` | `docker/hexstrike-mcp.Dockerfile` | `python:3.11-slim` | | **BOAZ MCP** | `crhacky/blhackbox:boaz-mcp` | `docker/boaz-mcp.Dockerfile` | `python:3.11-slim` | @@ -196,6 +197,7 @@ Skills are available in the container via two mechanisms: | `boaz-mcp` | `crhacky/blhackbox:boaz-mcp` | `9005` | default | BOAZ-MCP Gamma server (Streamable HTTP) | | `portainer` | `portainer/portainer-ce:latest` | `9443` | default | Docker management UI (HTTPS) | | `claude-code` | `crhacky/blhackbox:claude-code` | — | `claude-code` | Claude Code CLI client (Docker) | +| `deepseek` | `crhacky/blhackbox:deepseek` | — | `deepseek` | DeepSeek (Reasonix) terminal agent (Docker) | | `mcp-gateway` | `docker/mcp-gateway:latest` | `8080` | `gateway` | Single MCP entry point (host clients) | | `neo4j` | `neo4j:5` | `7474` / `7687` | `neo4j` | Cross-session knowledge graph | @@ -242,7 +244,8 @@ Requires `--profile gateway` (`make up-gateway`). | Variable | Default | Description | |:--|:--|:--| -| `ANTHROPIC_API_KEY` | — | Required for Claude Code in Docker | +| `ANTHROPIC_API_KEY` | — | Required for the Claude Code container (`--profile claude-code`) | +| `DEEPSEEK_API_KEY` | — | Required for the DeepSeek/Reasonix container (`--profile deepseek`) | | `MCP_GATEWAY_PORT` | `8080` | MCP Gateway host port (optional) | | `MSF_TIMEOUT` | `300` | Metasploit command timeout in seconds | | `NEO4J_URI` | `bolt://neo4j:7687` | Neo4j connection URI (optional) | @@ -305,6 +308,19 @@ Requires `--profile gateway` (`make up-gateway`). The Claude Code container includes the full skills system. Skills (`.claude/skills/`) and project instructions (`CLAUDE.md`) are baked into the image at build time and overridden by volume mounts at runtime for live updates. +### DeepSeek / Reasonix — `crhacky/blhackbox:deepseek` + +| | | +|:--|:--| +| **Base** | `node:22-slim` | +| **Agent** | [Reasonix](https://github.com/esengine/DeepSeek-Reasonix) (DeepSeek-native), installed via `npm install -g reasonix` | +| **Entrypoint** | `deepseek-entrypoint.sh` (health checks + launch) | +| **MCP config** | Auto-reads the baked Claude-style `.mcp.json`; Direct Streamable HTTP to each server (no gateway dependency) | +| **Provider** | `reasonix.toml` → DeepSeek (`https://api.deepseek.com`), key from `DEEPSEEK_API_KEY` env (never written to disk) | +| **Requires** | `DEEPSEEK_API_KEY` in `.env` | + +Reasonix maps the `.mcp.json` `mcpServers` entries (`type: http`, `url: …/mcp`) field-for-field onto its plugins, so it reaches the same five MCP servers as the Claude Code container. Launch it with `make deepseek` or `docker compose --profile deepseek run --rm deepseek`. Note that Claude Code *skills* (slash commands) are not a Reasonix feature; the agent works from natural-language instructions and the mounted `CLAUDE.md` methodology. + --- ## Portainer diff --git a/Makefile b/Makefile index 021f086..e0ff770 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: help setup up up-full up-gateway down logs test test-local lint format clean nuke \ pull status health portainer gateway-logs \ - claude-code \ + claude-code deepseek \ neo4j-browser logs-kali \ logs-wireshark logs-screenshot \ restart-kali \ @@ -27,7 +27,7 @@ up: ## Start default stack (7 containers: Kali, WireMCP, Screenshot, HexStrike A $(COMPOSE) up -d down: ## Stop all services (default + auxiliary profiles) - $(COMPOSE) --profile gateway --profile neo4j --profile claude-code down + $(COMPOSE) --profile gateway --profile neo4j --profile claude-code --profile deepseek down logs: ## Tail logs from all services $(COMPOSE) logs -f @@ -83,7 +83,7 @@ boaz-bridge: ## Run local BOAZ MCP helper server python boaz-mcp/server.py clean: ## Remove containers, volumes, networks, and build artifacts (keeps images) - $(COMPOSE) --profile gateway --profile neo4j --profile claude-code down -v --remove-orphans + $(COMPOSE) --profile gateway --profile neo4j --profile claude-code --profile deepseek down -v --remove-orphans find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true rm -rf dist/ build/ *.egg-info @@ -91,7 +91,7 @@ nuke: ## Full cleanup: containers + volumes + ALL images (frees max disk space) @echo "\033[1;33m WARNING: This will remove ALL blhackbox containers, volumes, AND images.\033[0m" @echo "\033[2m You will need to 'docker compose pull' or 'docker compose build' again.\033[0m" @echo "" - $(COMPOSE) --profile gateway --profile neo4j --profile claude-code down -v --remove-orphans --rmi all + $(COMPOSE) --profile gateway --profile neo4j --profile claude-code --profile deepseek down -v --remove-orphans --rmi all @echo "" @echo "\033[2m Pruning dangling images and build cache...\033[0m" docker image prune -f @@ -119,12 +119,24 @@ claude-code: ## Build and launch Claude Code in a Docker container @echo "" $(COMPOSE) --profile claude-code run --rm claude-code +# ── DeepSeek / Reasonix (Docker) ──────────────────────────────── +deepseek: ## Build and launch the DeepSeek (Reasonix) agent in a Docker container + $(COMPOSE) --profile deepseek pull deepseek || $(COMPOSE) --profile deepseek build deepseek + @echo "" + @echo "\033[1m Pre-flight Container Status\033[0m" + @echo "\033[2m ──────────────────────────────────────\033[0m" + @$(COMPOSE) ps --format "table {{.Name}}\t{{.Status}}" 2>/dev/null || $(COMPOSE) ps + @echo "" + @echo "\033[2m Waiting for all dependencies to become healthy...\033[0m" + @echo "" + $(COMPOSE) --profile deepseek run --rm deepseek + # ── Health & Status ────────────────────────────────────────────── status: ## Health status of all containers @echo "" @echo "\033[1m blhackbox Container Status\033[0m" @echo "\033[2m ──────────────────────────────────────\033[0m" - @$(COMPOSE) --profile gateway --profile neo4j --profile claude-code ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}" 2>/dev/null || $(COMPOSE) ps + @$(COMPOSE) --profile gateway --profile neo4j --profile claude-code --profile deepseek ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}" 2>/dev/null || $(COMPOSE) ps @echo "" health: ## Quick health check of all MCP servers @@ -215,6 +227,7 @@ push-all: ## Build and push all custom images to Docker Hub docker build -f docker/wire-mcp.Dockerfile -t crhacky/blhackbox:wire-mcp . docker build -f docker/screenshot-mcp.Dockerfile -t crhacky/blhackbox:screenshot-mcp . docker build -f docker/claude-code.Dockerfile -t crhacky/blhackbox:claude-code . + docker build -f docker/deepseek.Dockerfile -t crhacky/blhackbox:deepseek . docker build -f docker/hexstrike-ai.Dockerfile -t crhacky/blhackbox:hexstrike-ai . docker build -f docker/hexstrike-mcp.Dockerfile -t crhacky/blhackbox:hexstrike-mcp . docker build -f docker/boaz-mcp.Dockerfile -t crhacky/blhackbox:boaz-mcp . @@ -222,6 +235,7 @@ push-all: ## Build and push all custom images to Docker Hub docker push crhacky/blhackbox:wire-mcp docker push crhacky/blhackbox:screenshot-mcp docker push crhacky/blhackbox:claude-code + docker push crhacky/blhackbox:deepseek docker push crhacky/blhackbox:hexstrike-ai docker push crhacky/blhackbox:hexstrike-mcp docker push crhacky/blhackbox:boaz-mcp diff --git a/README.md b/README.md index 739fe32..1c252bc 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ |---|---| | **Getting Started** | [How It Works](#how-it-works) · [Architecture](#architecture) · [Prerequisites](#prerequisites) · [Installation](#installation) | | **Skills** | [Skills Overview](#skills--slash-commands) · [Available Skills](#available-skills) · [How Skills Work](#how-skills-work) | -| **Tutorials** | [Claude Code (Docker)](#tutorial-1-claude-code-docker--recommended) · [Claude Code (Web)](#tutorial-2-claude-code-web) · [Claude Desktop](#tutorial-3-claude-desktop-host--gateway) · [ChatGPT / OpenAI](#tutorial-4-chatgpt--openai-host--gateway) | +| **Tutorials** | [Claude Code (Docker)](#tutorial-1-claude-code-docker--recommended) · [DeepSeek (Reasonix)](#tutorial-1b-deepseek-reasonix-docker) · [Claude Code (Web)](#tutorial-2-claude-code-web) · [Claude Desktop](#tutorial-3-claude-desktop-host--gateway) · [ChatGPT / OpenAI](#tutorial-4-chatgpt--openai-host--gateway) | | **Advanced** | [Advanced Usage & FAQ](#advanced-usage--faq) | | **Reference** | [Components](#components) · [Output Files](#output-files) · [CLI Reference](#cli-reference) · [Makefile Shortcuts](#makefile-shortcuts) · [Docker Hub Images](#docker-hub-images) | | **Operations** | [Prompt Flow](#how-prompts-flow-through-the-system) · [MCP Gateway](#do-i-need-the-mcp-gateway) · [Portainer Setup](#portainer-setup) · [Neo4j](#neo4j-optional) · [Troubleshooting](#troubleshooting) | @@ -422,6 +422,8 @@ The entrypoint script checks each service and shows a status dashboard with avai You are now inside an interactive Claude Code session. +> **Prefer DeepSeek?** A drop-in alternative agent is available. Set `DEEPSEEK_API_KEY` in `.env` and run `make deepseek` (or `docker compose --profile deepseek run --rm deepseek`). It launches [Reasonix](https://github.com/esengine/DeepSeek-Reasonix), a DeepSeek-native terminal agent, wired to the same five MCP servers over Streamable HTTP. See [Tutorial 1b](#tutorial-1b-deepseek-reasonix-docker). + ### Step 3 — Verify the connection ``` @@ -466,6 +468,32 @@ Or use **Portainer** at `https://localhost:9443` for a unified dashboard. --- +## Tutorial 1b: DeepSeek (Reasonix, Docker) + +Prefer a DeepSeek-powered agent over Claude? [Reasonix](https://github.com/esengine/DeepSeek-Reasonix) is a DeepSeek-native terminal coding agent that connects to the **same five MCP servers** over Streamable HTTP — it reads a Claude-style `.mcp.json`, so the wiring is identical to the Claude Code container. It is added as a separate `deepseek` profile and does **not** replace Claude Code. + +### Step 1 — Set your DeepSeek key + +Put `DEEPSEEK_API_KEY` in `.env` (get one at [platform.deepseek.com/api_keys](https://platform.deepseek.com/api_keys)). `setup.sh` prompts for it, or add it manually. The key is read from the environment at runtime and never written into the image. + +### Step 2 — Launch the agent + +```bash +make deepseek +``` + +Or manually: + +```bash +docker compose --profile deepseek run --rm deepseek +``` + +The entrypoint checks each MCP server, then drops you into an interactive Reasonix session with all the pentest tools available. The default model is **DeepSeek-V4-Flash**; type `/pro` for a single Pro turn or `/preset max` to use Pro for the whole session. + +> **Note:** Slash-command *skills* (`/full-pentest`, `/quick-scan`, …) are a Claude Code feature. With Reasonix, describe your authorized target and goal in natural language and the agent calls the MCP tools directly; the methodology in `CLAUDE.md` is mounted at `/root/CLAUDE.md` for reference. + +--- + ## Tutorial 2: Claude Code (Web) Claude Code on [claude.ai/code](https://claude.ai/code) works as a web-based coding agent. When you open this repo in a web session, the MCP server configures itself automatically. @@ -731,6 +759,7 @@ STEP 7 ─ (OPTIONAL) RESULTS STORED IN NEO4J | MCP Client | Gateway? | How it connects | |:--|:--:|:--| | **Claude Code (Docker)** | No | Direct Streamable HTTP to each MCP server over Docker network | +| **DeepSeek / Reasonix (Docker)** | No | Direct Streamable HTTP to each MCP server over Docker network | | **Claude Code (Web)** | No | Stdio MCP server from `.mcp.json` | | **Claude Desktop** | **Yes** | Host GUI app → `localhost:8080/mcp` gateway | | **ChatGPT / OpenAI** | **Yes** | Host GUI/web app → `localhost:8080/mcp` gateway | @@ -851,6 +880,7 @@ blhackbox mcp # Start MCP server | `make up-gateway` | Start with MCP Gateway for Claude Desktop (8 containers) | | `make down` | Stop all services | | `make claude-code` | Build and launch Claude Code in Docker | +| `make deepseek` | Build and launch the DeepSeek (Reasonix) agent in Docker | | `make status` | Container status table | | `make health` | Quick health check of all services | | `make test` | Run tests | @@ -889,6 +919,7 @@ All custom images are published to `crhacky/blhackbox`: | `crhacky/blhackbox:hexstrike-mcp` | Upstream HexStrike Gamma MCP server over Streamable HTTP | | `crhacky/blhackbox:boaz-mcp` | Upstream BOAZ-MCP Gamma server over Streamable HTTP | | `crhacky/blhackbox:claude-code` | Claude Code CLI client (direct Streamable HTTP to MCP servers) | +| `crhacky/blhackbox:deepseek` | DeepSeek (Reasonix) terminal agent (direct Streamable HTTP to MCP servers) | Official images pulled directly: @@ -954,7 +985,9 @@ blhackbox/ │ ├── wire-mcp.Dockerfile │ ├── screenshot-mcp.Dockerfile │ ├── claude-code.Dockerfile MCP client container -│ └── claude-code-entrypoint.sh Startup script with health checks +│ ├── claude-code-entrypoint.sh Startup script with health checks +│ ├── deepseek.Dockerfile DeepSeek (Reasonix) MCP client container +│ └── deepseek-entrypoint.sh DeepSeek startup script with health checks ├── kali-mcp/ Kali MCP server (70+ tools + Metasploit) ├── wire-mcp/ WireMCP server (tshark, 7 tools) ├── screenshot-mcp/ Screenshot MCP server (Playwright, 4 tools) diff --git a/docker-compose.yml b/docker-compose.yml index 9747449..4d4bd28 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,6 +5,7 @@ # docker compose up -d Start default stack (Kali, WireMCP, Screenshot, HexStrike, BOAZ, Portainer) # docker compose --profile gateway up -d Start with MCP Gateway # docker compose --profile claude-code up -d Start with Claude Code container +# docker compose --profile deepseek run --rm deepseek Run the DeepSeek (Reasonix) agent # docker compose --profile neo4j up -d Start with Neo4j # docker compose build Build all custom images locally # @@ -368,6 +369,54 @@ services: networks: - blhackbox_net + # -- DEEPSEEK / REASONIX (OPTIONAL) ---------------------------------------- + # DeepSeek-native MCP client running inside Docker -- no host install needed. + # Enable with: docker compose --profile deepseek run --rm deepseek + # (or `make deepseek`) + # + # Reasonix (https://github.com/esengine/DeepSeek-Reasonix) connects DIRECTLY + # to each MCP server via Streamable HTTP over the Docker network by reading + # its baked .mcp.json (Claude Code's mcpServers schema). Does NOT require the + # MCP Gateway. Requires DEEPSEEK_API_KEY (read from env, never written to disk). + deepseek: + image: crhacky/blhackbox:deepseek + build: + context: . + dockerfile: docker/deepseek.Dockerfile + container_name: blhackbox-deepseek + profiles: ["deepseek"] + stdin_open: true + tty: true + environment: + DEEPSEEK_API_KEY: "${DEEPSEEK_API_KEY:-}" + # Bypass egress proxies (e.g. GitHub Codespaces) for internal Docker traffic + no_proxy: "mcp-gateway,kali-mcp,wire-mcp,screenshot-mcp,hexstrike-ai,hexstrike-bridge-mcp,boaz-mcp,localhost,127.0.0.1" + NO_PROXY: "mcp-gateway,kali-mcp,wire-mcp,screenshot-mcp,hexstrike-ai,hexstrike-bridge-mcp,boaz-mcp,localhost,127.0.0.1" + dns: + - 8.8.8.8 + - 1.1.1.1 + volumes: + - ./output/screenshots:/tmp/screenshots:ro + - ./output/reports:/root/reports + - ./output/sessions:/root/results + # Shared working data from Kali MCP (recon files, tool artifacts) + - shared-output:/root/kali-data:ro + # Mount project instructions so the agent has the latest methodology + - ./CLAUDE.md:/root/CLAUDE.md:ro + depends_on: + kali-mcp: + condition: service_healthy + wire-mcp: + condition: service_healthy + screenshot-mcp: + condition: service_healthy + hexstrike-bridge-mcp: + condition: service_healthy + boaz-mcp: + condition: service_healthy + networks: + - blhackbox_net + # -- PORTAINER CE ---------------------------------------------------------- # Web UI for container management -- https://localhost:9443 # Source: https://github.com/portainer/portainer diff --git a/docker/deepseek-entrypoint.sh b/docker/deepseek-entrypoint.sh new file mode 100755 index 0000000..f3d0cc7 --- /dev/null +++ b/docker/deepseek-entrypoint.sh @@ -0,0 +1,172 @@ +#!/bin/bash +set -euo pipefail + +# ── Colors ────────────────────────────────────────────────────────── +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +BOLD='\033[1m' +DIM='\033[2m' +NC='\033[0m' # No Color + +# ── Symbols ───────────────────────────────────────────────────────── +CHECK="${GREEN}OK${NC}" +CROSS="${RED}FAIL${NC}" +WARN="${YELLOW}WARN${NC}" +WAIT="${DIM}....${NC}" + +# ── Configuration ─────────────────────────────────────────────────── +MAX_RETRIES=20 +RETRY_INTERVAL=3 + +# Ensure internal Docker hostnames bypass any egress proxy. +export no_proxy="${no_proxy:+${no_proxy},}mcp-gateway,kali-mcp,wire-mcp,screenshot-mcp,hexstrike-ai,hexstrike-bridge-mcp,boaz-mcp,localhost,127.0.0.1" +export NO_PROXY="$no_proxy" + +# ── Functions ─────────────────────────────────────────────────────── + +print_banner() { + echo "" + echo -e "${CYAN}${BOLD} ╔══════════════════════════════════════════════╗${NC}" + echo -e "${CYAN}${BOLD} ║ blhackbox v2.0 — DeepSeek (Reasonix) ║${NC}" + echo -e "${CYAN}${BOLD} ║ MCP-based Pentesting Framework ║${NC}" + echo -e "${CYAN}${BOLD} ╚══════════════════════════════════════════════╝${NC}" + echo "" +} + +# Check a single service. Returns 0 on success, 1 on failure. +check_service() { + local name="$1" + local url="$2" + local timeout="${3:-3}" + curl -s --max-time "$timeout" -o /dev/null "$url" 2>/dev/null + local rc=$? + # A bare GET to the Streamable HTTP endpoint (/mcp) returns an HTTP 4xx + # (no MCP session/headers) — curl still exits 0 because it received a + # response, which confirms the server is up. Exit code 28 (transfer + # timed out) is also treated as success for any endpoint that streams. + [ "$rc" -eq 0 ] || [ "$rc" -eq 28 ] +} + +# Wait for a service with retries. Prints status. +wait_for_service() { + local name="$1" + local url="$2" + local retries="${3:-$MAX_RETRIES}" + + printf " %-22s " "$name" + + for i in $(seq 1 "$retries"); do + if check_service "$name" "$url"; then + echo -e "[ ${CHECK} ]" + return 0 + fi + sleep "$RETRY_INTERVAL" + done + + echo -e "[ ${CROSS} ] (unreachable at $url)" + return 1 +} + +# ── Output directory symlinks ────────────────────────────────────── +# Report/session paths resolve to /root/output/* (WORKDIR is /root). +# Bind mounts are at /root/reports, /root/results, /tmp/screenshots. +# Create symlinks so both path conventions reach the bind mounts. +mkdir -p /root/output +ln -sfn /root/reports /root/output/reports +ln -sfn /root/results /root/output/sessions +ln -sfn /tmp/screenshots /root/output/screenshots + +# ── Main ──────────────────────────────────────────────────────────── + +print_banner + +# DeepSeek API key is required for Reasonix to authenticate against the +# DeepSeek API. It is read from the environment (reasonix.toml api_key_env). +if [ -z "${DEEPSEEK_API_KEY:-}" ]; then + echo -e " ${WARN} DEEPSEEK_API_KEY is not set — Reasonix cannot authenticate." + echo -e " ${DIM}Add it to .env and re-run, or pass -e DEEPSEEK_API_KEY=sk-...${NC}" + echo -e " ${DIM}Get a key at https://platform.deepseek.com/api_keys${NC}" + echo "" +fi + +echo -e "${BOLD}Checking service connectivity...${NC}" +echo -e "${DIM}Waiting for services to become healthy.${NC}" +echo "" + +MCP_OK=0 +MCP_FAIL=0 + +# -- MCP Servers (Reasonix connects via Streamable HTTP) -- +echo -e " ${BOLD}MCP Servers${NC}" +if wait_for_service "Kali MCP" "http://kali-mcp:9001/mcp"; then + MCP_OK=$((MCP_OK + 1)) +else + MCP_FAIL=$((MCP_FAIL + 1)) +fi + +# WireMCP shares kali-mcp's network namespace, so use kali-mcp hostname +if wait_for_service "WireMCP" "http://kali-mcp:9003/mcp"; then + MCP_OK=$((MCP_OK + 1)) +else + MCP_FAIL=$((MCP_FAIL + 1)) +fi + +if wait_for_service "Screenshot MCP" "http://screenshot-mcp:9004/mcp"; then + MCP_OK=$((MCP_OK + 1)) +else + MCP_FAIL=$((MCP_FAIL + 1)) +fi + +if wait_for_service "BOAZ MCP" "http://boaz-mcp:9005/mcp"; then + MCP_OK=$((MCP_OK + 1)) +else + MCP_FAIL=$((MCP_FAIL + 1)) +fi + +if wait_for_service "HexStrike MCP" "http://hexstrike-bridge-mcp:9006/mcp"; then + MCP_OK=$((MCP_OK + 1)) +else + MCP_FAIL=$((MCP_FAIL + 1)) +fi + +# Summary +echo "" +echo -e "${DIM}──────────────────────────────────────────────────${NC}" + +if [ "$MCP_FAIL" -eq 0 ]; then + echo -e "${GREEN}${BOLD} All $MCP_OK MCP servers connected.${NC}" +else + echo -e "${YELLOW}${BOLD} $MCP_OK/$((MCP_OK + MCP_FAIL)) MCP servers connected. $MCP_FAIL unreachable.${NC}" + echo -e "${DIM} Reasonix will start — unreachable servers simply won't expose tools.${NC}" + echo -e "${DIM} Use 'docker compose ps' in another terminal to check container health.${NC}" +fi + +echo "" +echo -e "${DIM}──────────────────────────────────────────────────${NC}" +echo -e " ${BOLD}MCP servers (connected via Streamable HTTP):${NC}" +echo -e " kali ${DIM}Kali Linux security tools + Metasploit (70+ tools)${NC}" +echo -e " wireshark ${DIM}WireMCP — tshark packet capture & analysis${NC}" +echo -e " screenshot ${DIM}Screenshot MCP — headless Chromium evidence capture${NC}" +echo -e " boaz ${DIM}BOAZ-MCP Gamma — agentic offensive security tools${NC}" +echo -e " hexstrike ${DIM}HexStrike Gamma — AI security automation tools${NC}" +echo "" +echo -e " ${BOLD}Model:${NC} ${DIM}DeepSeek-V4-Flash (default). Type ${NC}${CYAN}/pro${NC}${DIM} for one Pro turn,${NC}" +echo -e " ${DIM}or ${NC}${CYAN}/preset max${NC}${DIM} to use Pro for the whole session.${NC}" +echo "" +echo -e " ${BOLD}Methodology:${NC} ${DIM}Pentest workflow and rules are in ${NC}${CYAN}/root/CLAUDE.md${NC}${DIM}.${NC}" +echo -e " ${DIM}Describe your authorized target and goal; Reasonix will call the MCP tools.${NC}" +echo "" +echo -e " ${BOLD}Output files${NC} ${DIM}(mounted to host ./output/)${NC}${BOLD}:${NC}" +echo -e " ${DIM}output/reports/ → ./output/reports/ pentest reports${NC}" +echo -e " ${DIM}output/screenshots/ → ./output/screenshots/ PoC evidence (read-only)${NC}" +echo -e " ${DIM}output/sessions/ → ./output/sessions/ session data${NC}" +echo -e " ${DIM}/root/kali-data/ ← shared Kali MCP recon artifacts (read-only)${NC}" +echo -e "${DIM}──────────────────────────────────────────────────${NC}" +echo "" + +# Launch the Reasonix coding agent. `reasonix code` opens the interactive TUI; +# any args passed to the container are forwarded. +exec reasonix code "$@" diff --git a/docker/deepseek.Dockerfile b/docker/deepseek.Dockerfile new file mode 100644 index 0000000..be74b7e --- /dev/null +++ b/docker/deepseek.Dockerfile @@ -0,0 +1,64 @@ +# DeepSeek (Reasonix) MCP Client — runs inside the blhackbox Docker network. +# Usage: +# docker compose --profile deepseek run --rm deepseek +# +# Reasonix is a DeepSeek-native terminal coding agent (https://github.com/ +# esengine/DeepSeek-Reasonix). It connects DIRECTLY to each MCP server via +# Streamable HTTP on the internal blhackbox_net network by reading the baked +# .mcp.json (Claude Code's exact mcpServers schema). No MCP Gateway required, +# no host-side install. + +FROM node:22-slim + +# Reasonix ships a single Go binary delivered through npm. +RUN npm install -g reasonix + +# curl for health checks, python3/jq for data processing, +# and dnsutils for DNS resolution debugging +RUN apt-get update && apt-get install -y --no-install-recommends \ + curl \ + jq \ + python3 \ + dnsutils \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /root + +# DeepSeek provider config. The API key is read from the DEEPSEEK_API_KEY +# environment variable at runtime (api_key_env) and is never written to disk. +# Default model is the cost-efficient DeepSeek-V4-Flash; switch to Pro at +# runtime with /pro (next turn) or /preset max (whole session). +RUN printf '%s\n' \ + 'default_model = "deepseek-flash"' \ + '' \ + '[[providers]]' \ + 'name = "deepseek-flash"' \ + 'kind = "openai"' \ + 'base_url = "https://api.deepseek.com"' \ + 'model = "deepseek-v4-flash"' \ + 'api_key_env = "DEEPSEEK_API_KEY"' \ + > reasonix.toml + +# Reasonix auto-reads a Claude-Code .mcp.json from the project root and maps it +# field-for-field onto its plugins (type/url/headers, ${VAR} expansion). This is +# the same wiring the claude-code container uses. Wire-MCP shares kali-mcp's +# network namespace, so it's accessed via the kali-mcp hostname on port 9003. +RUN echo '{ \ + "mcpServers": { \ + "kali": { "type": "http", "url": "http://kali-mcp:9001/mcp" }, \ + "wireshark": { "type": "http", "url": "http://kali-mcp:9003/mcp" }, \ + "screenshot": { "type": "http", "url": "http://screenshot-mcp:9004/mcp" }, \ + "boaz": { "type": "http", "url": "http://boaz-mcp:9005/mcp" }, \ + "hexstrike": { "type": "http", "url": "http://hexstrike-bridge-mcp:9006/mcp" } \ + } \ +}' > .mcp.json + +# Project methodology, available on the filesystem for reference. A volume mount +# in docker-compose.yml overrides this at runtime with the latest version. +COPY CLAUDE.md /root/CLAUDE.md + +# Startup script: checks each MCP server, shows status, launches Reasonix. +COPY docker/deepseek-entrypoint.sh /usr/local/bin/deepseek-entrypoint.sh +RUN chmod +x /usr/local/bin/deepseek-entrypoint.sh + +ENTRYPOINT ["/usr/local/bin/deepseek-entrypoint.sh"] diff --git a/setup.sh b/setup.sh index 9293d4c..38f3739 100755 --- a/setup.sh +++ b/setup.sh @@ -27,6 +27,7 @@ ARROW="${CYAN}→${NC}" # ── Globals ────────────────────────────────────────────────────────── SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" API_KEY="" +DEEPSEEK_KEY="" MINIMAL=false SKIP_PULL=false NEO4J_PASS="" @@ -47,7 +48,8 @@ usage() { echo "Usage: $0 [OPTIONS]" echo "" echo "Options:" - echo " --api-key KEY Set ANTHROPIC_API_KEY (skips interactive prompt)" + echo " --api-key KEY Set ANTHROPIC_API_KEY for the Claude Code container" + echo " --deepseek-key KEY Set DEEPSEEK_API_KEY for the DeepSeek (Reasonix) container" echo " --minimal Core stack only (no Neo4j)" echo " --with-neo4j Enable Neo4j knowledge graph" echo " --with-gateway Enable MCP Gateway for Claude Desktop/ChatGPT" @@ -163,6 +165,23 @@ configure_env() { echo -e " ${WARN} ANTHROPIC_API_KEY skipped — Claude Code Docker won't start without it" fi + # --- DEEPSEEK_API_KEY (for the DeepSeek / Reasonix container) --- + if [ -z "$DEEPSEEK_KEY" ]; then + echo "" + echo -e " ${BOLD}DEEPSEEK_API_KEY${NC} ${DIM}(for the DeepSeek/Reasonix agent in Docker)${NC}" + echo -e " ${DIM}Get yours at: https://platform.deepseek.com/api_keys${NC}" + echo -e " ${DIM}Press Enter to skip if you won't use the DeepSeek agent.${NC}" + read -rsp " API Key: " DEEPSEEK_KEY + echo "" + fi + + if [ -n "$DEEPSEEK_KEY" ]; then + sed -i "s|^# DEEPSEEK_API_KEY=sk-.*|DEEPSEEK_API_KEY=${DEEPSEEK_KEY}|" "$SCRIPT_DIR/.env" + echo -e " ${CHECK} DEEPSEEK_API_KEY configured" + else + echo -e " ${WARN} DEEPSEEK_API_KEY skipped — the DeepSeek agent won't start without it" + fi + # --- NEO4J_PASSWORD --- if [[ "$PROFILES" == *"neo4j"* ]]; then if [ -z "$NEO4J_PASS" ]; then @@ -183,10 +202,12 @@ configure_env() { echo "" echo -e " ${BOLD}Keys & tokens${NC} ${DIM}(edit .env to add them, then restart the stack):${NC}" echo "" - echo -e " ${BOLD}Required${NC}" - echo -e " ${CYAN}ANTHROPIC_API_KEY${NC} ${DIM}Only for Claude Code inside Docker (--profile${NC}" - echo -e " ${DIM}claude-code). Not needed for Claude Code Web/host.${NC}" + echo -e " ${BOLD}Agent keys (set the one for the in-Docker agent you run)${NC}" + echo -e " ${CYAN}ANTHROPIC_API_KEY${NC} ${DIM}Claude Code container (--profile claude-code).${NC}" + echo -e " ${DIM}Not needed for Claude Code Web/host.${NC}" echo -e " ${DIM}→ https://console.anthropic.com/settings/keys${NC}" + echo -e " ${CYAN}DEEPSEEK_API_KEY${NC} ${DIM}DeepSeek (Reasonix) container (--profile deepseek).${NC}" + echo -e " ${DIM}→ https://platform.deepseek.com/api_keys${NC}" echo "" echo -e " ${BOLD}Optional — widen recon (all tools work without them)${NC}" echo -e " ${CYAN}WPSCAN_API_TOKEN${NC} ${DIM}WordPress vuln database; wpscan auto-reads it.${NC}" @@ -322,6 +343,7 @@ print_summary() { echo "" echo -e " ${BOLD}Quick start:${NC}" echo -e " ${CYAN}make claude-code${NC} ${DIM}Launch Claude Code in Docker${NC}" + echo -e " ${CYAN}make deepseek${NC} ${DIM}Launch the DeepSeek (Reasonix) agent in Docker${NC}" echo -e " ${CYAN}make status${NC} ${DIM}Check service status${NC}" echo -e " ${CYAN}make health${NC} ${DIM}Run health checks${NC}" echo -e " ${CYAN}make logs${NC} ${DIM}View service logs${NC}" @@ -359,6 +381,10 @@ while [[ $# -gt 0 ]]; do API_KEY="$2" shift 2 ;; + --deepseek-key) + DEEPSEEK_KEY="$2" + shift 2 + ;; --minimal) MINIMAL=true shift diff --git a/tests/test_compose_integrations.py b/tests/test_compose_integrations.py index 734d29f..ce0aea0 100644 --- a/tests/test_compose_integrations.py +++ b/tests/test_compose_integrations.py @@ -83,3 +83,34 @@ def test_claude_code_container_wires_all_default_mcp_servers() -> None: assert "hexstrike" in dockerfile assert "boaz-mcp" in entrypoint assert "hexstrike-bridge-mcp" in entrypoint + + +def test_deepseek_container_wires_all_default_mcp_servers() -> None: + dockerfile = (ROOT / "docker" / "deepseek.Dockerfile").read_text(encoding="utf-8") + entrypoint = (ROOT / "docker" / "deepseek-entrypoint.sh").read_text(encoding="utf-8") + + for expected in [ + "http://kali-mcp:9001/mcp", + "http://kali-mcp:9003/mcp", + "http://screenshot-mcp:9004/mcp", + "http://boaz-mcp:9005/mcp", + "http://hexstrike-bridge-mcp:9006/mcp", + ]: + assert expected in dockerfile + assert expected in entrypoint + + # Reasonix install + DeepSeek provider that reads the key from the env. + assert "npm install -g reasonix" in dockerfile + assert "reasonix.toml" in dockerfile + assert 'api_key_env = "DEEPSEEK_API_KEY"' in dockerfile + # Launches the Reasonix coding agent. + assert "reasonix code" in entrypoint + + +def test_deepseek_service_is_in_compose_under_profile() -> None: + compose = COMPOSE.read_text(encoding="utf-8") + assert "deepseek:" in compose + assert "image: crhacky/blhackbox:deepseek" in compose + assert 'profiles: ["deepseek"]' in compose + assert "docker/deepseek.Dockerfile" in compose + assert "DEEPSEEK_API_KEY" in compose