All notable changes to Vulnerator AI are documented here.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Caido Automate, Intercept and proxy capture (
caido_automate,caido_intercept,caido_proxy) — three more Caido subsystems as first-class kali-mcp tools, each verified end-to-end against Caido 0.59.0 + OWASP Juice Shop/DVWA.caido_automate: Intruder/ffuf-style fuzzing (mark an injection point with§, give a payload list, get per-payload status/length/timing), behind the same scope-guard ascaido_request.caido_intercept: a singleaction-dispatched tool to hold/list/read/edit-forward/drop traffic on Caido's proxy.caido_proxy+CAIDO_PROXY_CAPTURE=1: routekali_run's HTTP-tool traffic (curl/nuclei/ffuf/sqlmap/wget) through Caido so it is captured in the history and interceptable — CA fetched at startup with background retry until Caido is reachable, proxy env injected into subprocesses only (never the kali-mcp process),NO_PROXYexcludes Caido to avoid a loop. Stdlib-purecaido_automate.py/caido_intercept.py/caido_proxy.py(no new deps). Seedocs/caido.md. - Caido integration (
caido_graphql,caido_request,caido_history) — kali-mcp can now drive Caido (proxy + Replay + HTTPQL + scope + workflows), so "anything Caido can do, Vulnerator can do".caido_graphqlis a version-agnostic passthrough to Caido's whole public GraphQL API;caido_requestsends a request through Caido's Replay (logged and searchable) behind the same scope-guard askali_run(fullscheme://host:portis validated, soportsinscope.jsonis honored);caido_historysearches captured traffic by HTTPQL. Newcaidoservice indocker-compose.yml(internal network only, persistent volume,--allow-guests): fully zero-touch — kali-mcp logs in as guest and selects a project on its own. Stdlib-puredocker/kali/caido_client.py(no new dependencies), auto-renews a stale session if Caido is recreated, and reportsunauthenticated/unreachableinstead of faking success. Seedocs/caido.md.
dns_recontool (DNSDumpster API) — Newkali-mcptool for DNS + attack-surface recon. Given a domain, enumerates hosts/subdomains, unique IPs, ASN/PTR, CIDRs and HTTP/HTTPS banners in a single blocking call, normalizing the response into a consumable attack surface for downstream scanning. Honors the API rate limit (1 req/2s) internally with pagination and a single 429 retry; fails closed withoutDNSDUMPSTER_API_KEY. Pure-stdlib module (dnsdumpster_client.py) with a thin@mcp.toolwrapper.webtech_scantool (whatweb + webanalyze + wpscan cross-reference) — Newkali-mcptool that runs three fingerprinters and merges their output into a singletechnology → {versions per source, best_version, version_conflict}table, raising version confidence and surfacing discrepancies. Each binary is optional (skipped and reported, never faked);wpscanreports "not WordPress" as a normal result and usesWPSCAN_API_TOKENfor CVE data when present. Pure-stdlib module (webtech_scan.py) with a thin@mcp.toolwrapper.- Recon tooling wiring —
kali_mcp_serverexposes both tools and reports real binary availability (recon_tools) anddnsdumpster_key_presentinserver_info. Dockerfile installswpscan(apt) andwebanalyze(pinned release, checksum-verified) with its fingerprint DB at/opt/webanalyze/technologies.json..env.example,docker-compose.ymlandinstall.shwire the two optional API keys;docs/usage.mddocuments the tools. Backed by 37 new tests (204 total). - Automatic LLM fallback with GLM-5.3 Flash — Configured native Hermes
fallback_providerschain withz-ai/glm-5.3-flashas automatic fallback. When Mistral Large 4 fails (rate-limit 429, server error 500/502/503, auth failure 401/403), Hermes automatically switches mid-session without losing context. Per-turn failover: each message attempts primary first. Same Cyber Index as Mistral (50%) but 20x cheaper ($0.07/$0.21 vs $1.36/$4.18). Proven in production for end-to-end exploits and 0-day discovery. Top CyberGym score (84.5%). Manual override viaOPENROUTER_MODELenv var orhermes config set model.default. Seedocs/modelos-cyberseguridad-openrouter-CORRECTED.mdfor full analysis. - Enhanced model documentation — Updated
agent-ooda/profile/config.yamlwith detailedfallback_providersconfiguration and prompt cache cost warnings,.env.examplewith automatic fallback behavior, and README section on native Hermes fallback mechanism.
- Kanban board tracking (optional) — Hermes Agent's Kanban system integrated as opt-in tracking layer for long pentests. Provides crash recovery, dependency DAG, and audit trail without changing default OODA loop behavior. Enabled via
kanbantoolset inconfig.yaml. - Increased delegation concurrency —
max_concurrent_childrenincreased from 10 to 50 workers, validated by Nous 1,393-agent refactor (218 concurrent workers stable). Enables massive parallel scans for /24 networks. - Complete Kanban documentation — New guides:
agent-ooda/KANBAN-USAGE.md(usage patterns, workflow examples, troubleshooting) anddocs/KANBAN-INTEGRATION.md(technical changes, design decisions, roadmap). - Extended SOUL.md — New section "Loop state management with todo_list and Kanban" (74 lines) documenting when to use each tracking system and OODA+Kanban workflow patterns.
- Documentation language — All repository documentation standardized to English for consistency.
1.5.0 - 2026-10-18
- Hermes web dashboard on
:9119— built-in browser UI activated viaHERMES_DASHBOARD=1with basic-auth and the Vulnerator-AI custom skin (dark red/green cyber theme, block ASCII banner,⚡prompt symbol, OODA spinner verbs). labs/looney-tunables-ctf— isolated CVE-2023-4911 (glibc 2.37 LPE) lab. Includes uname wrapper to mask linuxkit kernel false positives, tini as PID 1, and documented engagement prompts for bothmode: pentestandmode: ctf.labs/pinguinazo-ssti— Flask/Jinja2 SSTI reverse-shell lab. Attack path: SSTI → RCE → reverse shell to kali → sudo java → root. Integrates withvulnerator-ai_defaultnetwork for reverse shell routing. Inspired by dockerlabs.es "Pinguinazo".pentest-reportskill v0.3 — two-layer report:report_gen.pystructured base + LLM narrative enrichment + standalone HTML with Vulnerator-AI visual theme.- Landing web (
docs/): CRT boot screen with lens/barrel effect, Whisper-synced karaoke lyrics, audio controls bar, VULNERATOR! page inversion flash, scroll reveal animations, content drawer, screenshot lightbox, CTF and pentest sample reports. todotoolset enabled so the agent usestodo_listfor structured OODA state tracking across context compression and session restarts.
- SOUL.md — multiple improvements:
modo: pentestvsmodo: redteam/ctfengagement mode selection.- Evidence discipline: only real tool output counts; zero search results = "not found".
- 3-step no-progress counter with concrete, exhaustive criteria.
- ORIENT phase always calls
read_findingsto reload engagement state. todo_liststructured template (OBSERVE/ORIENT/DECIDE/ACT/REPORT).- Reverse shell guidance via
kali_execbackground listener. - Container environment awareness: userspace vulns work in containers.
- OODA format label
OODA — <FASE> (paso <N>)enforced as mandatory. - Ephemeral system prompt reinforces format on every turn.
config.yaml—todoadded to toolsets;display.skin: vulneratoractivates custom skin.docker-compose.yml—HERMES_DASHBOARD=1+ basic-auth env vars; port 9119 published.
1.4.0 - 2026-10-16
install.sheasy installer. An interactive installer that reduces first-run setup to a single input: theOPENROUTER_API_KEY. It checks prerequisites (docker,docker composev2,openssl), auto-generates the two secret tokensHERMES_API_SERVER_KEYandVULNERATOR_MCP_INBOUND_TOKENas separate 32-byte hex values (openssl rand -hex 32), builds the.envfrom.env.example(filling in only those three keys and preserving every other default and the template comments), and brings the default stack up withdocker compose up -d --build— without the Juice Shop lab. The OpenRouter key is read with no terminal echo, or taken from an exportedOPENROUTER_API_KEYfor non-interactive runs. Flags:--with-juice-shop(also start the OWASP Juice Shop practice lab),--no-up(write the.envonly),--force(overwrite an existing.env; otherwise it refuses to clobber one). The manualcp .env.example .envpath still works.- README "Let an AI assistant set it up for you" block. A copy-paste prompt the user hands to an
LLM coding assistant (Claude Code / Kiro / Cursor) with shell access, so the assistant runs
install.shand wires up thevulnerator-mcpstdio server end to end — the user only supplies the OpenRouter key when asked.
- README trimmed to a short Quick Start; detail moved into
docs/. The README now leads with the./install.shQuick Start (plus a collapsed manual-setup fallback) and a documentation index, keeping only a condensed architecture summary and the authorized-use warning. The long-form content was split into new topic docs:docs/configuration.md(every.envvariable, AWS credentials, local Ollama inference),docs/usage.md(driving a pentest via TUI / MCP client / raw HTTP, the Juice Shop lab, clean restarts between exercises), anddocs/security.md(the no-guardrails model, the opt-in scope-guard, the MCP inbound token). No behavior changed; this is a documentation reorganization. pentest-reportnow emits the report in English.docker/kali/report_gen.pypreviously rendered the Markdown deliverable in Spanish; its output strings (section headings, status labels, executive summary, methodology, evidence labels, and themainsummary line) are now English, aligned with the repo's public documentation. Logic is unchanged and the module's own code comments/docstrings stay in Spanish like the rest ofdocker/kali/. The unit tests indocker/kali/tests/test_report_gen.pywere updated to assert the English output.- Added a redacted English sample deliverable (
docs/example-report.md) and its matching findings store (docs/example-findings.jsonl), linked from the README, showing the end-to-end OODA-over-MCP output (recon → recorded findings with ATT&CKtechnique_idand verbatim evidence → generated report). Target IP uses the RFC 5737 documentation address; device serial and hostname are redacted.
vulnerator-mcpMCP front door over the Hermes:8642runs API (up by default). A thin FastMCP wrapper (docker/mcp/) that lets external MCP clients (Claude Code / Kiro locally over stdio; remote/containerized consumers like BugTraceAI over streamable-HTTP) trigger, observe, steer and stop a Hermes OODA pentest as MCP tools. It WRAPS, does not replace, the HTTP API: it exposes ONLY the runs lifecycle — five tools (start_pentest,get_run_status,stream_run_events,steer_run,stop_run) plushealth()— so the client stays a trigger/observer and never the brain. It never exposes/v1/chat/completionsor any rawkali_runpass-through. The wrapper is stateless and version-tolerant: the run object and events are forwarded opaquely and terminality is derived from the run booleans (completed/interrupted), never from thestatusstring; the upstream version is read fromGET /healthand reported verbatim, never branched on.stream_run_eventsuses the eventseqas a portable cursor (batched pages withnext_cursor/done) and additionally emits MCP progress notifications over streamable-HTTP, degrading to pure batching on stdio. Shipped as a 4th service in the defaultdocker-compose.yml— the default stack is now 4 containers (kali,ooda-agent,playwright-mcp,vulnerator-mcp), brought up with a plaindocker compose up -d --build— because the product's intended UX is driving the engine from an MCP client. The streamable-HTTP service binds the internal docker network with host publication OFF by default (noports:block; opt-in by settingVULNERATOR_MCP_HOST_PORTand uncommenting the service'sports:block) and is fail-closed on a mandatory inbound token (VULNERATOR_MCP_INBOUND_TOKEN): it refuses to start without one and rejects any request without the matchingAuthorization: Bearer(constant-time compare), with an exact-match carve-out for a dedicated/healthzroute only. The same image also runs stdio for local Claude Code / Kiro with no token and no port (zero network surface). Upstream auth is a pass-through Bearer fromHERMES_API_SERVER_KEY(no second secret for the:8642hop). The requiredscopeargument is advisory, folded into the prompt for operator clarity — the MCP layer enforces NO scope and adds NO safety (the optional Kali-layer scope-guard from v1.3.0 is a separate, opt-in defense-in-depth layer). New.env.exampleentries (VULNERATOR_MCP_INBOUND_TOKEN,VULNERATOR_MCP_HOST_PORT), a README section with a copy-paste Claude Code / Kiro stdiomcpServerssnippet and a loud no-guardrails warning, and unit tests for the SSE cursor parser and scope-folding/validation logic.stream_run_eventspaging is hardened: a batch cut short by any cap (max_events, the ~256 KiB byte budget, or thewait_secondswall-clock budget) returnsdone: falseand the confirmingget_runruns ONLY on a genuine stream drain, so a client looping untildonenever drops the tail of a multi-page terminal run; the byte budget is checked BEFORE adding an event (never overshoots the transport limit by a whole event); the SSE read is async with a deadline-aware cancellation so a quiet upstream ends the batch atwait_secondsinstead of stalling on the network timeout — the deadline now also wraps response acquisition and the error-body drain, so an upstream that accepts the connection but withholds headers is bounded bywait_secondstoo (not just the connect timeout) — and if a non-2xx error body itself stalls past the deadline, the already-observed status is still reported as a bareupstream_errorenvelope (terminal for paging) instead of degrading to an empty deadline page that a loop-until-doneclient would re-issue; a single SSE event is bounded by an absolute per-event ceiling (~512 KiB) and, if a single event exceeds it, the batch fails loud: the event is NOT forwarded (neither verbatim — truncating an opaque event would break pass-through — nor as an in-eventsplaceholder, which would drop the untrusted payload and consume the cursor) and the cursor is NOT advanced; instead a bare{"error": {...}}envelope withcode: "oversized_event"carries the event metadata (seq/type/size, payload withheld), terminal for paging, and the real terminal state is recovered viaget_run_status— so an oversized event can never exceed the transport message limit, never silently drops its payload, and never returns arun.completedmarker withdone: false; sub-ceiling events on the same page are delivered complete first; terminality requires the literal booleanTrue; a stream failure preserves the full{"error": {...}}envelope (surfaced understream_errorafter partial events, orterminality_errorfor a failed confirmingget_run), while a failure received BEFORE any event (invalidrun_id,run_not_found, unreachable) returns the bare envelope — terminal for paging, like every other tool; and the untrustedrun_idis encoded as a single path segment (route-traversal rejected before any upstream call). All six tools are async and offload their blocking:8642call to a worker thread, so a slow upstream never freezes the streamable-HTTP event loop (the MCP SDK runs sync tool bodies inline).httpxanduvicorncarry lower-bound pins in line with the repo's dependency discipline.
1.3.0 - 2026-10-16
- Opt-in scope-guard for
kali_run/kali_exec. A deterministic (code, not prompt) layer that validates the DESTINATION of each raw-shell action BEFORE executing it. It is opt-in: with noscope.jsonpresent (path viaSCOPE_FILE, default/scope/scope.json) andenabled: true, behavior is identical to before (no gate). When active it is fail-closed: Hermes must declare the new optionaltargetsargument (the IP/host/URL the command touches), and any destination outside the allowed scope — or indeny— blocks the whole execution with a structuredSCOPE_VIOLATIONerror WITHOUT running.SCOPE_ENFORCE=0is a kill-switch that force-disables the guard even if the file saysenabled: true. Zero new dependencies (stdlibjson/ipaddress/urllib.parse); validation is IP-against-CIDR plus LITERAL hostname match (no DNS) with optional ports, anddenytakes priority overallow. Each violation is logged into the engagement findings store as adiscardedSCOPE_VIOLATIONrecord for an auditable trail. Newscope.example.jsontemplate, a commented bind-mount indocker-compose.yml, and a README section document how to turn it on. Scope coverage: onlykali_run/kali_exec(cloud and browser tools unchanged).
1.2.0 - 2026-10-16
- Curated pentest CLIs baked into the Kali image. The Kali
Dockerfilenow pre-installs a small, deliberate set the skills assume exist and invoke viakali_run:nmap,whatweb,nuclei,ffuf,sqlmap,gobuster, plusimpacket-scriptsandbloodhound.py. The basekalilinux/kali-rollingimage ships none of these, so this fixes a latent runtime gap while keeping the image reasonably sized (curated, not the fullkali-linux-headlessmetapackage). - Documented Juice Shop lab quickstart. New README subsection documenting how to bring the
stack up together with
docker-compose.target.yml(OWASP Juice Shop) and point an engagement athttp://juice-shop:3000— a deliberately-vulnerable web target on the internal network (not exposed to the host) for practicing theweb-pentestskill.
- The Ollama startup branch now warns (non-fatal, to stderr) when
OLLAMA_BASE_URLis set butOLLAMA_MODELis empty, since the profile default model name would otherwise be used against the Ollama endpoint (which almost certainly does not serve it). Behavior is otherwise unchanged. - Added a regression test for the OpenRouter-vs-Ollama provider-selection startup logic in
docker-compose.yml, protecting the optional${...:-}env form, the fail-closed OpenRouter guard and the new empty-OLLAMA_MODELwarning against silent regressions.
1.1.0 - 2026-10-16
- Opt-in local / remote Ollama inference. Set
OLLAMA_BASE_URLin.envto point Hermes at an Ollama OpenAI-compatible endpoint (localhttp://host.docker.internal:11434/v1or a remotehttp://<host>:11434/v1) instead of OpenRouter. Leave it empty to keep the OpenRouter default behavior. OLLAMA_MODELto set the Ollama model name used in Ollama mode (e.g.qwen2.5-coder:32b).extra_hosts: host.docker.internal:host-gatewayonooda-agentso a host-run Ollama is reachable on Linux as well.
OPENROUTER_API_KEYis no longer required when running in Ollama mode. The fail-closed guard (abort when the key is missing) is re-created in the startup script and now applies only to OpenRouter mode, so default behavior is unchanged.- Documented the Ollama caveats: the endpoint must serve a context window of at least ~64K
tokens (
OLLAMA_CONTEXT_LENGTH=64000), and the model must support reliable tool/function calling and not refuse the authorized-offensive framing. Local parity with Mistral Large on OpenRouter is not guaranteed (experimental).
1.0.1 - 2026-10-16
- Configurable OpenRouter model via
OPENROUTER_MODEL. Override the model Hermes reasons with from.env; empty falls back to the profile default (mistralai/mistral-large-4-0), so existing setups are unaffected. VERSIONfile.
- The project deliberately uses Mistral Large because models like Claude (
anthropic/*) refuse the authorized-offensive pentest framing; overriding with such a model may make the agent refuse to work.