EasyHunt-AI

EasyHunt-AI

MCP server for AI-driven VAPT orchestration, enabling agents to plan and execute authorized security scans through a control plane that enforces scope, sanitization, budget, rate limits, human approval, and audit logging.

Category
访问服务器

README

EasyHunt AI

Agentic VAPT orchestrator. Drives open-source security engines through a custom MCP server, runs inside the Claude CLI, and routes model traffic through OpenRouter.

Authorized testing only. Owned assets, an in-scope bug bounty program, or org assets with documented written approval. The scope.yaml you write is the authorization boundary, and the server refuses every request that falls outside it.


What it actually is

A control plane that sits between an AI agent and ~50 security tools. The agent plans; the control plane decides what is permitted. Every capability — engine, wrapper, or user-supplied plugin — passes through one fixed sequence:

scope → sanitize → budget → rate-limit → approval → sandbox exec
      → parse/normalize → audit → structured return

There is no flag, argument, or debug mode that skips a step. That is the whole design: adding the fiftieth tool cannot accidentally add the first unguarded one.

The five rules it enforces in code

Rule Where it lives
Denylist beats allowlist; unparseable input fails closed control_plane/scope.py
Arguments are rejected, never sanitized-and-run control_plane/sanitize.py
Aggressive and exploit actions stop for a human control_plane/approval.py
No PoC, no finding — only a reproducible proof confirms knowledge/findings.py
No scope, rate-limit, or attribution evasion capability, ever sanitize.GLOBAL_DENIED_FLAGS

The fourth is worth spelling out: Finding.confirm() requires a PoC with both reproduction steps and an observed result. AI triage can rank, downgrade, and drop — a taskflow that declares a confirm verdict is rejected at load time.


Install

git clone <your-fork> EasyHunt-AI && cd EasyHunt-AI
./install.sh                    # package, skills, MCP registration
easyhunt install                # the ~20-tool core pipeline
easyhunt install --all          # all 64, including cloud and LLM red-team

easyhunt install is idempotent, dependency-ordered, and verifies every tool after installing it — a successful go install does not mean a working tool. It reports per-tool failures with the command and stderr and keeps going, so one broken recipe costs you one tool rather than the run.

easyhunt install --dry-run      # show the plan, change nothing
easyhunt install --category dns # one group at a time
easyhunt doctor --fix           # repair what is already here

It never installs into EasyHunt's own environment — Python tools go through pipx, isolated. That is enforced with a guard, after pip install semgrep once pulled in fastmcp-slim and silently broke the application's MCP client.

Then, before anything else:

cp scope.example.yaml scope.yaml
$EDITOR scope.yaml              # fill in from the program's policy page
easyhunt doctor                 # what is installed, configured, and missing
easyhunt scope example.com      # confirm a target resolves the way you expect

In Claude Code: /easyhunt.

What "installed" means here

doctor and the installer both resolve tools by identity, not PATH order. httpx is both ProjectDiscovery's prober and the Python HTTP library's CLI; if the wrong one is first on your PATH it exits zero, prints nothing, and looks exactly like a target with no live hosts. EasyHunt runs each candidate once and picks the one that identifies itself, so a shadowed install is reported and used correctly rather than silently producing empty scans.


Architecture

L5  STRATEGY   Claude CLI — plans and decides. No network access of its own.
L4  METHOD     8 Claude Skills, one per VAPT phase.
L3  CONTROL    MCP server — scope, sanitize, rate-limit, approve, sandbox, audit.
L2  EXECUTION  Engines (BBOT · Nuclei · Osmedeus · Strix) + ~30 atomic wrappers.
L1  KNOWLEDGE  Rule packs · task graph · findings store · evidence · PoC memory.

               LLM traffic ──▶ OpenRouter (3 tiers, fallbacks, price ceilings)

Engines over wrappers. BBOT already orchestrates 80+ recon modules, so EasyHunt drives it through its Python API rather than wrapping each one. Atomic wrappers exist where surgical control matters.

Scope is enforced twice. BBOT's own whitelist/blacklist are populated from scope.yaml, and every emitted event is re-checked before storage — a module that resolves outward cannot smuggle a host into the findings store.


Extending it

Drop a YAML file into rules/ and you have a new detection. No code change.

Directory Format Run by
rules/nuclei/ Nuclei templates + workflows Nuclei engine
rules/easyhunt/ native matcher/extractor packs built-in matcher engine
rules/jaeles/, rules/semgrep/ those tools' native formats their engines
rules/bbot/ BBOT presets BBOT
rules/easyhunt/*.py + manifest Python plugin the EasyHunt runner

Every rule must declare a verify block saying how a hit gets confirmed, and a Python plugin claiming mode: passive while its source reaches for an aggressive primitive is refused at load time — that check exists so the approval gate cannot be bypassed by mislabeling.

easyhunt rules          # what loaded, and what was rejected and why

A rejected rule is a detection you think you have and don't, so rules_list() surfaces rejections to the agent too.


Cost control

Three tiers, configured in config.yaml, never hardcoded:

  • T0 — dedupe, classify, bulk-summarize recon.
  • T1 — correlation, candidate ranking, false-positive triage.
  • T2 — exploit reasoning and the final report.

With models[] fallbacks (billed only for the one that runs, openrouter/auto last so a renamed slug degrades instead of failing), a max_price ceiling per tier, per-phase token budgets, and rate-limit demotion to a cheaper tier rather than failing a phase.

Raw tool output never reaches a model. It is parsed, deduplicated, and filtered in code first, then map-reduced on the cheap tier. Everything except AI triage and report synthesis works with no API key at all.


Remote access (OAuth 2.1 + PKCE)

stdio — the normal Claude CLI setup — is a pipe to the parent process and needs no auth. The remote transport is different: a network-reachable EasyHunt runs scanners and exploitation tools on request, so binding a non-loopback address without auth is refused outright, not warned about.

auth:
  mode: jwt                                # or oauth_proxy
  base_url: https://easyhunt.internal.example.com
  jwks_uri: https://idp.example.com/.well-known/jwks.json
  issuer: https://idp.example.com/
  authorization_servers: [https://idp.example.com]

EasyHunt acts as an OAuth 2.1 Resource Server: it publishes RFC 9728 protected-resource metadata, answers unauthenticated calls with WWW-Authenticate: Bearer resource_metadata="…", and verifies bearer tokens against your IdP. PKCE is S256-only — the MCP SDK types the challenge method as Literal["S256"], so plain cannot be negotiated. Tokens are audience-bound to base_url (RFC 8707), so one minted for another service that trusts the same IdP is rejected here.

Scopes map onto EasyHunt's risk tiers, which is where this earns its keep:

Scope Unlocks
easyhunt:read status, findings, scope checks — no target contact
easyhunt:recon passive tools
easyhunt:scan aggressive tools (ports, nuclei, brute force)
easyhunt:exploit exploit tools (PoC validation, takeover confirmation)
easyhunt:approve answering approval prompts
easyhunt:admin loading a scope, reloading rules

A token is a ceiling, checked before the human approval gate rather than instead of it — a CI token holding only easyhunt:recon cannot invoke exploitation even if a human would have approved it. Scope filtering applies to discovery as well as invocation, so an unauthenticated caller cannot even enumerate the tooling.

easyhunt:approve is deliberately separate from every operational scope. If the agent's token could satisfy it, the agent could answer its own approval prompts and human-in-the-loop would be decorative. Issue it to an operator's token and nothing else.

For an IdP without Dynamic Client Registration (GitHub, Google), use mode: oauth_proxy; FastMCP fronts it and forwards PKCE and the resource indicator upstream. Credentials come from the environment, never config.yaml.

Safety properties worth knowing

  • Audit log is hash-chained. Every attempt — including refusals — is one JSONL line carrying the previous line's digest. Deletions and edits are detectable. Credential-shaped values are redacted on the way in.
  • Tool output is treated as untrusted input. Prompt-injection markers in target-controlled text are stripped before it reaches a context window, with a visible [stripped: ...] marker left behind.
  • Tool definitions are cryptographically pinned. A passive tool that becomes an exploit tool between runs is reported as a privilege escalation.
  • Budget ceilings abort cleanly. Report generation is deliberately exempt from the spend gate, so a stopped run still produces a report — labelled PARTIAL on its first page.
  • Canary defense in triage. Fabricated findings on .invalid hosts are mixed into every batch; a pass that "confirms" one has its verdicts weighted down, and the measurement is reported.

Reasoning across an engagement

Attack paths. cloud_attack_paths turns posture findings into reachability: which internet-facing entry point reaches which valuable resource, in how many hops. Paths are ranked by what the destination is worth against how exposed the entry is — a two-hop path to customer data outranks a one-hop path to an empty dev bucket. With Cartography + Neo4j the edges are observed; without it they are inferred from control failures and labelled as such.

Graph memory. Every asset, finding, and relationship is indexed as the run proceeds, so graph_recall("api.example.com") answers "what do I already know about this host" without a re-scan. Native by default — Neo4j is optional and only adds cross-engagement persistence. Stores the index, never the loot.

Rendered graphs. Reports get taskgraph.svg and attack-paths.svg (plus .dot, and .png when a converter is installed). SVG is generated by a dependency-free layered-DAG layout, because a report artifact that only exists when Graphviz happens to be installed is one you cannot rely on.

Prompt caching. Stable instructions carry an explicit cache_control breakpoint with volatile data after them, so a triage phase pays for its rubric once instead of twenty times. Cached tokens and the resulting savings are recorded per call in the audit log.


Layout

easyhunt/
├── mcp_server.py          MCP entrypoint — the only door
├── control_plane/         scope · sanitize · ratelimit · approval
│                          sandbox · audit · budget · jobs · pins
├── engines/               bbot · nuclei · osmedeus · strix
├── tools/                 base.py (the decorator) + wrappers by phase
├── plugins/               manifest schema · loader · matcher engine
├── knowledge/             findings · taskgraph · memory
├── llm/                   openrouter · summarize · triage
└── report/                synthesize.py
rules/ · taskflows/ · skills/ · tests/
docs/ · scripts/ · CLAUDE.md · bootstrap.sh

Documentation

CLAUDE.md is loaded automatically by Claude CLI and carries the hard invariants — read it first. Full index in docs/README.md.

Document Answers
CLAUDE.md The invariants, working rhythm, and known traps.
docs/ARCHITECTURE.md Mind map, control-plane sequence, engagement flow, module map.
docs/BUILD_STATUS.md What works, what does not, what is left.
docs/BOOTSTRAP.md New-machine setup and troubleshooting.
docs/PAYLOADS.md Vetted payload store: tiers, quarantine, tool mapping.

New machine? ./bootstrap.sh — idempotent, safe to re-run.

Development

.venv/bin/python -m pytest tests/ -q          # 601 tests
.venv/bin/python -m pytest tests/test_security.py -q   # adversarial suite
.venv/bin/ruff check easyhunt/ tests/

tests/test_security.py tries to defeat each control — scope bypass via homoglyphs, IP encodings and list smuggling; sanitizer fuzzing; approval bypass; prompt injection; tool-definition tampering. tests/test_e2e.py runs the full pipeline against a deliberately misconfigured server it starts on loopback.

License

MIT. Note that several wrapped tools carry stronger licenses — TruffleHog and masscan are AGPL-3.0, nmap is NPSL. Each tool's license is recorded in its ToolSpec and printed in the report's tool inventory, which matters the moment anyone redistributes a bundle.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选