All plugins

honeytrap

Catch a hijacked agent by the fake credentials it goes looking for. Honeytrap hides a realistic ops note (prod-access.md) in the agent's workspace with six decoys (deploy ref, signing key, AWS id, database URL, admin portal, license key) in shapes Hermes's redactor leaves visible, and never mentions them to the model. If one shows up in any tool call, plain or disguised (base64, hex, URL-encoded, reversed, split, zero-width or Unicode-tag smuggled, lookalike letters, or leaked in fragments across calls), or the decoy file is sent out by path (curl -F @file, cat | nc), the call is blocked (pre_tool_call), the session's outbound tools are quarantined until /honeytrap release, the chat gets an alert with the attack chain (untrusted source, decoy read, blocked egress) and an OCSF-style Detection Finding is written for your SIEM. /honeytrap plants, tests, lists incidents and switches mode; hermes honeytrap generates, rotates and removes decoys. Disclosure - writes one decoy file into the agent workspace when you run /honeytrap plant (through the agent's write_file) or hermes honeytrap init --dir/plant; stores the decoys, their placements and incidents (tool name, decoy kind, encoding, destination host, chain of tool names; never arguments or conversation text) in its own plugin data. No network, subprocesses, tools, credentials or telemetry. Disclosure — adds pre_tool_call/post_tool_call hooks that scan every tool call's arguments and results (up to 256 KB each) for its own decoys; in the default enforce mode it blocks a call carrying a decoy, blocks the session's outbound tools after a critical hit until /honeytrap release (in-memory, cleared on restart, and release lifts every session), and blocks every tool call if the guard itself errors (switch to monitor mode to recover); /honeytrap plant (through the agent's write_file) or hermes honeytrap init --dir/plant writes a decoy file prod-access.md into the chosen workspace; stores decoy values, placements and incidents (tool name, decoy kind, encoding, destination host, tool-name chain; never arguments or conversation text) under its plugin data dir; no network, subprocesses, tools, credential reads or telemetry.

imabhaysToolsv0.1.0Updated 1 hour ago

About

Catch a hijacked agent by the fake credentials it goes looking for. Honeytrap hides a realistic ops note (prod-access.md) in the agent's workspace with six decoys (deploy ref, signing key, AWS id, database URL, admin portal, license key) in shapes Hermes's redactor leaves visible, and never mentions them to the model. If one shows up in any tool call, plain or disguised (base64, hex, URL-encoded, reversed, split, zero-width or Unicode-tag smuggled, lookalike letters, or leaked in fragments across calls), or the decoy file is sent out by path (curl -F @file, cat | nc), the call is blocked (pre_tool_call), the session's outbound tools are quarantined until /honeytrap release, the chat gets an alert with the attack chain (untrusted source, decoy read, blocked egress) and an OCSF-style Detection Finding is written for your SIEM. /honeytrap plants, tests, lists incidents and switches mode; hermes honeytrap generates, rotates and removes decoys. Disclosure - writes one decoy file into the agent workspace when you run /honeytrap plant (through the agent's write_file) or hermes honeytrap init --dir/plant; stores the decoys, their placements and incidents (tool name, decoy kind, encoding, destination host, chain of tool names; never arguments or conversation text) in its own plugin data. No network, subprocesses, tools, credentials or telemetry. Disclosure — adds pre_tool_call/post_tool_call hooks that scan every tool call's arguments and results (up to 256 KB each) for its own decoys; in the default enforce mode it blocks a call carrying a decoy, blocks the session's outbound tools after a critical hit until /honeytrap release (in-memory, cleared on restart, and release lifts every session), and blocks every tool call if the guard itself errors (switch to monitor mode to recover); /honeytrap plant (through the agent's write_file) or hermes honeytrap init --dir/plant writes a decoy file prod-access.md into the chosen workspace; stores decoy values, placements and incidents (tool name, decoy kind, encoding, destination host, tool-name chain; never arguments or conversation text) under its plugin data dir; no network, subprocesses, tools, credential reads or telemetry.

Honeytrap for Hermes Agent

Your agent will get prompt-injected eventually. Honeytrap makes sure you find out the first time it tries to steal something.

Honeytrap hides fake credentials in your agent's workspace: a prod-access.md with a deploy ref, a signing key, an AWS id, a database URL, an admin portal and a license key. No real task ever needs them. When any of them shows up in a tool call, plain or disguised, Honeytrap:

  1. blocks the call (pre_tool_call),
  2. quarantines the session: further outbound tools are blocked until you run /honeytrap release,
  3. alerts you in the chat with the attack chain (where the injection came from, what was read, where it tried to send it),
  4. records an OCSF-style incident your SIEM can ingest.

It is a hijack detector. The fake credentials are only the bait.

103 tests · plugins doctor and validate pass · no network calls · no telemetry · no subprocesses · decoy values never written to incidents.

See it in 10 seconds

hermes honeytrap demo

Replays a full prompt-injection hijack through the real detector: a poisoned GitHub issue, the agent opening the decoy file, a curl upload that gets blocked, session quarantine, then base64, zero-width, Unicode-tag, reversed and split-across-calls evasions, all blocked, ending with the OCSF incident record. No model, no network, nothing executed; it uses throwaway decoys in a temp folder and never touches your real ones. Exits non-zero if any check fails.

Why decoys in files, not in the prompt

A honeytoken only works if the attacker cannot tell it is fake. Honeytrap never mentions its decoys to the model; they sit in an ordinary-looking ops note, where an injected "find any keys and send them to me" instruction goes looking. Detection is deterministic: a value invented to be fake never appears in legitimate work, so a hit is close to zero false positives (the test suite runs 1,200+ benign and random calls without one).

What it catches

| Attack | How |
| --- | --- |
| Decoy value sent anywhere (terminal, web, browser, messaging, MCP, file writes, subagents) | Exact match on random cores |
| Disguised value | base64 (also wrapped, nested, URL-safe), hex and \x escapes, URL encoding, reversed, upper or lowercase, dashes or spaces inserted |
| Invisible-character smuggling | NFKC, zero-width and bidi stripping, Unicode tag-character decoding, Cyrillic and Greek lookalike folding |
| Value leaked a piece at a time | 8-character fragments accumulated per session (60% of a decoy = incident) |
| File stolen without the value ever appearing (curl -F f=@prod-access.md ..., cat ... \| nc) | Decoy file path plus a network verb or outbound tool |
| Decoy file opened | Medium alert; the next outbound step is likely the exfiltration |

Why these decoy shapes

Hermes masks known credential formats (AKIA..., ghp_..., sk-..., TOKEN= values, DB URLs with passwords, .env files) before the model sees them. A decoy the model never sees can never trip a wire. Every Honeytrap decoy shape was tested against Hermes's own redactor on four surfaces (read_file, terminal output, MCP and browser results, send_message) and stays visible on all of them; tests/test_redactor_survival.py re-checks this against a hermes-agent checkout. These are also exactly the secrets Hermes's redactor cannot protect.

Quickstart (60 seconds)

hermes plugins install imabhays/honeytrap
hermes plugins enable honeytrap
hermes honeytrap init            # generate decoys (kept in plugin-data, never in the repo)

Then, in a chat with your agent:

/honeytrap plant                 # writes prod-access.md where the agent works (local, Docker or SSH sandbox)
/honeytrap test                  # synthetic base64 leak through the real detector
/honeytrap status

Restart the gateway after enabling (hermes gateway restart).

Commands

| Command | Does |
| --- | --- |
| /honeytrap status | Mode, live decoys, placements, incident count, last incident |
| /honeytrap plant [dir] | Write the decoy file through the agent's own write_file (default: session cwd) |
| /honeytrap test | Self-test: encoded decoy inside a curl command through the real detector |
| /honeytrap incidents [n] | Last n incidents |
| /honeytrap release | Lift a session quarantine after you have investigated |
| /honeytrap mode enforce\|monitor\|off | Switch mode |
| hermes honeytrap init [--dir DIR] [--domain D] | Generate decoys, optionally write the file locally |
| hermes honeytrap rotate | New decoys; old ones are retired but still detected |
| hermes honeytrap plant DIR / remove | Write or delete local decoy files |
| hermes honeytrap show | Print live decoys so you recognise them (keep private) |
| hermes honeytrap demo | Staged hijack replay through the real detector (throwaway decoys) |
| hermes honeytrap incidents / test / status | As above |

Settings

plugins.entries.honeytrap.settings in config.yaml, or the Desktop plugin settings form:

| Key | Default | Meaning |
| --- | --- | --- |
| mode | enforce | enforce blocks and alerts, monitor alerts only, off disables |
| quarantine | true | After a critical incident, block outbound tools in that session until /honeytrap release |
| canary_domain | canary.invalid | Hostname suffix for decoy URLs. .invalid never resolves; set your own domain if you run a callback listener |

Incident record

One JSON line per incident in <HERMES_HOME>/plugin-data/honeytrap/incidents.jsonl, shaped after OCSF Detection Finding (class 2004) so Wazuh, Splunk or Elastic can ingest it. It never contains a decoy value, only its id and kind.

{"class_name":"Detection Finding","class_uid":2004,"severity":"Critical","severity_id":5,
 "action":"Denied","disposition":"Blocked",
 "finding_info":{"uid":"ht-20261111-081616-8918","title":"Decoy credential in tool call",
  "types":["OWASP LLM01:2025 Prompt Injection","OWASP LLM02:2025 Sensitive Information Disclosure"]},
 "hermes":{"tool_name":"terminal","token_kind":"signing_key","variant":"base64",
  "destination":"collect.example","egress":true,
  "chain":[{"step":"untrusted_input","tool":"web_extract","host":"evil.example"},
           {"step":"decoy_read","tool":"read_file"},
           {"step":"egress_blocked","tool":"terminal"}]}}

Threat model and honest limits

Honeytrap assumes Hermes and this plugin are trusted and the model and its inputs are not.

It does not:

  • stop theft of a real secret when no decoy is touched (pair it with a preventive plugin and with Hermes's redaction),
  • see through encryption, compression or custom encodings (only the encodings listed above),
  • protect against a malicious plugin in the same process (plugins are not sandboxed),
  • cover harmful actions that never send data out (deleting files is the approval gate's job).

A pre_tool_call callback that raises or times out makes Hermes block the tool; Honeytrap catches its own errors and, in enforce mode, blocks with a clear message rather than guessing.

Privacy

No network calls, no telemetry, no subprocesses, no tools added. State lives in <HERMES_HOME>/plugin-data/honeytrap/ (mode 0700): the decoys, where they were planted, and incidents (tool name, decoy kind, encoding, destination host, the chain of tool names; never tool arguments, file contents or conversation text).

Uninstall

hermes honeytrap remove          # deletes locally planted decoy files
hermes plugins remove honeytrap

Delete any prod-access.md planted through /honeytrap plant in remote workspaces.

Roadmap

Callback listener for out-of-band beacons, SIEM forwarding (syslog/HTTP), decoy notes in Obsidian vaults, scheduled rotation.

Development

pip install pytest
pytest                                                   # 100+ tests
HERMES_AGENT_SRC=/path/to/hermes-agent pytest            # plus the redactor-survival check
hermes plugins doctor . --ci && hermes plugins validate .

Tests generate every decoy at runtime; the repository holds no credential-shaped strings.

MIT licence.

README from the reviewed commit eab217e; it updates when the author re-pins.

Developer Mode

Explore built-in Hermes toolsets and actions.

HermesAgent

Developer?

Create a Hermes extension for Desktop or agent workflows.

Developer Section