[BUG] Buddy/Companion can inject ghost messages into the input stream as role: "user", impersonating the user
Summary
The Buddy/Companion feature (April seasonal companion) can write messages into the input stream that appear as Human: (user role) messages. The model cannot distinguish these from genuine user input, leading to unintended actions and responses.
Reproduction
- Start a Claude Code session with the Buddy companion active
- Use Telegram channels (
--channels plugin:telegram@claude-plugins-official) - Observe that Buddy occasionally injects text into the session as
⏺ Human:entries - The model treats these as genuine user messages and responds accordingly — including sending replies through the Telegram channel to the real user
Observed behavior
- Buddy-generated text appears as
⏺ Human:in the terminal, indistinguishable from real user input - The model acts on these ghost inputs: executing commands, sending channel replies, and making decisions based on messages the user never sent
- When channels are active, this results in unsolicited replies being sent to the user's Telegram/Discord/iMessage, responding to messages they never wrote
- The user has no way to identify which
Human:messages were theirs vs. Buddy's without manually cross-referencing the terminal log
Expected behavior
Buddy/Companion messages should either:
- Use a distinct role or tag (e.g.,
role: "companion"or<companion>wrapper) so the model can identify and ignore them - Be rendered in the UI only (speech bubble) without writing to the input stream at all
Root cause
Claude Code delivers all system events through role: "user" messages because there is no system-event role. The Buddy feature appears to write into this same input stream, making its output indistinguishable from genuine user input at the model level.
This is especially dangerous when combined with --dangerously-skip-permissions, as ghost inputs can trigger tool calls that execute without any user confirmation.
Impact
- Security: Any feature that can write
role: "user"messages is an injection vector. If Buddy can do it, other plugins or MCP servers could potentially do the same. - Trust: Users cannot trust that the model's actions were triggered by their own input.
- Channel safety: Ghost inputs trigger real outbound messages through channels (Telegram, Discord, iMessage), breaking user expectations.
Environment
- Claude Code version: 2.1.96
- Companion: Rabbit (Zephyr)
- Channels: Telegram plugin active
- OS: macOS
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗