tamamo
tamamo is an LLM-driven web honeypot that mimics the behavior of real internal admin pages to lure and observe attackers. It generates realistic login screens, dashboards, API endpoints, and server signatures using LLM, then serves them as fully functional decoy sites — capturing every interaction for analysis.
The name "tamamo" comes from Tamamo-no-Mae (玉藻の前), a legendary fox spirit in Japanese mythology known for its shape-shifting abilities. Just as Tamamo-no-Mae disguised itself to deceive, this tool disguises honeypots as legitimate services to deceive attackers.



Getting Started
The fastest way to try tamamo — generate a scenario and start serving it in one command:
go run github.com/secmon-lab/tamamo@latest serve \
--llm-provider openai \
--llm-api-key $OPENAI_API_KEY
Then open http://localhost:8080 in your browser. You'll see a realistic-looking admin login page generated by LLM, ready to capture any interaction.
Features
- LLM-powered scenario generation — Generates complete honeypot scenarios including login pages, dashboard pages, API routes, and server signatures using LLM agents
- Multi-provider LLM support — OpenAI, Claude (Anthropic), and Gemini (Google Cloud)
- Realistic authentication simulation — Configurable auth strategy that rejects initial login attempts before succeeding, mimicking real systems
- Event emission — Captures all attacker interactions and reports via structured logging, webhook (with HMAC-SHA256 signature), and/or Google Cloud Pub/Sub
- Scenario portability — Scenarios are exported as ZIP files and can be shared, versioned, and deployed independently
Install
go install github.com/secmon-lab/tamamo@latest
Quick Start
Generate a scenario
# Generate with default settings (random site type, style, taste)
tamamo generate --llm-provider openai --llm-api-key $OPENAI_API_KEY
# Customize the scenario
tamamo generate \
--llm-provider claude \
--llm-api-key $ANTHROPIC_API_KEY \
--site-type "Employee directory & HR portal" \
--site-style "corporate-minimal" \
--site-taste "Looks like it was built 10 years ago and never updated" \
--site-lang "Japanese" \
--output my-scenario.zip
Serve a scenario
# Serve a pre-generated scenario
tamamo serve --scenario my-scenario.zip --addr 0.0.0.0:8080
# Auto-generate and serve in one step
tamamo serve \
--llm-provider openai \
--llm-api-key $OPENAI_API_KEY \
--addr 0.0.0.0:8080
Validate a scenario
tamamo validate --scenario my-scenario.zip
Commands
tamamo generate
Generate a honeypot scenario using LLM.
| Flag |
Env |
Description |
--llm-provider |
TAMAMO_LLM_PROVIDER |
LLM provider: openai, claude, gemini |
--llm-api-key |
TAMAMO_LLM_API_KEY |
API key for the LLM provider |
--llm-model |
TAMAMO_LLM_MODEL |
Model name (provider-specific default if omitted) |
--output, -o |
|
Output ZIP file path (default: scenario.zip) |
--site-type |
TAMAMO_SITE_TYPE |
Site type (random if omitted) |
--site-style |
TAMAMO_SITE_STYLE |
Visual style (random if omitted) |
--site-taste |
TAMAMO_SITE_TASTE |
Taste/atmosphere (random if omitted) |
--site-color |
TAMAMO_SITE_COLOR |
Color scheme (random if omitted) |
--site-lang |
TAMAMO_SITE_LANG |
Display language (default: English) |
--extra-prompt |
TAMAMO_EXTRA_PROMPT |
Additional prompt text |
--prompt-file |
|
Additional prompt from file |
--max-retries |
|
Max retries on validation failure (default: 3) |
--dump-dir |
|
Dump raw files to directory (debugging) |
--keep-tmp |
|
Keep temp generation directory (debugging) |
For Gemini provider:
| Flag |
Env |
Description |
--gemini-project |
TAMAMO_GEMINI_PROJECT |
Google Cloud project ID |
--gemini-location |
TAMAMO_GEMINI_LOCATION |
Google Cloud location (default: us-central1) |
tamamo serve
Start the honeypot HTTP server.
| Flag |
Env |
Description |
--scenario, -s |
|
Scenario ZIP or directory path (auto-generates if omitted) |
--addr |
|
Listen address (default: 127.0.0.1:8080) |
--node-id |
TAMAMO_NODE_ID |
Node identifier (default: hostname) |
--tls |
TAMAMO_TLS |
Enable HTTPS with auto-generated self-signed certificate |
--tls-cert |
TAMAMO_TLS_CERT |
Path to TLS certificate file (requires --tls and --tls-key) |
--tls-key |
TAMAMO_TLS_KEY |
Path to TLS private key file (requires --tls and --tls-cert) |
--webhook-url |
TAMAMO_WEBHOOK_URL |
Webhook URL for event notification |
--webhook-secret |
TAMAMO_WEBHOOK_SECRET |
HMAC-SHA256 signing secret for webhook |
--pubsub-project-id |
TAMAMO_PUBSUB_PROJECT_ID |
Google Cloud project ID for Pub/Sub |
--pubsub-topic-id |
TAMAMO_PUBSUB_TOPIC_ID |
Pub/Sub topic ID for event notification |
--pubsub-sa-key |
TAMAMO_PUBSUB_SA_KEY |
Service account key JSON data (takes priority over ADC) |
All generate flags are also available when --scenario is omitted.
tamamo validate
Validate a scenario for correctness. Reports all errors at once.
| Flag |
Description |
--scenario, -s |
Scenario ZIP or directory path (required) |
Scenario Structure
A scenario is a ZIP file (or directory) containing:
scenario.json # Metadata (name, server signature, headers)
routes.json # Route definitions (paths, methods, responses)
pages/
login.html # Login page
dashboard.html # Perpetual loading dashboard
logo.svg # (optional) Generated images/assets
Authentication Strategy
Login endpoints support an auth field in routes.json that simulates realistic authentication behavior:
{
"path": "/api/auth/login",
"method": "POST",
"status_code": 200,
"headers": {"Content-Type": "application/json"},
"body": "{\"success\": true, \"redirect\": \"/dashboard\"}",
"auth": {
"min_failures": 3,
"success_probability": 0.2,
"failure_status_code": 401,
"failure_body": "{\"success\": false, \"error\": \"Invalid credentials\"}",
"failure_headers": {"Content-Type": "application/json"},
"credential_fields": ["username", "password"]
}
}
The server tracks unique credential submissions per source IP. The first min_failures unique credentials always fail. After that, each new unique credential has a success_probability chance of succeeding — making the timing unpredictable and realistic. The same credential always returns the same result. Only fields listed in credential_fields are used to determine uniqueness (other fields like CSRF tokens are ignored). Both JSON and form-urlencoded submissions are supported.
Event Notification
All attacker interactions are captured and emitted as structured events:
{
"timestamp": "2026-03-20T12:34:56Z",
"node_id": "honeypot-01",
"event_type": "http_request",
"source_ip": "203.0.113.1",
"method": "POST",
"path": "/api/auth/login",
"headers": {"User-Agent": "..."},
"body": {"username": "admin", "password": "P@ssw0rd"},
"scenario": "acme-corp-admin"
}
- Log (always active): Structured log output via slog
- Webhook: HTTP POST with
X-Tamamo-Signature: sha256=<hex> header (HMAC-SHA256)
License
Apache License 2.0