GraphQL recon & analysis CLI — find endpoints, dump schema, flag risky fields.
detection-only · scope-aware · bug-bounty ready
🌍 bess1lie.github.io · 🔍 apihunter · 🎯 bounthunt
⚡ 30-second start
pip install gqlhunter
# 1. scope — allowlist for your target (never scan out-of-scope)
cat > scope.yaml <<'YAML'
targets: ["https://example.com"]
allowlist: ["example.com"]
YAML
# 2. discover + scan + risk in one go
gqlhunter discover https://example.com --scope scope.yaml
gqlhunter scan https://example.com/graphql --scope scope.yaml
# 3. report + dashboard
gqlhunter report --db gqlhunter_*.db --format html -o report.html
gqlhunter dashboard --db gqlhunter_*.db
# -> http://127.0.0.1:8080
Why now: 46k GraphQL issues found across 1500 APIs in 2024, 10% critical (Escape Tech). Introspection + batching + depth misconfigs are still the top 3.
✨ Features
| Feature | What it does | Output |
|---|---|---|
| Discovery | 18 common paths + POST fallback | live endpoints |
| Introspection | Configurable depth, handles REQUIRES_AUTH/FILTERED |
__schema |
| Risk | delete*/admin*/reset* + IDOR args (id, email, uuid) |
critical/high/medium/low |
| Auth | With vs without token, body-aware (Unauthorized in 200) |
public/auth_required/over_permissive |
| Diff | Schema changes across 2 runs | added/modified/removed |
| Variants | alias, arg-removal, depth | query templates |
| Export | JSON clean + SARIF 2.1.0 | gqlhunter.sarif for Code Scanning |
| Notify | Slack / Telegram / Webhook via Jinja | notify |
| Dashboard | SQLite + built-in HTTP UI | /api/runs |
🚀 Demo
| discover + scan | report + dashboard |
$ gqlhunter discover https://example.com --scope scope.yaml
╭────────── Discovered ──────────╮
│ https://example.com/graphql 200 │
│ https://example.com/graphiql 200 │
╰──────────────────────────────╯
$ gqlhunter scan https://example.com/graphql --scope scope.yaml
Introspection: enabled (HTTP 200)
Stored 18 types, 8 queries, 3 mutations
Risk findings: 2 high, 1 medium
|
|
📖 Commands
| Command | Purpose | Example |
|---|---|---|
discover |
Find GraphQL endpoints | gqlhunter discover https://example.com --scope scope.yaml |
scan |
Introspection + risk (single endpoint) | gqlhunter scan https://example.com/graphql --scope scope.yaml --max-depth 5 |
batch |
Multi-target from scope.yaml |
gqlhunter batch scope.yaml --db batch.db |
auth |
Token vs anon comparison | gqlhunter auth https://example.com/graphql --scope scope.yaml --auth-header "Bearer x" --db scan.db |
variants |
Query variant generation | gqlhunter variants --db scan.db --strategy combinations |
report |
HTML / Markdown | gqlhunter report --db scan.db -o report.html |
export |
JSON + SARIF | gqlhunter export --db scan.db --output out/ --sarif |
diff |
Last 2 runs diff | gqlhunter diff --db batch.db |
notify |
Slack/TG/webhook | gqlhunter notify slack --db scan.db --webhook-url https://hooks.slack.com/... |
dashboard |
Web UI | gqlhunter dashboard --db scan.db |
Full docs: docs/scope.md · docs/examples.md · docs/notifications.md
🏗️ Architecture
flowchart LR
T[Target] --> D[Discovery 18 paths + POST]
D --> I[Introspection]
I --> P[Parser]
P --> A[Risk IDOR+BOLA]
P --> Q[Query Builder]
P --> U[Auth Analyzer]
A --> DB[(SQLite)]
Q --> DB
U --> DB
DB --> R[Report HTML/MD]
DB --> E[Export SARIF]
DB --> V[Dashboard]
DB --> N[Diff/Notify]
Stack: Python 3.11+ · Typer · httpx (+sse) · SQLite (WAL) · Jinja2 · Docker
🛡️ Philosophy
| 🔍 | Detection only — never payloads, never exploitation |
| 🛡️ | Scope-aware — every request gated by scope.yaml |
| 📂 | Open formats — SQLite, HTML, SARIF 2.1.0 |
| 🧪 | 202 tests in CI |
🗺️ Roadmap
| Feature | Status |
|---|---|
| Discovery (18 paths + POST) | ✅ |
| Introspection + risk + IDOR | ✅ |
| Auth body-aware (200+errors) | ✅ |
| Dashboard + diff + SARIF | ✅ |
| Batching amplification tester | 🚧 next |
| Depth/Complexity DoS tester | 🚧 |
| Clairvoyance (introspection off) | 🔮 |
| WebSocket subscriptions | 🔮 |
❓ FAQ
Does it exploit? No. It discovers and classifies. Variant queries include # DO NOT AUTO-RUN warning.
Introspection disabled? Marked FILTERED/DISABLED. Next: Clairvoyance-lite via Did you mean ...? reconstruction.
Scope required? Yes. scope.yaml with targets/allowlist is mandatory for discover/scan/batch.
SARIF upload? gqlhunter.sarif → GitHub Code Scanning. Version synced from __version__.
🤝 Contributing
git clone https://github.com/bess1lie/gqlhunter.git
cd gqlhunter
pip install -e ".[dev]"
pytest -q # 202 tests
ruff check gqlhunter/ && ruff format --check gqlhunter/
See CONTRIBUTING.md if present, else open an issue.
📄 License
MIT — see LICENSE.
built in Almaty · bess1lie · detection-first security tooling
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gqlhunter-0.2.1.tar.gz.
File metadata
- Download URL: gqlhunter-0.2.1.tar.gz
- Upload date:
- Size: 204.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8a4567b99845d1118dd42db8fb90c214baf677be604567681d1809e9b7848ad5
|
|
| MD5 |
6b34d03370e47a5ac2a07be88dfb8175
|
|
| BLAKE2b-256 |
ce63105f1b53bf8a932ee318d131990c92ad6e3094998f6edb8802241a38ac81
|
File details
Details for the file gqlhunter-0.2.1-py3-none-any.whl.
File metadata
- Download URL: gqlhunter-0.2.1-py3-none-any.whl
- Upload date:
- Size: 40.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30832c9e3ce668757cb77cce9dfea75d6f58e63f93f77c270ed9d9d1e0f02a60
|
|
| MD5 |
3c8ef8586227bf9f682077a4964b09aa
|
|
| BLAKE2b-256 |
80c65b1be1fa4ad3cc859aa1fdc019b41ecbee1635b9603e011d592b55e3178e
|