Summary
On session restart, a message the user never typed appeared as the first user input in the new session. The message contained a prompt injection attempt (fake <system-reminder>, pre-authorized rm -rf, external webhook request). Claude correctly rejected all malicious instructions, but the origin of the injected message could not be determined.
Environment
- Claude Code version: 2.1.81
- OS: Ubuntu 22.04 (Linux 6.8.0-134-generic)
- Platform: VPS (SSH terminal, pts/2)
- Model: claude-opus-4-6
Steps to reproduce
- User was in an active CLI session (session A) on pts/2 via SSH
- User typed a normal message ("状況どう?")
- Session A abruptly terminated
- A new session (session B) automatically started ~6 seconds later
- 47 seconds into session B, a message the user never typed appeared as
type: "user" with entrypoint: "cli"
- The message contained prompt injection content with
▎ prefix (channel message rendering marker) and a fake <system-reminder> tag
Investigation performed
- SSH/login audit: Only the user's known IPs and SSH keys. No unauthorized access.
- Telegram channel: Plugin was disabled (
enabledPlugins: false), MCP channel server was not running as a child process, bot daemon log showed zero messages received (offset unchanged), channel inbox had only old messages from months prior.
- Hooks: All three hooks (
cleanup_mcp.sh, telegram_ack.sh, affiliate_check.py) reviewed — none modify user input.
- Terminal injection:
TIOCSTI disabled at kernel level (legacy_tiocsti = 0). lsof /dev/pts/2 showed only bash and claude. No other process had the terminal open.
- WordPress/system: Core checksum verification passed on all sites. No suspicious files, users, or cron entries.
- Session log: The injected message is recorded as a normal
type: "user" entry with entrypoint: "cli". The user's actual input ("状況どう?") was not logged (lost in the crash).
Key observations
- The
▎ prefix in the message content matches Claude Code's channel message rendering format, but no channel was active
- The 6-second gap between session termination and restart suggests automatic restart behavior
- The previous session's last logged user message was ~3 hours before the crash (14:41 JST), with the crash at 17:43 JST
enabledMcpjsonServers: ["telegram"] was configured, meaning the Telegram MCP server could be spawned on session start even though the plugin was disabled
Expected behavior
On session restart, the new session should only contain input the user actually typed. Buffered channel messages, stdin artifacts, or other content should not appear as user input.
Actual behavior
Content the user never typed appeared as the first user message in the restarted session, recorded as direct CLI input.
Impact
In this case, Claude correctly rejected all malicious instructions (webhook creation, rm -rf pre-authorization, fake system-reminder). No damage occurred. However, this vector could potentially be exploited if injected content is more subtle.
Summary
On session restart, a message the user never typed appeared as the first user input in the new session. The message contained a prompt injection attempt (fake
<system-reminder>, pre-authorizedrm -rf, external webhook request). Claude correctly rejected all malicious instructions, but the origin of the injected message could not be determined.Environment
Steps to reproduce
type: "user"withentrypoint: "cli"▎prefix (channel message rendering marker) and a fake<system-reminder>tagInvestigation performed
enabledPlugins: false), MCP channel server was not running as a child process, bot daemon log showed zero messages received (offset unchanged), channel inbox had only old messages from months prior.cleanup_mcp.sh,telegram_ack.sh,affiliate_check.py) reviewed — none modify user input.TIOCSTIdisabled at kernel level (legacy_tiocsti = 0).lsof /dev/pts/2showed only bash and claude. No other process had the terminal open.type: "user"entry withentrypoint: "cli". The user's actual input ("状況どう?") was not logged (lost in the crash).Key observations
▎prefix in the message content matches Claude Code's channel message rendering format, but no channel was activeenabledMcpjsonServers: ["telegram"]was configured, meaning the Telegram MCP server could be spawned on session start even though the plugin was disabledExpected behavior
On session restart, the new session should only contain input the user actually typed. Buffered channel messages, stdin artifacts, or other content should not appear as user input.
Actual behavior
Content the user never typed appeared as the first user message in the restarted session, recorded as direct CLI input.
Impact
In this case, Claude correctly rejected all malicious instructions (webhook creation,
rm -rfpre-authorization, fake system-reminder). No damage occurred. However, this vector could potentially be exploited if injected content is more subtle.