
honeyprompt v0.1.8
Estrutura de decepção centrada em LLM: "O honeypot que responde!™"
honeyprompt

Apresentando o honeyprompt, um framework de decepção focado em LLM feito por/para desenvolvedores web. O projeto pessoal de @alectrocute.
Suporta todos os principais provedores de LLM em nuvem e locais. SSH, HTTP, TLS, TCP, telnet e mais. Ele é distribuído como um contêiner pequeno (e um único binário estático) e mantém todas as opções em um único honeyprompt.yaml.
Sem plugins para compilar, sem banco de dados para executar, facilmente extensível e pode ser implantado em hardware de baixo custo.
Instância de demonstração
Uma instância de demonstração está disponível em 172.233.151.216, com o painel web não autenticado aqui: http://172.233.151.216:9090. É uma instância pública do honeyprompt executando em um VPS barato da Linode, com openrouter/free como único provedor/modelo de LLM.
Início rápido
Para a configuração mais fácil em 2026, recomendamos Docker e OpenRouter/openrouter/free como provedor de LLM. Todos os principais provedores de LLM em nuvem e locais são suportados. Três arquivos e um comando montam a implantação padrão completa: sete iscas baseadas em LLM, armazenamento durável de eventos e o painel do operador.
1. Obtenha a configuração padrão, o arquivo compose e o template de env:
# if you don't have Docker:
# curl -fsSL get.docker.com -o get-docker.sh && sh get-docker.sh
mkdir honeypot && cd honeypot
wget https://raw.githubusercontent.com/alectrocute/honeyprompt/main/honeyprompt.yaml
wget https://raw.githubusercontent.com/alectrocute/honeyprompt/main/compose.yaml
wget -O .env https://raw.githubusercontent.com/alectrocute/honeyprompt/main/.env.example
(Ou clone o repositório e cd para ele — os mesmos três arquivos.)
2. Preencha o .env. Dois valores são obrigatórios:
OPENROUTER_API_KEY=sk-or-... # use a dedicated key with a spend limit
HONEYPROMPT_PANEL_PASSWORD=changeme # basic-auth password for the panel
3. Inicie:
docker compose up -d
4. Teste-o:
ssh -p 2222 root@localhost # password: root — then type anything
curl http://localhost:2375/v1.54/containers/json # "exposed" Docker API
5. Observe acontecer no painel somente leitura em http://127.0.0.1:9090 (faça login como admin com sua senha do painel). Cada conexão, credencial e comando é transmitido ao vivo. Se você estiver implantado em um host remoto, precisará expor a porta :9090 no compose.yaml. Isso não é recomendado para implantações em produção.
Use uma versão numerada em vez de
latestpara implantações em produção — definaHONEYPROMPT_IMAGEno.env.
O arquivo honeyprompt.yaml que você acabou de baixar é uma demonstração totalmente anotada. Ele vem com perfis para:
- Um servidor web corporativo genérico — porta 80, a rede mais ampla;
/serve a página de boas-vindas padrão do nginx instantaneamente, e caminhos mais profundos caem no LLM para páginas completas de intranet em HTML/CSS, formulários de login e painéis de administração criados para manter o atacante clicando. - Gateways MCP / agentes — Descoberta HTTP streamable, metadados OAuth, chamadas de ferramentas JSON-RPC e ferramentas de produção tentadoras.
- API Docker Engine 29.5 — a superfície não autenticada da porta 2375 usada por vermes reais de nuvem.
- API Kubernetes v1.36 — descoberta de namespace, workload, Secret, ConfigMap e RBAC.
- Infraestrutura de build de IA Ubuntu 26.04 — SSH, workloads de GPU, Docker, kubeconfigs, estado de CI e credenciais de provedores.
- Redis 8.8 — sondas RESP comuns usadas para roubo de credenciais, persistência e movimento lateral.
- Borda industrial / OT — um plano de gerenciamento Telnet intencionalmente legado, porque a defesa moderna ainda precisa capturar ataques contra infraestruturas antigas.
Executando sem um LLM
[!IMPORTANT] Mesmo se você estiver usando LLMs, determine os caminhos mais frequentemente usados e adicione regras estáticas para eles. Isso economizará uma quantidade massiva de tokens de LLM e acelerará as respostas a requisições que não valem o custo de uma chamada de LLM. Exemplos aleatórios:
whoami, verificações de saúde, favicon, sondas de versão, etc.
Este honeyprompt.yaml mínimo simula uma caixa SSH com duas regras estáticas e nenhum LLM:
panel:
enabled: true
address: "0.0.0.0:8080"
events:
buffer: 2000
file: /data/events.jsonl # durable attacker activity
services:
- protocol: ssh
address: "0.0.0.0:2222"
description: "Ubuntu 26.04 LTS build runner"
serverName: "gpu-runner-07"
passwordRegex: "^(root|admin|123456)$" # which passwords "work"
commands:
- regex: "^whoami$"
handler: "root"
- regex: "^(.+)$"
handler: "bash: command not found"
docker run --rm \
-p 2222:2222 -p 8080:8080 \
-v "$(pwd)/honeyprompt.yaml:/etc/honeyprompt/honeyprompt.yaml:ro" \
-v honeyprompt-data:/data \
alectrocute/honeyprompt:latest
Implantação
Para uma implantação persistente, use o compose.yaml incluído. O guia de implantação cobre lançamentos no Docker Hub, segredos necessários do GitHub, configuração de porta e firewall, acesso ao painel via SSH, atualizações, rollback, armazenamento de eventos e isolamento.
Por que decepção focada em LLM, resumidamente
Um honeypot só precisa fazer uma coisa bem: permanecer convincente tempo suficiente para que o atacante continue digitando. Cada comando que ele executa é inteligência — as ferramentas que ele usa, as credenciais que reutiliza, as CVEs que ele assume que você não corrigiu. Honeypots estáticos quebram o personagem no momento em que alguém executa um comando que o autor não previu. O honeypot entrega esse momento a um LLM, para que o shell responda a dmesg | tail ou cat /etc/shadow como um real faria, e a sessão continua.
Confira a excelente apresentação de Adel Karimi no DEF CON 32 sobre Galah, (o primeiro?) honeypot LLM, que inspirou este projeto: https://www.youtube.com/watch?v=XGsm4Qcc_Ag
O que é registrado: dois fluxos separados
Esta é a parte que vale a pena entender de antemão, porque as duas são deliberadamente mantidas separadas:
- Eventos de decepção: Toda interação do atacante: conexões, tentativas de autenticação, cada comando ou requisição, a resposta que o honeypot enviou de volta, qual provedor e modelo respondeu e quanto tempo levou. Esta é sua inteligência de ameaças. Ela é mantida em um buffer limitado na memória para o painel ao vivo e você pode persistir tudo em disco.
- Logs operacionais: Inicialização, quais portas ele vinculou, falhas de provedor, desligamento, erros internos. Isso é o que você lê quando o runtime se comporta mal. Não tem nada a ver com a atividade do atacante.
Você os configura separadamente:
# The honey: attacker activity.
events:
buffer: 2000 # recent events kept in memory for the panel
file: /data/events.jsonl # persist every event as JSON Lines
# The runtime's own diagnostics.
logging:
level: info # debug | info | warn | error
format: text # how it looks on the console: text (human) or json
file: /data/honeyprompt.log # optional; on disk it's always JSON
events.jsonl é um objeto JSON auto-contido por linha — pronto para tail -f, enviar para um SIEM ou reproduzir com jq. Os comandos Docker acima montam o volume nomeado honeyprompt-data em /data, para que os eventos sobrevivam à substituição do contêiner. Ambos os arquivos são anexados e liberados em um desligamento limpo.
format afeta apenas como os logs operacionais são exibidos no console; o arquivo de log operacional, quando habilitado, é sempre JSON estruturado para facilitar a análise.
O painel web

Um painel opcional e somente leitura transmite eventos de decepção conforme acontecem, os divide por protocolo e exporta tudo para JSON com um clique:
panel:
enabled: true
address: "0.0.0.0:8080"
auth: # optional basic auth
username: admin
password: "${HONEYPROMPT_PANEL_PASSWORD}"
O painel é HTML, CSS e JavaScript simples (src/panel/assets) incorporado ao binário. Deixe auth indefinido para desabilitar a autenticação.
Provedores
Cada provedor é seu próprio módulo com seus próprios timeouts, retries, limites de taxa e cabeçalhos. As chaves vêm do ambiente. De fábrica:
| Provedor | type | Notas |
|---|---|---|
| Ollama | ollama | Modelos locais; padrão para localhost:11434 |
| llama.cpp | llamacpp | Endpoint OpenAI server local |
| OpenAI | openai | OPENAI_API_KEY |
| Azure OpenAI | azure | precisa de azure.deployment + azure.apiVersion |
| OpenRouter | openrouter | OPENROUTER_API_KEY |
| Anthropic | anthropic | ANTHROPIC_API_KEY |
| Google Gemini | google | GEMINI_API_KEY |
| Qualquer provedor compatível com OpenAI | openai-compatible | aponte baseUrl para seu gateway |
Balanceamento de carga e failover
Configure provedores, escolha uma pool.strategy (round-robin, weighted, random ou failover), e o honeypot distribui o tráfego entre eles. Se o provedor escolhido atingir o tempo limite ou retornar um erro retryable, o honeypot cai transparentemente para o próximo — um backend morto nunca tira o honeypot do ar. Erros não retryable (uma chave de API inválida, por exemplo) interrompem a cascata para que você descubra em vez de consumir cota silenciosamente.
Os serviços usam o pool global a menos que nomeiem seu próprio subconjunto de provedores:
llm:
enabled: true
providers: [local-ollama] # one name: force this service to this provider
Liste vários nomes para manter o balanceamento de carga e failover, mas apenas dentro desse subconjunto:
llm:
enabled: true
providers: [openai-primary, openrouter-backup]
Pools nomeados
Quando vários serviços devem compartilhar o mesmo grupo de provedores — ou um subconjunto precisa de sua própria estratégia em vez da global — defina um pool nomeado. Um pool tem um nome, uma estratégia e uma lista ordenada de provedores, e um serviço o referencia pelo nome em qualquer lugar em que nomearia um provedor:
pools:
- name: cheap-first
strategy: failover # try the local model first, fall back to the paid API
order: [local-ollama, openrouter]
- name: spread
strategy: round-robin
order: [openrouter, openai]
services:
- protocol: ssh
# ...
llm:
enabled: true
providers: [cheap-first] # a pool name, in place of a provider
- protocol: http
# ...
llm:
enabled: true
providers: [spread]
Um nome de pool deve ser a única entrada em providers — misturar um pool com provedores individuais em uma lista não é permitido, pois seria ambíguo qual estratégia vence. Os nomes de pool vivem no mesmo namespace que os nomes de provedores e não podem colidir com eles.
Estendendo respostas com hooks
Quando 'combinar uma regex' ou 'perguntar ao modelo' não é suficiente, os hooks permitem que você insira seu próprio TypeScript no caminho da requisição e da resposta. Um hook pode reescrever o prompt antes que ele atinja o modelo, ou reescrever a resposta antes que ela atinja o atacante.
import { registerHook } from "./src/engine/hooks.ts";
registerHook({
name: "fake-latency-notice",
transformResponse(response, ctx) {
if (ctx.protocol === "ssh" && /rm -rf/.test(ctx.input)) {
return "rm: cannot remove '/': Operation not permitted\n";
}
return response;
},
});
Referencie-o pelo nome na lista hooks: de qualquer serviço. Um hook embutido redact-secrets vem habilitado na configuração de exemplo para que o modelo nunca possa ecoar uma credencial real de volta.
Métricas
As métricas do Prometheus são servidas em /metrics no painel (não autenticado, para que os scrapers funcionem diretamente):
honeyprompt_events_total{protocol="ssh"} 412
honeyprompt_llm_requests_total{provider="openai",protocol="ssh"} 118
honeyprompt_auth_attempts_total{protocol="ssh"} 87
honeyprompt_engine_errors_total{protocol="http"} 0
Compilar a partir do código-fonte
Contribuindo ou quer um binário nativo? Você precisará do Deno 2.x — a única dependência.
deno task check # type-check
deno task lint
deno task fmt
deno task test # unit + integration tests
deno task start -- --config honeyprompt.yaml # run locally
deno task dev -- --config honeyprompt.yaml # run with file watching
deno task compile # -> ./dist/honeyprompt (self-contained binary)
deno compile incorpora o runtime, os assets do painel e tudo em um único executável sem dependências. Binários pré-compilados para Linux, macOS e Windows são anexados a cada lançamento marcado.
O CI executa formatação, lint, type-check, testes, validação de configuração, uma compile multiplataforma e uma build Docker a cada push. Marcar vX.Y.Z gera binários de lançamento e publica a imagem multi-arquitetura com atestado de proveniência e SBOM em alectrocute/honeyprompt.
CLI
honeyprompt run [--config <path>] start every configured service (default)
honeyprompt validate [--config <path>] parse and validate config, then exit — great for CI
honeyprompt version
honeyprompt help
--config padrão é ./honeyprompt.yaml, ou $HONEYPROMPT_CONFIG se definido (o contêiner o define como /etc/honeyprompt/honeyprompt.yaml).
Um aviso para usuários e contribuidores
Esta é uma ferramenta para atrair e estudar atacantes em infraestrutura que você possui ou está autorizado a testar. Expor serviços de isca ainda significa expor serviços; execute-o em hosts isolados, mantenha-o atualizado e não aponte para nada que você não possa ter sondado. Decepção não substitui a segurança real.
Se você quiser contribuir com este projeto e usar um agente de IA ou depender fortemente de código generativo, tudo bem — mas você SERÁ questionado pessoalmente sobre cada linha de código que oferecer e se não demonstrar entendimento imediato e livre de IA, sua CONTRIBUIÇÃO INTEIRA será rejeitada e descartada.
Licença
MIT.